Buscar

Validar CPF: o cálculo e o código em Python e JS

Como validar CPF pelo módulo 11, com código testado em Python e JavaScript, regex de formato, o novo CNPJ alfanumérico e o algoritmo de Luhn.

Gabriel Pedroso11 min de leitura
validação de cpf com dígitos verificadores e código

Um formulário de cadastro aceita 111.111.111-11, o número entra no banco e ninguém repara até aparecerem dezenas de cadastros com ele. O campo tinha máscara, regex e cálculo do dígito verificador. Faltava a regra da sequência repetida.

Quem precisa validar CPF num sistema próprio costuma copiar uma função pronta sem testar esse caso. Este guia mostra o cálculo do módulo 11, o código testado em Python e JavaScript e a regex de formato. No fim, entram CNPJ e cartão.

Validar CPF confere a matemática do número e não diz nada sobre a pessoa por trás dele. A regex, sozinha, confere só o desenho dos caracteres.

1Limpartira ponto, traço e espaço
2Formato11 dígitos e não repetidos
31º dígitopesos de 10 a 2, módulo 11
42º dígitopesos de 11 a 2, módulo 11
5Compararbate com os dois últimos dígitos
A ordem importa: a limpeza e a checagem de formato vêm antes de qualquer conta, e a comparação final usa os dois dígitos calculados.

Como o CPF é montado

O CPF tem 11 dígitos. Os nove primeiros são a base, e os dois últimos são dígitos verificadores, calculados a partir dessa base. Com máscara, ele fica no formato 000.000.000-00.

O dígito verificador existe para pegar erro de digitação. Se alguém troca um dígito ou inverte dois vizinhos, a conta quase sempre deixa de fechar. Ele não protege nada: qualquer pessoa que conhece a fórmula gera um número que passa.

O exemplo deste post é 123.456.789-09, gerado pela própria conta a partir da base 123456789.

O cálculo para validar CPF, passo a passo

O método é o módulo 11, aplicado duas vezes. A primeira rodada gera o primeiro dígito verificador. A segunda usa a base mais esse dígito e gera o segundo.

Primeiro dígito verificador

Multiplique cada dígito da base por um peso que vai de 10 a 2. Depois some tudo.

1×10 + 2×9 + 3×8 + 4×7 + 5×6 + 6×5 + 7×4 + 8×3 + 9×2 = 210.

Divida a soma por 11 e fique com o resto. 210 dividido por 11 dá 19, com resto 1. A regra é esta: se o resto for menor que 2, o dígito é 0; nos outros casos, o dígito é 11 menos o resto. Com resto 1, o primeiro verificador é 0.

Segundo dígito verificador

Agora a sequência tem dez dígitos, com o 0 no fim. Os pesos vão de 11 a 2.

1×11 + 2×10 + 3×9 + 4×8 + 5×7 + 6×6 + 7×5 + 8×4 + 9×3 + 0×2 = 255.

O resto de 255 por 11 é 2, porque 11 vezes 23 dá 253. Como 2 não é menor que 2, o dígito é 11 menos 2, ou seja, 9. O CPF completo fica 123.456.789-09.

Para validar CPF digitado pelo usuário, você refaz as duas contas sobre os nove primeiros dígitos e compara com os dois últimos. Se bater, o número é matematicamente válido.

A armadilha da sequência repetida

O número 111.111.111-11 passa nas duas contas. O mesmo vale para as outras sequências de um dígito só: rodei as dez no código e todas fecharam. A função precisa rejeitar esses números antes da conta, porque eles aparecem quando alguém quer pular o campo.

O código em Python e em JavaScript

As duas funções abaixo seguem o diagrama para validar CPF. Elas limpam a entrada, conferem o tamanho, rejeitam a sequência repetida e calculam os dois dígitos. Para quem começa em Python, a versão com zip e range é a mais curta.

import re

