Fastway
Voltar ao blog

Como Funcionam os Dígitos Verificadores do CPF e do CNPJ (Com o Algoritmo)

Rodrigo Krohling
·9 min de leitura

Todo CPF termina em dois dígitos que não são escolhidos — eles são calculados a partir dos nove anteriores. O mesmo vale para os dois últimos do CNPJ, calculados a partir dos doze anteriores. É isso que torna possível rejeitar um número digitado errado num formulário sem perguntar a nenhuma API do governo se ele existe.

Este post percorre a aritmética à mão e depois transforma tudo em código. Se você só quer a resposta para um número, o validador faz isso ao vivo enquanto você digita.

Para que serve um dígito verificador

Dígitos verificadores existem para pegar erro humano, não fraude. Eles são projetados para que os dois erros de transcrição mais comuns — trocar um dígito e inverter dois dígitos vizinhos — produzam um número que falha na checagem.

Eles não dizem que um documento foi emitido. Um número que passa é estruturalmente válido; se pertence a uma pessoa real é uma pergunta completamente diferente, que só a Receita Federal responde. Essa distinção é importante o suficiente para repetir: passar na checagem significa que os dígitos são internamente consistentes, e nada além disso.

CPF, passo a passo

Pegue os nove primeiros dígitos e calcule o décimo.

Use 123.456.789-XX. Os nove primeiros são 1 2 3 4 5 6 7 8 9.

Passo 1 — multiplique cada dígito por um peso decrescente começando em 10.

dígito  1   2   3   4   5   6   7   8   9
peso   10   9   8   7   6   5   4   3   2
prod   10  18  24  28  30  30  28  24  18

Passo 2 — some os produtos.

10 + 18 + 24 + 28 + 30 + 30 + 28 + 24 + 18 = 210

Passo 3 — multiplique por 10 e tire o resto da divisão por 11.

210 * 10 = 2100
2100 mod 11 = 10

Passo 4 — se o resultado for 10 ou 11, o dígito é 0. Caso contrário é o próprio resultado. Aqui deu 10, então o primeiro dígito verificador é 0.

Agora o décimo primeiro dígito, calculado a partir dos dez primeiros (incluindo o que acabamos de achar). Desta vez os pesos começam em 11:

dígito  1   2   3   4   5   6   7   8   9   0
peso   11  10   9   8   7   6   5   4   3   2
prod   11  20  27  32  35  36  35  32  27   0
soma = 255
255 * 10 = 2550
2550 mod 11 = 3

O segundo dígito verificador é 3. O número completo é 123.456.789-03.

O * 10 e o mod 11 parecem arbitrários. Eles são o mecanismo: multiplicar por 10 antes de tirar o resto é o que garante que alterar qualquer dígito muda o resultado, e os pesos decrescentes são o que faz a troca de dois dígitos vizinhos mudar a soma.

CPF em código

function isValidCpf(input) {
  const digits = input.replace(/\D/g, '');
  if (digits.length !== 11) return false;

  // Sequências de dígitos iguais satisfazem a aritmética mas nunca são emitidas.
  if (/^(\d)\1{10}$/.test(digits)) return false;

  const checkDigit = (upTo) => {
    let sum = 0;
    for (let i = 0; i < upTo; i++) {
      sum += Number(digits[i]) * (upTo + 1 - i);
    }
    const result = (sum * 10) % 11;
    return result === 10 || result === 11 ? 0 : result;
  };

  return checkDigit(9) === Number(digits[9])
      && checkDigit(10) === Number(digits[10]);
}

Aquela cláusula de guarda para dígitos repetidos não é opcional. 111.111.111-11 passa perfeitamente na aritmética mod-11 — os pesos e a soma fecham — e não é um CPF válido. Toda implementação ingênua aceita, e esse é de longe o bug mais comum em validadores caseiros.

CNPJ: mesma ideia, pesos diferentes

O CNPJ tem 14 caracteres: doze de conteúdo e dois verificadores. A sequência de pesos não é uma contagem decrescente simples — ela cicla de 2 a 9 e reinicia.

Para o primeiro dígito, aplicado aos doze caracteres de conteúdo, leia da direita para a esquerda com os pesos 2,3,4,5,6,7,8,9,2,3,4,5. Para o segundo, aplicado a treze caracteres, o mesmo ciclo estendido em um.

A regra do resto difere um pouco da do CPF: calcule soma mod 11, e o dígito é 0 se o resto for menor que 2, senão 11 - resto.

O CNPJ alfanumérico de 2026

A partir de 2026 o CNPJ aceita letras nas doze primeiras posições. Isso quebra todo validador construído sobre uma regex só de dígitos — e quebra em silêncio: registros novos simplesmente passam a ser rejeitados como malformados.

A correção é menor do que parece. A rotina do dígito verificador mantém exatamente o mesmo formato; só muda o valor de cada caractere. Em vez de Number(char), cada caractere contribui com seu código ASCII menos 48:

  • '0' tem código 48, então contribui com 0. '9' tem código 57, contribuindo com 9. Os dígitos mantêm exatamente o peso que sempre tiveram.
  • 'A' tem código 65, contribuindo com 17. 'Z' tem código 90, contribuindo com 42.

Os dois dígitos verificadores continuam numéricos.

function cnpjCharValue(char) {
  return char.toUpperCase().charCodeAt(0) - 48;
}

function cnpjCheckDigit(chars) {
  let weight = 2;
  let sum = 0;
  for (let i = chars.length - 1; i >= 0; i--) {
    sum += cnpjCharValue(chars[i]) * weight;
    weight = weight === 9 ? 2 : weight + 1;
  }
  const remainder = sum % 11;
  return remainder < 2 ? 0 : 11 - remainder;
}

function isValidCnpj(input) {
  const clean = input.replace(/[^0-9A-Za-z]/g, '').toUpperCase();
  if (clean.length !== 14) return false;
  if (/^(.)\1{13}$/.test(clean)) return false;

  const body = clean.slice(0, 12);
  const d1 = cnpjCheckDigit(body);
  const d2 = cnpjCheckDigit(body + d1);

  return `${d1}${d2}` === clean.slice(12);
}

Como os dígitos mapeiam para si mesmos sob charCodeAt - 48, esta implementação valida CNPJs antigos totalmente numéricos e os novos alfanuméricos pelo mesmo caminho. Não há ramificação, nem feature flag, nem data de migração para tratar.

Três observações de implementação que valem a pena

Remova a pontuação antes de validar e armazene só os caracteres. A máscara é apresentação. Rejeitar um número sem formatação e aceitar um bem formatado porém inválido são as duas metades do mesmo erro.

Não valide a cada tecla sem máscara. Quem digita um CPF fica inválido nos dez primeiros toques. Mostre o resultado quando o campo estiver completo ou no blur, não enquanto a pessoa digita — senão o formulário reclama durante todo o preenchimento.

Nunca gere um número de documento realista fora de um fixture de teste. Se precisar de um para testar formulário, um gerador feito para isso produz números estruturalmente válidos que não pertencem a ninguém. Usá-los para qualquer coisa além de teste é fraude — e a aritmética acima é exatamente o motivo de esses números parecerem convincentes o bastante para isso ser uma tentação real.

O esquema inteiro é cerca de cem linhas de aritmética protegendo milhões de formulários contra erro de digitação. Vale entender em vez de copiar, porque são as cópias que aceitam 111.111.111-11.