cnpjcpf.
Código · JavaScript

Validar CNPJ em JavaScript

Uma função sem dependências que valida CNPJ pelo módulo 11numérico e alfanumérico no mesmo código. A conversão ASCII − 48 trata letra e dígito de forma uniforme; só os 2 verificadores continuam numéricos.

A função

JavaScript
const W1 = [5,4,3,2,9,8,7,6,5,4,3,2];
const W2 = [6,5,4,3,2,9,8,7,6,5,4,3,2];
const val = (c) => c.charCodeAt(0) - 48;        // '0'->0 ... 'Z'->42
const dvCNPJ = (base, w) => {
  let s = 0;
  for (let i = 0; i < w.length; i++) s += val(base[i]) * w[i];
  const r = s % 11;
  return r < 2 ? 0 : 11 - r;
};

function isValidCNPJ(cnpj) {
  cnpj = String(cnpj).replace(/[./-]/g, '').toUpperCase();
  if (!/^[A-Z0-9]{12}\d{2}$/.test(cnpj)) return false;   // 12 base + 2 DV numérico
  if (/^(.)\1{13}$/.test(cnpj)) return false;            // repetidos
  const d1 = dvCNPJ(cnpj.slice(0, 12), W1);
  const d2 = dvCNPJ(cnpj.slice(0, 12) + d1, W2);
  return d1 === Number(cnpj[12]) && d2 === Number(cnpj[13]);
}

isValidCNPJ('12.ABC.345/01DE-35'); // true  (alfanumérico, exemplo SERPRO)
isValidCNPJ('11.222.333/0001-81'); // true  (numérico)
isValidCNPJ('11.222.333/0001-00'); // false

O mesmo código valida os dois formatos: o numérico é um caso particular do alfanumérico. A base tem 12 posições (letras A–Z ou dígitos 0–9) e os 2 verificadores são sempre numéricos.

Por que ASCII − 48

No módulo 11 cada posição vira um número antes de multiplicar pelo peso. Para tratar letra e dígito de forma uniforme, converte-se o caractere pelo seu código ASCII menos 48: '0' vira 0, '9' vira 9 e 'A' vira 17 (segue até 'Z' = 42). É exatamente o que val() faz com charCodeAt(0) - 48.

JavaScript
val('0'); // 0
val('9'); // 9
val('A'); // 17
val('Z'); // 42

Os pesos vêm em duas listas (W1 para o 1º dígito, W2 para o 2º) e o resto da divisão por 11 define o verificador — resto < 2 ? 0 : 11 - resto. É o módulo 11 de sempre, só com a entrada normalizada.

publicidade

TypeScript

TypeScript
const W1 = [5,4,3,2,9,8,7,6,5,4,3,2];
const W2 = [6,5,4,3,2,9,8,7,6,5,4,3,2];
const val = (c: string): number => c.charCodeAt(0) - 48;
const dvCNPJ = (base: string, w: number[]): number => {
  let s = 0;
  for (let i = 0; i < w.length; i++) s += val(base[i]) * w[i];
  const r = s % 11;
  return r < 2 ? 0 : 11 - r;
};

export function isValidCNPJ(value: string): boolean {
  const cnpj = value.replace(/[./-]/g, '').toUpperCase();
  if (!/^[A-Z0-9]{12}\d{2}$/.test(cnpj)) return false;
  if (/^(.)\1{13}$/.test(cnpj)) return false;
  const d1 = dvCNPJ(cnpj.slice(0, 12), W1);
  const d2 = dvCNPJ(cnpj.slice(0, 12) + d1, W2);
  return d1 === Number(cnpj[12]) && d2 === Number(cnpj[13]);
}

Cuidados

  • Regex só valida formato. Um padrão como /^[A-Z0-9]{12}\d{2}$/ confirma que são 12 posições alfanuméricas + 2 dígitos, mas não confere o verificador — quem faz isso é a função acima. Veja regex de CNPJ.
  • Sequências repetidas (00000000000000) passariam no módulo 11, por isso a função as descarta antes com /^(.)\1{13}$/.
  • Normalize antes. A função força toUpperCase() e remove . / -; minúsculas e máscara são tratadas, mas guarde sempre os 14 caracteres limpos.
  • Válido ≠ existe. A função confirma a consistência matemática, não se o CNPJ foi emitido a uma empresa real. Para isso é outra coisa: CNPJ válido vs. CNPJ real.
  • Alfanumérico entra em jul/2026 (IN RFB nº 2.229/2024), só para novos registros. O código já está pronto para os dois formatos.

Continue

Código verificado por execução com o exemplo oficial SERPRO (12ABC34501DE → DV 35). Algoritmo módulo 11 com conversão ASCII−48. Revisado em 06/2026.