def validar_cpf(valor: str) -> bool:
    digitos = re.sub(r"[^0-9]", "", valor)
    if len(digitos) != 11:
        return False
    if digitos == digitos[0] * 11:
        return False
    numeros = [int(d) for d in digitos]
    for posicao in (9, 10):
        pesos = range(posicao + 1, 1, -1)
        soma = sum(n * p for n, p in zip(numeros[:posicao], pesos))
        resto = soma % 11
        dv = 0 if resto < 2 else 11 - resto
        if numeros[posicao] != dv:
            return False
    return True

A limpeza usa [^0-9] em vez de \D porque, em Python, \d também reconhece dígitos de outros alfabetos.

Estes são os testes que rodei com python3:

casos = {
    "123.456.789-09": True,
    "12345678909": True,
    "123.456.789-08": False,
    "111.111.111-11": False,
    "000.000.000-00": False,
    "123.456.789": False,
    "": False,
}
for cpf, esperado in casos.items():
    assert validar_cpf(cpf) == esperado, cpf
print("todos os casos passaram")

A versão em JavaScript roda igual no navegador e no Node.js:

function validarCpf(valor) {
  const digitos = String(valor).replace(/\D/g, "");
  if (digitos.length !== 11) return false;
  if (/^(\d)\1{10}$/.test(digitos)) return false;
  const numeros = [...digitos].map(Number);
  for (const posicao of [9, 10]) {
    let soma = 0;
    for (let i = 0; i < posicao; i++) {
      soma += numeros[i] * (posicao + 1 - i);
    }
    const resto = soma % 11;
    const dv = resto < 2 ? 0 : 11 - resto;
    if (numeros[posicao] !== dv) return false;
  }
  return true;
}

Os mesmos sete casos, rodados com node, deram o mesmo resultado.

Como as duas funções removem tudo o que não é dígito, elas aceitam lixo como 123abc456.789-09. A regex da próxima seção recusa esse tipo de entrada.

Regex para o formato, com e sem máscara

A expressão mais comum deixa cada separador opcional:

const FORMATO_CPF = /^\d{3}\.?\d{3}\.?\d{3}-?\d{2}$/;

Ela recusa 12.3456.789-09 e 123-456-789.09, que têm a pontuação no lugar errado. Mas aceita 123456.789-09, porque cada ponto é opcional por conta própria. Se você quer exigir a máscara inteira ou nenhuma máscara, use a alternância ^(\d{3}\.\d{3}\.\d{3}-\d{2}|\d{11})$, que testei com os mesmos casos.

Nenhuma das duas faz conta. As duas aceitam 123.456.789-08, que tem o desenho certo e o dígito errado, e aceitam 111.111.111-11.

A regex dá retorno rápido ao usuário enquanto ele digita, e a função de dígito verificador decide antes de gravar. Para validar CPF com segurança, as duas rodam também no servidor. Qualquer pessoa consegue chamar a sua API direto, sem passar pelo navegador.

CNPJ alfanumérico e cartão de crédito

O CNPJ tem 14 caracteres: 8 de raiz, 4 de ordem e 2 verificadores. Os pesos vão de 5 a 2 e depois de 9 a 2; no segundo dígito, a sequência ganha um 6 na frente.

A mudança está no formato. A Instrução Normativa RFB nº 2.229, publicada em 15 de outubro de 2024, permite letras no CNPJ, segundo a nota do Serpro. As 12 primeiras posições podem ter letras maiúsculas ou números, e os dois verificadores continuam numéricos. O perguntas e respostas da Receita Federal diz que os primeiros números alfanuméricos entram em produção a partir de julho de 2026. Os CNPJs atuais continuam válidos.

Para o cálculo, cada caractere vira o seu código ASCII menos 48. Os dígitos ficam com o próprio valor, e a letra A vale 17. O exemplo da Receita é 12.ABC.345/01DE. A primeira soma dá 459, com resto 8 e dígito 3; a segunda dá 424, com resto 6 e dígito 5. O resultado é 12.ABC.345/01DE-35.

def dv_cnpj(base12: str) -> str:
    valores = [ord(c) - 48 for c in base12.upper()]
    pesos = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
    for _ in range(2):
        soma = sum(v * p for v, p in zip(valores, pesos))
        resto = soma % 11
        valores.append(0 if resto < 2 else 11 - resto)
        pesos.insert(0, 6)
    return f"{valores[-2]}{valores[-1]}"

