Detector e Validador de CPF/CNPJ
Detecta automaticamente se uma string é CPF (11 dígitos) ou CNPJ (14 dígitos) e valida o dígito verificador correspondente.
Detectar CPF ou CNPJ em campo único: o padrão moderno de formulários brasileiros
Forçar o usuário a escolher "CPF ou CNPJ" em um radio button antes de digitar é fricção desnecessária. O padrão moderno — adotado por Stripe BR Checkout, Mercado Pago, RD Station, Hotmart e a maioria dos SaaS brasileiros — é expor um campo único rotulado "CPF ou CNPJ" que detecta automaticamente o tipo do documento a partir do que o usuário digita.
A técnica explora uma diferença estrutural sólida: CPF tem 11 dígitos, CNPJ tem 14 dígitos. Remova tudo que não for número, conte os dígitos e roteie para o algoritmo correto. Ambos compartilham a família módulo 11, mas com pesos e tamanhos diferentes — então a detecção precisa acontecer antes da validação.
Rotina de detecção de referência
function detectarDoc(raw) {
const dig = String(raw).replace(/\D/g, '')
if (dig.length === 11) return { tipo: 'CPF', valor: dig }
if (dig.length === 14) return { tipo: 'CNPJ', valor: dig }
return { tipo: 'DESCONHECIDO', valor: dig }
}
A mesma rotina deve rodar em todo evento oninput para a UI já trocar a máscara dinâmica de XXX.XXX.XXX-XX (CPF) para XX.XXX.XXX/XXXX-XX (CNPJ) assim que o 11º ou 14º dígito chegar. Bibliotecas que implementam bem: imask.js (vanilla), react-input-mask e vue-the-mask. Em React Hook Form, dá pra montar um resolver Zod que ramifica por comprimento.
Comprimento + formato: detecção bem feita
Comprimento sozinho funciona, desde que a máscara seja removida antes. Um value.length ingênuo em "123.456.789-09" devolve 14 (comprimento de um CNPJ cru) e quebra a detecção. Normalize sempre primeiro:
- Tire
.,-,/, espaços e whitespace Unicode. - Rejeite caracteres que não sejam dígitos (ou o alfabeto do CNPJ alfanumérico).
- Ramifique pelo comprimento: 11 -> CPF, 14 -> CNPJ, qualquer outro valor -> dica "incompleto".
- Rode o algoritmo de DV apenas depois que o comprimento bater.
CNPJ alfanumérico (julho/2026): pegadinha de detecção
A partir de julho de 2026, a Receita Federal emite CNPJs alfanuméricos: as 12 primeiras posições aceitam letras A-Z e dígitos 0-9, as duas últimas continuam sendo DVs numéricos calculados pela mesma fórmula módulo 11 com o valor ASCII de cada caractere. Sua rotina de auto-detect precisa aceitar os dois formatos:
- Normalize letras para maiúsculas antes de validar.
- Permita A-Z 0-9 nas 12 primeiras posições de um input de 14 chars; rejeite minúsculas e não-ASCII silenciosamente.
- CPF segue puramente numérico — qualquer letra em um input de 11 chars é sinal forte de typo.
- Máscara fica igual
XX.XXX.XXX/XXXX-XX, apenas com letras permitidas nos 12 primeiros slots.
Anti-padrões a evitar
- Dois campos separados: confunde MEIs que têm os dois números e derruba a conversão em 5-12 por cento em testes A/B.
- Regex de formato sem normalização de comprimento: bate no tamanho mascarado e conta dígitos errado.
- Validar sem discriminar o tipo: um
validate(doc)que tenta CPF e depois CNPJ vaza a informação pelo tempo de resposta e pelas mensagens — péssimo para UX e auditoria. - Confiar só no client-side: revalide sempre no servidor. Qualquer usuário pode burlar checagem no browser.
Union discriminada em TypeScript
type Doc =
| { tipo: 'CPF'; valor: string }
| { tipo: 'CNPJ'; valor: string }
| { tipo: 'INVALIDO'; motivo: string }
function parseDoc(raw: string): Doc { /* ... */ }
Unions discriminadas deixam o compilador estreitar código a jusante (emitir nota, chamar APIs da RFB, escolher buckets de rate-limit) sem cast inseguro. Combine com o pacote cpf-cnpj-validator do npm, que expõe cpf.isValid, cnpj.isValid, cpf.format e cnpj.format — todos trabalham em dígitos crus.
FAQ
Posso detectar o tipo só pelo comprimento?
Sim. Após remover não-dígitos, 11 significa CPF e 14 significa CNPJ. Nenhum outro documento brasileiro compartilha esses comprimentos, então a heurística é inequívoca.
Como detectar o novo CNPJ alfanumérico?
Permita letras A-Z nas posições 1-12 de qualquer input de 14 caracteres. A presença de qualquer letra já é sinal forte de CNPJ, já que CPF segue numérico.
Existe biblioteca JS testada de produção?
Sim: cpf-cnpj-validator (npm, ~250 mil downloads/semana). Cuida de formatação, strip e cálculo de DV. No backend, brazilian-values em Go e brutils em PHP são equivalentes.
E se o usuário colar com caracteres extras?
Normalize antes de validar: retire pontos, barras, hífens e whitespace, depois conte os dígitos. Tire emojis e espaços zero-width também — eles entram em colagens de apps de clipboard.
Devo validar no client-side ou server-side?
Os dois. Validação no browser dá feedback instantâneo e reduz submissões ruins. Validação no servidor é a única em que você pode confiar para regra de negócio, antifraude e persistência.
Ferramentas Relacionadas
Validador de CNPJ
Valide CNPJs instantaneamente pelo algoritmo oficial da Receita Federal, sem enviar dados para nenhum servidor. Gratuito e sem cadastro.
Validador de CGC (CNPJ antigo)
Valida o formato e dígito verificador do CGC (Cadastro Geral de Contribuintes) — antigo formato do CNPJ. Mesmas regras matemáticas.
Validador de CPF
Valide CPFs instantaneamente pelo algoritmo oficial da Receita Federal, sem enviar dados para nenhum servidor. Gratuito e sem cadastro.