Valide números de CNH ou gere válidos para testes. Verificação completa dos dois dígitos verificadores.
Informe uma CNH ou gere novas
A CNH tem 11 dígitos. Os dois últimos são dígitos verificadores calculados pelo módulo 11 com pesos variáveis.
O primeiro verificador usa pesos 1 a 9 (ascendente) sobre os 9 primeiros dígitos. O segundo verificador usa pesos 9 a 1 (descendente), com ajuste (DSC) quando o primeiro verificador é zero.
⚠️ CNHs geradas são fictícias, válidas matematicamente mas não vinculadas a nenhuma pessoa real. Use apenas para testes.
A CNH (Carteira Nacional de Habilitação) é o documento oficial que habilita o cidadão brasileiro a conduzir veículos automotores no território nacional. Emitida pelo DETRAN de cada estado e regulamentada pelo DENATRAN (hoje SENATRAN), é controlada pelo RENACH (Registro Nacional de Carteiras de Habilitação), sistema federal que unifica os dados de todos os condutores do país.
Para fins de sistemas e validação, o que importa é o Registro de CNH: um número de 11 dígitos onde os 9 primeiros formam o número base e os 2 últimos são dígitos verificadores calculados por um algoritmo módulo 11 com pesos variáveis — similar ao CPF, mas com lógica diferente.
| Posição | Descrição | Exemplo |
|---|---|---|
| 1–9 | Número base da CNH | 123456789 |
| 10 | 1° dígito verificador (DV1) | 0 |
| 11 | 2° dígito verificador (DV2) | 9 |
| 1–11 | Registro completo da CNH | 12345678909 |
O algoritmo usa módulo 11 com dois cálculos distintos de pesos — um ascendente (1→9) para o primeiro verificador e um descendente (9→1) para o segundo, com um DSC (desconto) especial quando o primeiro dígito verificador é zero.
function validarCNH(cnh) { // Remove não-dígitos e valida comprimento cnh = cnh.replace(/\D/g, ''); if (cnh.length !== 11) return false; // Rejeita sequências repetidas (ex.: 00000000000) if (/^(\d)\1+$/.test(cnh)) return false; const digits = cnh.split('').map(Number); let soma = 0, dsc = 0; // Calcula DV1 com pesos 1 a 9 for (let i = 0; i < 9; i++) soma += digits[i] * (i + 1); let dv1 = soma % 11; if (dv1 >= 10) { dv1 = 0; dsc = 2; } // Calcula DV2 com pesos 9 a 1 soma = 0; for (let i = 0; i < 9; i++) soma += digits[i] * (9 - i); soma += dsc; let dv2 = soma % 11; if (dv2 >= 10) dv2 = 0; return digits[9] === dv1 && digits[10] === dv2; } console.log(validarCNH('12345678909')); // true console.log(validarCNH('12345678900')); // false
import re def validar_cnh(cnh: str) -> bool: cnh = re.sub(r'\D', '', cnh) if len(cnh) != 11: return False if len(set(cnh)) == 1: return False # todos iguais digits = [int(d) for d in cnh] dsc = 0 # DV1 — pesos 1 a 9 soma = sum(digits[i] * (i + 1) for i in range(9)) dv1 = soma % 11 if dv1 >= 10: dv1, dsc = 0, 2 # DV2 — pesos 9 a 1 soma = sum(digits[i] * (9 - i) for i in range(9)) + dsc dv2 = soma % 11 if dv2 >= 10: dv2 = 0 return digits[9] == dv1 and digits[10] == dv2 print(validar_cnh('12345678909')) # True print(validar_cnh('00000000000')) # False
function validarCNH(string $cnh): bool { $cnh = preg_replace('/\D/', '', $cnh); if (strlen($cnh) !== 11) return false; if (preg_match('/^(\d)\1+$/', $cnh)) return false; $digits = array_map('intval', str_split($cnh)); $dsc = 0; $soma = 0; for ($i = 0; $i < 9; $i++) $soma += $digits[$i] * ($i + 1); $dv1 = $soma % 11; if ($dv1 >= 10) { $dv1 = 0; $dsc = 2; } $soma = 0; for ($i = 0; $i < 9; $i++) $soma += $digits[$i] * (9 - $i); $dv2 = ($soma + $dsc) % 11; if ($dv2 >= 10) $dv2 = 0; return $digits[9] === $dv1 && $digits[10] === $dv2; }
public static boolean validarCNH(String cnh) { cnh = cnh.replaceAll("\\D", ""); if (cnh.length() != 11) return false; if (cnh.matches("(\\d)\\1{10}")) return false; int[] d = cnh.chars().map(c -> c - '0').toArray(); int soma = 0, dsc = 0; for (int i = 0; i < 9; i++) soma += d[i] * (i + 1); int dv1 = soma % 11; if (dv1 >= 10) { dv1 = 0; dsc = 2; } soma = 0; for (int i = 0; i < 9; i++) soma += d[i] * (9 - i); int dv2 = (soma + dsc) % 11; if (dv2 >= 10) dv2 = 0; return d[9] == dv1 && d[10] == dv2; }
public static bool ValidarCNH(string cnh) { cnh = Regex.Replace(cnh, @"\D", ""); if (cnh.Length != 11) return false; if (Regex.IsMatch(cnh, @"^(\d)\1+$")) return false; int[] d = cnh.Select(c => c - '0').ToArray(); int soma = 0, dsc = 0; for (int i = 0; i < 9; i++) soma += d[i] * (i + 1); int dv1 = soma % 11; if (dv1 >= 10) { dv1 = 0; dsc = 2; } soma = 0; for (int i = 0; i < 9; i++) soma += d[i] * (9 - i); int dv2 = (soma + dsc) % 11; if (dv2 >= 10) dv2 = 0; return d[9] == dv1 && d[10] == dv2; }
| Característica | CNH | CPF |
|---|---|---|
| Total de dígitos | 11 | 11 |
| Dígitos verificadores | 2 (posições 10 e 11) | 2 (posições 10 e 11) |
| Pesos DV1 | 1, 2, 3, 4, 5, 6, 7, 8, 9 (crescente) | 10, 9, 8, 7, 6, 5, 4, 3, 2 (decrescente) |
| Pesos DV2 | 9, 8, 7, 6, 5, 4, 3, 2, 1 (decrescente) | 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 (inclui DV1) |
| Regra ≥ 10 | DV = 0 e aplica DSC = 2 no DV2 | DV = 0 (simples) |
| DSC especial | Sim — quando DV1 ≥ 10 | Não |
| Dígito regional | Não (no registro) | Sim — posição 9 indica região |
Testes de formulários: Sistemas de frota, locadoras, seguros e detrans precisam validar CNH em tempo real no frontend. Use o gerador para criar massas de dados de teste sem expor dados reais de condutores.
LGPD e dados pessoais: CNH é dado pessoal sensível conforme a LGPD. Em ambientes de desenvolvimento e homologação, nunca use CNHs reais — use sempre dados gerados fictícios que passem na validação matemática mas não correspondam a pessoas reais.
Validação frontend vs backend: Valide a CNH no frontend para UX (feedback imediato), mas sempre revalide no backend antes de persistir. Nunca confie apenas na validação client-side — ela pode ser bypassada facilmente.
Sim, para fins de desenvolvimento e testes. Gerar números que passam na validação matemática é legal para testar sistemas, preencher bancos de dados de homologação e desenvolver validadores. O que é ilegal é usar números reais de terceiros sem autorização, apresentar CNH falsa como documento oficial, ou usar dados gerados para fraude. Ferramentas de geração de documentos fictícios para desenvolvimento são amplamente utilizadas e aceitas na indústria de software.
Por convenção do algoritmo — e para evitar valores triviais — números como 00000000000, 11111111111 e outros com todos os dígitos iguais são considerados inválidos, mesmo que matematicamente possam passar nos cálculos de módulo. É o mesmo tratamento dado ao CPF. Na prática, é um filtro de sanidade básico que qualquer validador deve implementar.
Não. O número de registro da CNH é permanente e vinculado ao condutor no RENACH — não muda com renovações, mudanças de categoria, adição de ACC (autorização para conduzir ciclomotores) ou mudança de estado. O que muda a cada renovação é o número do documento físico (impresso no canto da carteira), não o número de registro de 11 dígitos usado para validação.
Antes de calcular os dígitos verificadores, aplique estas validações rápidas:
/^\d{11}$//^(?!(\d)\1+$)/Essas verificações eliminam entradas obviamente inválidas antes do cálculo custoso — boa prática para validação em massa.
Sim, mas requer credenciais e autorização do SENATRAN/DETRAN. Opções disponíveis:
Nenhuma dessas opções é gratuita para consulta em massa — apenas a validação matemática (o que este validador faz) é livre.
Extraia os 9 dígitos base (posições 1–9). Rejeite se comprimento ≠ 11 ou todos os dígitos forem iguais.
DV1: some cada dígito × peso crescente (1, 2, ..., 9). DV1 = soma % 11. Se ≥ 10 → DV1 = 0 e DSC = 2.
DV2: some cada dígito × peso decrescente (9, 8, ..., 1) + DSC. DV2 = soma % 11. Se ≥ 10 → DV2 = 0.
Validação: dígito[9] == DV1 E dígito[10] == DV2. Ambos devem bater — se qualquer um falhar, a CNH é inválida.
Complexidade: O(n) com n=11 — validação instantânea, sem necessidade de lookup externo. Ideal para validação em formulários com feedback em tempo real (onInput/onChange).