A função devolve 35 para 12ABC34501DE e 08 para 12345678000A, outro exemplo do mesmo documento. Neste segundo caso a primeira soma tem resto 1, e o dígito 0 confirma a regra do resto menor que 2. O sistema que guarda CNPJ como número inteiro, ou que valida com \d{14}, vai recusar os novos.

O cartão de crédito usa outro algoritmo, o de Luhn. Hans Peter Luhn criou o algoritmo na IBM, e a patente americana saiu em 1960, segundo a página do algoritmo de Luhn. A norma ISO/IEC 7812-1 o especifica. A conta dobra um dígito sim, outro não, a partir da direita. O dígito dobrado que passar de 9 perde 9, e a soma final tem que ser múltipla de 10. Ele pega todo erro de um dígito só e quase toda inversão de vizinhos, mas não percebe a troca de 09 por 90.

function luhnValido(numero) {
  const digitos = String(numero).replace(/\D/g, "");
  let soma = 0;
  for (let i = 0; i < digitos.length; i++) {
    let d = Number(digitos[digitos.length - 1 - i]);
    if (i % 2 === 1) {
      d *= 2;
      if (d > 9) d -= 9;
    }
    soma += d;
  }
  return digitos.length > 0 && soma % 10 === 0;
}

Com o número de exemplo da mesma página, 17893729974, a função devolve true; trocando o último dígito por 5, devolve false.

DocumentoTamanhoAlgoritmoPega o quê
CPF11 dígitosmódulo 11, pesos 10 a 2 e 11 a 2erro de digitação; sequência repetida exige regra à parte
CNPJ numérico14 dígitosmódulo 11, pesos 5 a 2 e 9 a 2erro de digitação
CNPJ alfanumérico12 caracteres e 2 dígitosmódulo 11 sobre ASCII menos 48erro de digitação, inclusive em letra
Cartão de créditovaria por emissorLuhn, módulo 10dígito trocado e quase toda inversão de vizinhos; não pega 09 por 90
Regex de formatoqualquernenhum cálculosó quantidade de caracteres e pontuação

Como ferramentas de DLP acham CPF em texto

Ferramentas de DLP precisam achar e validar CPF em e-mail, arquivo e texto colado. Com regex sozinha, o falso positivo dispara: celular com DDD e número de pedido também têm 11 dígitos.

Por isso a detecção costuma usar três camadas. A regex encontra os candidatos. O dígito verificador descarta quase todos os números aleatórios. Num teste meu com um milhão de sequências de 11 dígitos sorteadas, cerca de 1% passou na conta. A terceira camada procura uma palavra próxima, como "CPF" ou "contribuinte", numa janela curta de texto. Só então a ferramenta sobe a confiança do alerta.

O que a validação não responde

Validar CPF não diz se o número tem dono. Também não diz se a pessoa está viva ou se a situação cadastral está regular. Essas respostas vêm da consulta à base da Receita Federal.

O CPF também é dado pessoal, e a LGPD para PMEs trata o que isso exige de quem guarda o número. No código, isso pesa no log: quando a validação falha, registre o motivo (tamanho, sequência repetida ou dígito errado) e deixe o valor de fora.

Checklist para validar CPF num formulário:

  1. Aceite o número com e sem máscara, e aplique a máscara só na exibição.
  2. Confira o formato com a regex e remova o que não é dígito.
  3. Confira se sobraram exatamente 11 dígitos.
  4. Rejeite as dez sequências repetidas antes do cálculo.
  5. Calcule os dois dígitos verificadores e compare com os dois últimos.
  6. Repita a mesma validação no servidor.
  7. Guarde o CPF como texto, porque número inteiro apaga o zero à esquerda.
  8. Mantenha o CPF fora do log, da mensagem de erro e da ferramenta de monitoramento.

Cada base de nove dígitos gera um único par de verificadores. Por isso, dos 100 bilhões de combinações de 11 dígitos, só 1 bilhão fecha a conta, e tirando as dez sequências repetidas sobram 999.999.990 números que as funções deste post aceitam.