Artigo Build·Desenvolvimento·13 min de leitura

Algoritmo do Dígito Verificador do CPF: Módulo 11 Completo

O algoritmo de módulo 11 do CPF é matemática elegante por trás de uma das validações mais comuns em apps brasileiros. Veja o passo a passo numérico, implementações em 5 linguagens, casos especiais e como preparar seu sistema para o CPF alfanumérico de 2026.

Vitor Morais

Por Vitor Morais

Fundador do MochaLabz ·

Valide CPF e CNPJ instantaneamente

Verificação de dígitos verificadores em tempo real, 100% no navegador.

Usar validador →

O algoritmo de módulo 11 é a matemática por trás dos dois dígitos verificadores do CPF. Ele detecta erros de digitação com altíssima probabilidade — incluindo transposição de dígitos adjacentes — e permite que qualquer sistema valide um CPF localmente, em microssegundos, sem consultar a Receita Federal. Este guia explica o algoritmo passo a passo, mostra implementações em cinco linguagens, cobre casos especiais e prepara você para o futuro CPF alfanumérico que entra em vigor em 2026.

Por que módulo 11 e não módulo 10

Vários documentos no Brasil e no mundo usam algoritmos de dígito verificador (CNPJ, ISBN-10, código de barras EAN). A escolha do módulo (10 ou 11) tem trade-offs:

Módulo 10 vs módulo 11 em dígitos verificadores
CritérioMódulo 10Módulo 11
Detecta erro de digitação simplesSimSim
Detecta transposição de dígitos vizinhosParcialQuase 100%
Pode produzir resto 10Não (vai até 9)Sim (precisa de tratamento)
Onde apareceCartão de crédito (Luhn), código de barrasCPF, CNPJ, ISBN-10

O CPF resolve o caso do resto 10 com uma convenção: restos 0, 1 ou 10 viram dígito 0. Restos de 2 a 9 viram 11 - resto.

A estrutura do CPF e o que entra no cálculo

O CPF tem 11 dígitos no formato XXX.XXX.XXX-DD. Os 9 primeiros formam o número-base (atribuído sequencialmente pela Receita); os 2 últimos são os dígitos verificadores calculados a partir dos 9 anteriores. Para entender mais sobre o significado de cada dígito (incluindo a 9ª posição, que indica a região fiscal), veja o que é CPF e estrutura completa.

Calculando o primeiro dígito verificador (DV1)

O processo tem cinco passos:

  1. Pegue os 9 primeiros dígitos do CPF (o número-base).
  2. Multiplique cada um por um peso decrescente de 10 a 2.
  3. Some todos os produtos.
  4. Calcule o resto da divisão por 11.
  5. Se resto < 2 → DV1 = 0; senão → DV1 = 11 − resto.

Vejamos com o CPF 529.982.247-25:

Posição: 1 2 3 4 5 6 7 8 9 Dígito: 5 2 9 9 8 2 2 4 7 Peso: 10 9 8 7 6 5 4 3 2 Produto: 5 × 10 = 50 2 × 9 = 18 9 × 8 = 72 9 × 7 = 63 8 × 6 = 48 2 × 5 = 10 2 × 4 = 8 4 × 3 = 12 7 × 2 = 14 Soma = 50 + 18 + 72 + 63 + 48 + 10 + 8 + 12 + 14 = 295 Resto = 295 mod 11 = 9 Como 9 ≥ 2 → DV1 = 11 - 9 = 2 ✅

Calculando o segundo dígito verificador (DV2)

Agora consideramos os 10 primeiros dígitos (o número-base + o DV1 calculado), com pesos de 11 a 2:

Posição: 1 2 3 4 5 6 7 8 9 10 Dígito: 5 2 9 9 8 2 2 4 7 2 Peso: 11 10 9 8 7 6 5 4 3 2 Produto: 5 × 11 = 55 2 × 10 = 20 9 × 9 = 81 9 × 8 = 72 8 × 7 = 56 2 × 6 = 12 2 × 5 = 10 4 × 4 = 16 7 × 3 = 21 2 × 2 = 4 Soma = 55 + 20 + 81 + 72 + 56 + 12 + 10 + 16 + 21 + 4 = 347 Resto = 347 mod 11 = 6 Como 6 ≥ 2 → DV2 = 11 - 6 = 5 ✅ CPF completo: 529.982.247-25

A regra do resto < 2

