Algoritmo de validação do CPF: o módulo 11 passo a passo
Como os dois dígitos verificadores do CPF são calculados com módulo 11, com a conta completa de um exemplo e os erros mais comuns.
O CPF tem 11 dígitos, mas só os nove primeiros carregam informação. Os dois últimos são dígitos verificadores: números calculados a partir dos anteriores para detectar erros de digitação. A conta usada é uma variação do módulo 11, a mesma família de algoritmos que aparece em códigos de barras, contas bancárias e no CNPJ. Este guia percorre o cálculo completo com o CPF de exemplo 529.982.247-25 e termina com uma implementação que você pode copiar.
O que é o módulo 11
Módulo é o resto de uma divisão inteira. “Módulo 11” significa que, em algum momento, a conta divide uma soma por 11 e usa apenas o resto, que sempre fica entre 0 e 10. Em JavaScript, Python, Java, C# e PHP, o operador % faz exatamente isso: 295 % 11 é 9.
O esquema de dígito verificador do CPF funciona assim:
- Cada dígito é multiplicado por um peso. Os pesos são decrescentes e terminam sempre em 2.
- Os produtos são somados.
- A soma é dividida por 11 e o resto é guardado.
- Se o resto for menor que 2, o dígito verificador é 0. Caso contrário, é 11 menos o resto.
O passo 4 existe porque 11 menos 0 dá 11 e 11 menos 1 dá 10, valores que não cabem em um único dígito. A regra os converte em 0.
Os pesos decrescentes são o que torna o esquema útil. Uma soma simples dos dígitos não perceberia a troca de dois números vizinhos, como digitar 259 no lugar de 529. Com pesos diferentes em cada posição, a troca muda a soma e, na grande maioria dos casos, o resto. Isso permite apontar o erro antes que o CPF chegue ao banco de dados.
O cálculo é feito duas vezes. A primeira rodada usa os nove primeiros dígitos e produz o décimo. A segunda usa os dez primeiros, incluindo o verificador recém-calculado, e produz o décimo primeiro.
Cálculo do primeiro dígito verificador
Pegue os nove primeiros dígitos de 529.982.247-25, que são 5 2 9 9 8 2 2 4 7, e multiplique cada um por um peso que começa em 10 e desce até 2:
| Posição | Dígito | Peso | Produto |
|---|---|---|---|
| 1 | 5 | 10 | 50 |
| 2 | 2 | 9 | 18 |
| 3 | 9 | 8 | 72 |
| 4 | 9 | 7 | 63 |
| 5 | 8 | 6 | 48 |
| 6 | 2 | 5 | 10 |
| 7 | 2 | 4 | 8 |
| 8 | 4 | 3 | 12 |
| 9 | 7 | 2 | 14 |
| Soma | 295 |
Agora divida 295 por 11. O quociente inteiro é 26 (26 × 11 = 286) e o resto é 295 − 286 = 9. Como 9 não é menor que 2, o dígito é 11 − 9 = 2.
O décimo dígito do CPF de exemplo é justamente 2, então a primeira verificação passa. Se você quiser conferir a conta com outro número, a calculadora de dígitos mostra cada produto, a soma e o resto.
Cálculo do segundo dígito
A segunda rodada repete o processo com dez dígitos: os nove da base mais o 2 que acabamos de calcular. Os pesos agora começam em 11 e continuam descendo até 2.
| Posição | Dígito | Peso | Produto |
|---|---|---|---|
| 1 | 5 | 11 | 55 |
| 2 | 2 | 10 | 20 |
| 3 | 9 | 9 | 81 |
| 4 | 9 | 8 | 72 |
| 5 | 8 | 7 | 56 |
| 6 | 2 | 6 | 12 |
| 7 | 2 | 5 | 10 |
| 8 | 4 | 4 | 16 |
| 9 | 7 | 3 | 21 |
| 10 | 2 | 2 | 4 |
| Soma | 347 |
Dividindo 347 por 11, o quociente é 31 (31 × 11 = 341) e o resto é 6. O dígito é 11 − 6 = 5, que é o último dígito de 529.982.247-25. As duas verificações passam e o CPF é válido.
Repare no que acontece com 529.982.247-26. A primeira rodada é idêntica e o décimo dígito, 2, confere. A segunda rodada produz 5, mas o número informado termina em 6. O CPF é inválido, e o problema está especificamente no segundo verificador.
Um detalhe que costuma confundir: o resto 0 também leva ao dígito 0. Com a base 529.982.248, por exemplo, a primeira soma é 297, que é múltiplo exato de 11. O resto é 0 e o primeiro verificador vira 0, o que dá o CPF 529.982.248-06.
Implementação de referência
O código abaixo é a versão em JavaScript da implementação usada pelas ferramentas deste site. Ele separa três responsabilidades: limpar a entrada, calcular os dígitos e decidir se o CPF é válido. A função analisarCpf devolve também o motivo da recusa, útil para mensagens de erro.
function limparCpf(valor) {
return String(valor ?? '').replace(/\D/g, '');
}
function calcularDigito(digitos, pesoInicial) {
let soma = 0;
for (let i = 0; i < digitos.length; i++) {
soma += Number(digitos[i]) * (pesoInicial - i);
}
const resto = soma % 11;
return resto < 2 ? 0 : 11 - resto;
}
function calcularDigitos(nove) {
const base = limparCpf(nove);
if (base.length !== 9) throw new Error('calcularDigitos exige exatamente 9 dígitos');
const dv1 = calcularDigito(base, 10);
const dv2 = calcularDigito(base + String(dv1), 11);
return { dv1, dv2 };
}
const REPETIDO = /^(\d)\1{10}$/;
function analisarCpf(valor) {
const bruto = String(valor ?? '');
const semPontuacao = bruto.replace(/[.\-\s]/g, '');
const limpo = limparCpf(bruto);
if (semPontuacao.length > 0 && /\D/.test(semPontuacao)) return { valido: false, limpo, motivo: 'caracteres' };
if (limpo.length !== 11) return { valido: false, limpo, motivo: 'tamanho' };
if (REPETIDO.test(limpo)) return { valido: false, limpo, motivo: 'repetido' };
const { dv1, dv2 } = calcularDigitos(limpo.slice(0, 9));
if (Number(limpo[9]) !== dv1) return { valido: false, limpo, motivo: 'dv1', esperado: { dv1, dv2 } };
if (Number(limpo[10]) !== dv2) return { valido: false, limpo, motivo: 'dv2', esperado: { dv1, dv2 } };
return { valido: true, limpo };
}
function validarCpf(valor) {
return analisarCpf(valor).valido;
}
validarCpf('529.982.247-25'); // true
analisarCpf('111.111.111-11'); // { valido: false, motivo: 'repetido', ... }
analisarCpf('529.982.247-26'); // { valido: false, motivo: 'dv2', esperado: { dv1: 2, dv2: 5 } }Algumas decisões merecem explicação:
- Pontos, hífen e espaços são separadores aceitos, mas qualquer outro caractere invalida a entrada. Assim, “529.982.247-25” passa, enquanto “529a982247-25” é recusado com o motivo
caracteresem vez de ter a letra descartada em silêncio. - O tamanho é conferido depois da limpeza. Isso aceita o CPF com ou sem máscara e recusa qualquer coisa que não tenha exatamente 11 dígitos.
- A sequência repetida é checada antes da conta, pelo motivo explicado na próxima seção.
- A função compara os verificadores calculados com os informados, sem montar o CPF de novo. Isso permite dizer qual dos dois falhou.
Versões equivalentes em outras linguagens estão em TypeScript, Python, PHP, Java e C#.
Por que 111.111.111-11 é rejeitado
Faça a conta para 111.111.111-11. Na primeira rodada, todos os dígitos são 1, então a soma é a soma dos pesos: 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 = 54. O resto de 54 por 11 é 10, e o dígito é 11 − 10 = 1. Na segunda rodada, a soma é 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 = 65, o resto é 10 e o dígito, de novo, é 1.
Ou seja, a matemática fecha: 111.111.111-11 passa no módulo 11. O mesmo acontece com as outras sequências de dígitos repetidos, de 000.000.000-00 a 999.999.999-99. Por convenção, essas sequências não são consideradas válidas, e todo validador sério as recusa explicitamente. O motivo prático é que elas são o valor de preenchimento mais comum em formulários: quem quer pular um campo obrigatório digita o mesmo número onze vezes.
Por isso a checagem ^(\d)\1{10}$ vem antes do cálculo. A expressão captura o primeiro dígito e exige que ele se repita mais dez vezes. Se casar, o CPF é recusado sem fazer conta nenhuma.
Erros comuns
A maioria dos validadores quebrados que aparecem em projetos reais tem um destes quatro problemas.
Esquecer a regra do resto menor que 2. Uma implementação que faz só 11 - resto devolve 10 ou 11 quando o resto é 1 ou 0. Comparado com um único dígito, esse valor nunca bate, e o validador passa a recusar CPFs legítimos, como 529.982.248-06, cujo primeiro verificador vem de um resto 0. Algumas variantes calculam (soma * 10) % 11 e depois transformam 10 em 0, o que dá o mesmo resultado; o erro é omitir essa última transformação.
Usar parseInt sem base ou sobre a string inteira. Em motores JavaScript antigos, parseInt sem o segundo argumento podia interpretar uma string com zero à esquerda como octal. Hoje o comportamento é decimal, mas parseInt continua tolerante demais: parseInt('529.982') devolve 529 e ignora o resto sem erro. Para converter um único caractere, prefira Number(digito); para a entrada inteira, valide com expressão regular em vez de converter.
Não limpar a pontuação. Se a função recebe “529.982.247-25” e percorre a string como se fossem 11 dígitos, os pontos entram na conta como NaN e o resultado é sempre inválido. A limpeza precisa acontecer antes de qualquer cálculo, e a checagem de tamanho, depois dela.
Aceitar 10 dígitos e completar com zero. Quando um CPF começa com zero e passa por uma coluna numérica, o zero se perde e sobram 10 dígitos. Completar com padStart(11, '0') faz sentido ao migrar dados de uma coluna que você sabe que era numérica. Fazer isso com a entrada do usuário, porém, aceita como válido um número que a pessoa digitou incompleto. Na entrada, 10 dígitos devem ser recusados com o motivo tamanho. O guia erros comuns ao validar CPF traz esses e outros casos, com uma tabela de testes para conferir o seu validador.
Para testar uma implementação rapidamente, use três casos: 529.982.247-25 deve ser válido, 111.111.111-11 deve ser inválido por repetição e 529.982.247-26 deve ser inválido no segundo dígito. O validador de CPF mostra o motivo de cada recusa, e o gerador de CPF produz números válidos para testes. Esses números podem coincidir com um CPF real por acaso, então use-os apenas em ambientes de teste.
Perguntas frequentes
Por que o resto 0 e o resto 1 viram dígito 0?
Porque 11 menos 0 dá 11 e 11 menos 1 dá 10, e nenhum dos dois cabe em uma única posição decimal. A regra do CPF define que, quando o resto da divisão por 11 é menor que 2, o dígito verificador é 0.
O segundo dígito usa o primeiro dígito verificador no cálculo?
Sim. O segundo dígito é calculado sobre os dez primeiros dígitos, ou seja, os nove da base mais o primeiro verificador, com pesos de 11 a 2.
Se os dígitos verificadores conferem, o CPF existe?
Não necessariamente. O módulo 11 só garante que o número é estruturalmente possível. Saber se ele foi emitido e a quem pertence depende de consulta à Receita Federal ou a serviços autorizados.