JavaScript CNPJ Validation: Handling Alphanumeric Formats
Using BIGINT or ^\d{14}$ for CNPJ validation is now a ticking time bomb. By July 2026, new companies will start receiving alphanumeric CNPJs (e.g., 12.ABC.345/01DE-35), and if your system expects only numbers, it's going to crash and burn the moment a client with a "lettered" ID tries to sign up.
The technical shift is simple: the first 12 characters now accept 0-9 and A-Z, while the last two check digits remain numeric. The math still uses Modulo 11, but the twist is that characters are now processed as ASCII - 48. This means '0' stays 0, but 'A' becomes 17.
If you're doing a deep dive into your legacy code, look for parseInt() calls or numeric database columns—those are your primary points of failure.
Here is a practical tutorial on how to implement the official validation logic from scratch in JavaScript:
function checkDigits(base12) {
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 = (ch) => ch.charCodeAt(0) - 48; // '0'-'9' → 0-9, 'A'-'Z' → 17-42
const dv = (chars, weights) => {
const sum = chars.reduce((acc, ch, i) => acc + val(ch) * weights[i], 0);
const rest = sum % 11;
return rest < 2 ? 0 : 11 - rest;
};
const c = base12.split("");
const dv1 = dv(c, W1);
const dv2 = dv([...c, String(dv1)], W2);
return `${dv1}${dv2}`;
}
// Official example: should return "35"
console.log(checkDigits("12ABC34501DE"));
For those who don't feel like reinventing the wheel or writing their own regex to handle normalization and repetition checks, there's a zero-dependency package that handles this. It's basically a complete guide in a library.
npm install valida-cnpj-alfanumerico
const CNPJ = require("valida-cnpj-alfanumerico");
CNPJ.isValid("12.ABC.345/01DE-35"); // true
CNPJ.generate({ alphanumeric: true, masked: true }); // Great for test data
If you're managing a massive codebase, manually searching for every regex is a nightmare. There is a GitHub Action called cnpj-scan that scans your PRs for "dangerous" patterns like numeric-only columns or restrictive regex, which is a lifesaver for avoiding production regressions.
For a full deployment of this logic, keep the source link handy:
https://github.com/andrehenrique311085-debug/valida-cnpj-alfanumericoAll Replies (3)
Curious if there's a lightweight library for this checksum or if you're writing it from scratch?
Nightmare fuel. How do you handle legacy IDs when strictly typing numbers in your schema?
Terrifying thought! Are your database columns still set to numeric for these alphanumeric formats?