Restos 0, 1 e 10 geram dígito 0. Para restos de 2 até 9, o dígito é 11 − resto. Essa convenção evita que o DV seja maior que 9, garantindo que cabe em uma única posição decimal.

Implementação em JavaScript / TypeScript

A função abaixo é completa: limpa máscara, rejeita sequências repetidas, calcula os dois DVs e compara com os recebidos:

function calcMod11Digit(digits: number[]): number { // O peso da posição i é (length + 1 - i): para 9 dígitos // o primeiro tem peso 10, o último tem peso 2. const len = digits.length; const sum = digits.reduce( (acc, d, i) => acc + d * (len + 1 - i), 0, ); const remainder = sum % 11; return remainder < 2 ? 0 : 11 - remainder; } export function validarCPF(input: string): boolean { const cpf = input.replace(/[^\d]/g, ''); if (cpf.length !== 11) return false; if (/^(\d)\1{10}$/.test(cpf)) return false; // 000...0 a 999...9 const nums = cpf.split('').map(Number); const dv1 = calcMod11Digit(nums.slice(0, 9)); const dv2 = calcMod11Digit(nums.slice(0, 10)); return nums[9] === dv1 && nums[10] === dv2; } // Uso validarCPF('529.982.247-25'); // true validarCPF('111.111.111-11'); // false (todos iguais) validarCPF('123.456.789-00'); // false (DV errado)

Implementação em Python

import re def calc_mod11_digit(digits: list[int]) -> int: pesos = list(range(len(digits) + 1, 1, -1)) # ex.: 10..2 ou 11..2 soma = sum(d * p for d, p in zip(digits, pesos)) resto = soma % 11 return 0 if resto < 2 else 11 - resto def validar_cpf(cpf: str) -> bool: cpf = re.sub(r"\D", "", cpf) if len(cpf) != 11: return False if cpf == cpf[0] * 11: # rejeita 000...0 a 999...9 return False nums = [int(c) for c in cpf] dv1 = calc_mod11_digit(nums[:9]) dv2 = calc_mod11_digit(nums[:10]) return nums[9] == dv1 and nums[10] == dv2 print(validar_cpf("529.982.247-25")) # True

Implementação em Go

package cpf import "regexp" var soNumeros = regexp.MustCompile(`[^0-9]`) func calcMod11(digits []int) int { pesoInicial := len(digits) + 1 sum := 0 for i, d := range digits { sum += d * (pesoInicial - i) } rem := sum % 11 if rem < 2 { return 0 } return 11 - rem } func ValidarCPF(input string) bool { cpf := soNumeros.ReplaceAllString(input, "") if len(cpf) != 11 { return false } todoIgual := true for i := 1; i < 11; i++ { if cpf[i] != cpf[0] { todoIgual = false break } } if todoIgual { return false } nums := make([]int, 11) for i, c := range cpf { nums[i] = int(c - '0') } dv1 := calcMod11(nums[:9]) dv2 := calcMod11(nums[:10]) return nums[9] == dv1 && nums[10] == dv2 }

Implementação em Java

public class CpfValidator { private static int calcMod11(int[] digits) { int pesoInicial = digits.length + 1; int soma = 0; for (int i = 0; i < digits.length; i++) { soma += digits[i] * (pesoInicial - i); } int resto = soma % 11; return resto < 2 ? 0 : 11 - resto; } public static boolean validar(String input) { String cpf = input.replaceAll("[^\\d]", ""); if (cpf.length() != 11) return false; if (cpf.matches("^(\\d)\\1+$")) return false; int[] nums = new int[11]; for (int i = 0; i < 11; i++) nums[i] = cpf.charAt(i) - '0'; int dv1 = calcMod11(java.util.Arrays.copyOfRange(nums, 0, 9)); int dv2 = calcMod11(java.util.Arrays.copyOfRange(nums, 0, 10)); return nums[9] == dv1 && nums[10] == dv2; } }

Implementação em SQL (PostgreSQL)

Útil para validar CPFs já armazenados em uma tabela ou criar constraint:

CREATE OR REPLACE FUNCTION validar_cpf(input text) RETURNS boolean AS $$ DECLARE cpf text := regexp_replace(input, '[^0-9]', '', 'g'); nums int[]; dv1 int := 0; dv2 int := 0; soma int; resto int; BEGIN IF length(cpf) <> 11 THEN RETURN false; END IF; IF cpf ~ '^(\d)\1+$' THEN RETURN false; END IF; -- Converte para array de int SELECT array_agg(substring(cpf, i, 1)::int) INTO nums FROM generate_series(1, 11) AS i; -- DV1 soma := 0; FOR i IN 1..9 LOOP soma := soma + nums[i] * (11 - i); END LOOP; resto := soma % 11; dv1 := CASE WHEN resto < 2 THEN 0 ELSE 11 - resto END; -- DV2 soma := 0; FOR i IN 1..10 LOOP soma := soma + nums[i] * (12 - i); END LOOP; resto := soma % 11; dv2 := CASE WHEN resto < 2 THEN 0 ELSE 11 - resto END; RETURN nums[10] = dv1 AND nums[11] = dv2; END; $$ LANGUAGE plpgsql IMMUTABLE; -- Constraint na tabela: ALTER TABLE clientes ADD CONSTRAINT cpf_valido CHECK (validar_cpf(cpf));

Casos especiais que sua função precisa cobrir

  • Sequências repetidas: 000...000 a 999...999 passam matematicamente, são inválidas. Use regex /^(\d)\1{10}$/.
  • Tamanho diferente de 11: rejeite imediatamente sem entrar no cálculo.
  • Não-dígitos no input: remova com regex antes do cálculo (aceita máscara 123.456.789-00 ou só dígitos).
  • Whitespace em volta: trim() antes do regex.
  • String vazia ou null: sua função deve retornar false sem lançar exceção.
  • Caracteres Unicode: dígitos árabes (0–9) só. Recuse 0123456789 em qualquer outro alfabeto.

Performance: vale a pena se preocupar?

O cálculo é trivial e roda em microssegundos. Mesmo validando um milhão de CPFs em loop, qualquer linguagem moderna executa em alguns segundos. Em validação por requisição (formulário), o overhead é absolutamente irrelevante.

Quando otimizar

Em pipeline de ingestão (importar 100M+ de registros), use workers/threads em paralelo. Para validar uma coluna de tabela existente em SQL, prefira a função UDF (SQL acima) sobre buscar tudo na aplicação — o I/O é o real custo, não o cálculo.

Validar dígitos vs verificar existência na Receita

Validação local vs consulta à Receita Federal
CritérioValidação de DV (módulo 11)Consulta na Receita
O que verificaEstrutura matemáticaExistência e situação cadastral
Latência típica< 0,1 ms100 ms – 5 s
CustoZeroCusto por consulta (APIs pagas)
Funciona offline?SimNão
Quando usarSempre, em todo formulárioKYC, abertura de conta, antifraude

O que muda com o CPF alfanumérico em 2026

A Receita Federal aprovou a transição para o CPF alfanumérico. Os 8 primeiros caracteres podem ser letras maiúsculas ou dígitos; os 2 últimos continuam sendo dígitos verificadores. O algoritmo de módulo 11 continua, mas opera sobre o valor ASCII de cada caractere menos 48:

'0' (ASCII 48) → 0 '1' (ASCII 49) → 1 ... '9' (ASCII 57) → 9 'A' (ASCII 65) → 17 'B' (ASCII 66) → 18 ... 'Z' (ASCII 90) → 42 // JS preparado para os dois formatos function validarCPFMisto(input: string): boolean { const cpf = input.toUpperCase().replace(/[^0-9A-Z]/g, ''); if (cpf.length !== 11) return false; if (!/^[0-9]{2}$/.test(cpf.slice(9))) return false; // DVs sempre numéricos if (/^(.)\1+$/.test(cpf)) return false; const valor = (c: string) => c.charCodeAt(0) - 48; const calc = (chars: string[], peso0: number) => chars.reduce((acc, c, i) => acc + valor(c) * (peso0 - i), 0) % 11; const r1 = calc([...cpf.slice(0, 9)], 10); const r2 = calc([...cpf.slice(0, 10)], 11); const dv1 = r1 < 2 ? 0 : 11 - r1; const dv2 = r2 < 2 ? 0 : 11 - r2; return dv1 === Number(cpf[9]) && dv2 === Number(cpf[10]); }

Erros comuns na implementação

Lista negra

  • Esquecer a checagem de sequências repetidas.
  • Usar pesos errados (esquecer que DV2 começa em 11, não 10).
  • Não tratar input com máscara (123.456.789-00) e sem máscara.
  • Comparar string com número (nums[9] === "2" em vez de 2).
  • Lançar exceção em entrada inválida em vez de retornar false.
  • Armazenar CPF como integer no banco (perde zeros à esquerda).

Checklist da função de validação ideal

  • ✅ Aceita CPF com ou sem máscara.
  • ✅ Rejeita comprimento diferente de 11.
  • ✅ Rejeita sequências de 11 dígitos repetidos.
  • ✅ Calcula DV1 com pesos 10..2.
  • ✅ Calcula DV2 com pesos 11..2 sobre 10 dígitos (incluindo DV1).
  • ✅ Trata resto < 2 como dígito 0.
  • ✅ Não lança exceção em entrada inválida — retorna boolean.
  • ✅ É pura (sem efeito colateral).
  • ✅ Tem testes cobrindo casos válidos, inválidos, máscara, repetidos, vazio.
  • ✅ Considera evolução para CPF alfanumérico em 2026.

Perguntas frequentes

O que é o algoritmo de módulo 11?+

Módulo 11 é um esquema matemático de cálculo de dígito verificador (check digit). Multiplica cada dígito do número-base por um peso decrescente, soma os produtos, divide a soma por 11 e usa o resto para derivar o dígito de verificação. Foi adotado pelo CPF brasileiro porque detecta com altíssima probabilidade erros de digitação simples (troca de um dígito) e transposição de dois dígitos vizinhos.

Por que o CPF usa exatamente módulo 11 e não 10?+

Módulo 11 detecta mais tipos de erro que módulo 10. Em particular, captura transposição de dígitos adjacentes (troca de 25 por 52, por exemplo) — erro humano muito comum em digitação. O preço é que o cálculo pode produzir resto 10, que precisa de tratamento especial; no CPF, restos 0 e 1 também viram zero por convenção, simplificando a regra.

O que significa &ldquo;peso decrescente&rdquo; nos cálculos?+

Cada posição do número recebe um multiplicador diferente. No primeiro DV do CPF, o primeiro dígito é multiplicado por 10, o segundo por 9, o terceiro por 8, e assim por diante até o nono ser multiplicado por 2. No segundo DV, começa em 11 e vai até 2. Esses pesos foram escolhidos para garantir as propriedades de detecção de erro do módulo 11.

Por que CPFs como 111.111.111-11 passam na validação matemática?+

Porque qualquer sequência de 11 dígitos iguais produz dígitos verificadores que matematicamente fecham no cálculo de módulo 11 — uma coincidência da fórmula. A Receita Federal trata essas 10 sequências (000...000 até 999...999) como inválidas. Em qualquer implementação séria, adicione uma checagem específica para rejeitar dígitos repetidos antes do cálculo.

Posso usar a validação no front-end ou só no back-end?+

Sempre nos dois. No front, valide em tempo real para feedback imediato no formulário (UX melhor). No back, valide novamente porque você nunca pode confiar em dados que vieram do cliente. Como o cálculo é puramente matemático e leva microssegundos, o overhead em ambos é desprezível.

O algoritmo funciona da mesma forma para todos os 26 estados?+

Sim. O cálculo de módulo 11 é idêntico independente da região fiscal de origem (a 9ª posição do CPF). A região fiscal é informativa e não influencia o cálculo dos verificadores. Por isso a função de validação pode ser uma só, sem switch por estado.

O algoritmo de validação muda com o novo CPF alfanumérico de 2026?+

O esqueleto continua igual (módulo 11 com os mesmos pesos), mas opera sobre o valor ASCII de cada caractere menos 48 — assim &lsquo;0&rsquo; vira 0, &lsquo;9&rsquo; vira 9, &lsquo;A&rsquo; vira 17, &lsquo;Z&rsquo; vira 42. Os 2 últimos caracteres permanecem dígitos numéricos. Implementações novas devem aceitar maiúsculas e usar o mapeamento ASCII no cálculo.

Qual a diferença entre validar dígitos verificadores e consultar a Receita?+

Validar dígitos verificadores confirma que o número está estruturalmente bem formado (sem erro de digitação), mas não diz se o CPF realmente existe. Para confirmar existência e situação cadastral (regular, suspenso, cancelado), é necessário consulta à Receita Federal — geralmente via APIs pagas ou serviços credenciados. Para a grande maioria dos formulários, a validação local basta.

#cpf#algoritmo#módulo 11#dígito verificador#javascript#python#go#java#sql#validação

Continue lendo