1001Ferramentas
🆔Validadores

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