CNPJ
Cadastro Nacional da Pessoa Jurídica, the 14-character Brazilian company registration number. Alphanumeric since July 2026, with two numeric mod-11 check digits.
Validate
- JavaScript library
- Python library4 cases fail
- Go library3 cases fail
- Ruby library3 cases fail
- Rust library2 cases fail
- .NET library4 cases fail
- Erlang library4 cases fail
Validates a CNPJ: 12 base characters and 2 modulus 11 check digits.
options.version:1(default) accepts numeric CNPJs only.2also accepts the alphanumeric CNPJ, case-insensitively. Any other value is read as1.- A numeric CNPJ whose digits are all the same is rejected. The alphanumeric format has no reserved list.
- Since July 2026 new CNPJs may be alphanumeric, which the default
version: 1rejects. Passversion: 2to accept them. - The official character set of the alphanumeric CNPJ is the capital letters
AtoZand the digits; the 2 check digits are always digits. A lower case letter is accepted only as input normalization, like a mask character: the value is upper-cased first. - The Ex1 of question 23 of the Receita Federal Q&A on the alphanumeric CNPJ,
AA345678/0003-29, is a misprint: its check digits are86, so it is rejected.
Pending decision
The reference (JS) ignores the formatting characters (., -, /) and whitespace around and between groups. The other libraries accept digits only. See the open decision in docs/findings.md.
| Parameter | Type | Required |
|---|---|---|
cnpj | string | yes |
options | IsValidCnpjOptions | no |
options.version | 1 | 2 | no |
| returns | boolean |
Check if a CNPJ is valid.
- Options (
IsValidCnpjOptions):versionpicks the accepted format:1(default) numeric only,2numeric and alphanumeric. Any other value is read as1. - Since July 2026 new CNPJs may be alphanumeric, which the default
version: 1rejects: passversion: 2to accept them. - A reserved number (all digits the same) is rejected under both versions; version
2has no reserved list for letters. - The official character set of the alphanumeric CNPJ is the capital letters
AtoZand the digits (the 2 check digits are always digits). A lower case letter is accepted only as input normalization, like a mask character: the input is upper-cased first. - The Ex1 of question 23 of the Receita Federal's Q&A on the alphanumeric CNPJ,
AA345678/0003-29, is a misprint: its check digits are86, so it is rejected.
import { isValidCnpj } from '@brazilian-utils/brazilian-utils';
isValidCnpj('15515147234255'); // false
isValidCnpj('q0slfmbd7vx439', { version: 2 }); // true (read as Q0SLFMBD7VX439)Source: Instrução Normativa RFB nº 2.229/2024 (Anexo XV of IN RFB nº 2.119/2022, weights "da direita para esquerda" as corrected by the retificação in the DOU of 25/10/2024), Receita Federal, Manual do DV do CNPJ, CNPJ alfanumérico.
Code: brazilian-utils/javascriptTry it with JavaScript isValidCnpj
Shared test cases (42) and the result in each library cnpj.isValid
Format
- JavaScript library
- Python library36 cases fail
- Go library15 cases fail
- Ruby library36 cases fail
- Rust library18 cases fail
- .NET library7 cases fail
- Erlang library36 cases fail
Formats a CNPJ as 00.000.000/0000-00.
options.padfirst left-pads the value with zeros to 14 characters.options.version:1(default) keeps digits only.2(alphanumeric CNPJ) keeps letters (upper-cased) and digits. Any other value is read as1.options.obfuscate(defaultfalse, read for truthiness likepad) hides the first 2 characters and the 2 check digits with*, after padding. This is a convention of the library, with no official source: no law or Receita Federal act sets a masking rule for the CNPJ, whose data are public. It follows the rule the Leis de Diretrizes Orçamentárias set for the CPF.- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number returns an empty string (2.4.0 read the digits of any number).
- A value with no characters the version keeps (empty, or only symbols) returns an empty string even with
options.pad. Until 2.4.0padreturned the whole zero mask (00.000.000/0000-00). - The value is read up to 14 characters: characters past the 14th are dropped, also with
options.pad. - Since July 2026 new CNPJs may be alphanumeric. The default
version: 1drops their letters, so passversion: 2to keep them. A number loses its leading zeros: pass a string, or useoptions.pad, for a CNPJ that starts with0.
Pending decision
The reference (JS) formats only the characters an incomplete value has. It returns an empty string for empty or invalid input. The other libraries return null. See the open decision in docs/findings.md.
| Parameter | Type | Required |
|---|---|---|
value | string | number | yes |
options | FormatCnpjOptions | no |
options.pad | boolean | no |
options.version | 1 | 2 | no |
options.obfuscate | boolean | no |
| returns | string |
Format a CNPJ.
- Options (
FormatCnpjOptions):padleft-pads the value with zeros to 14 characters before masking (defaultfalse);versionpicks the format,1(default) numeric only,2alphanumeric;obfuscatehides the first 2 digits and the 2 check digits. An empty value, or one without digits, gives''even withpad. - Version
2keeps letters and digits, a lower case letter upper-cased first since the official set isAtoZ; version1keeps digits only. Since July 2026 new CNPJs may be alphanumeric, so passversion: 2to keep their letters. obfuscateworks in both versions and is applied afterpad. It is a convention of this library, not an official rule: no law or Receita Federal act sets a masking rule for the CNPJ, whose data are public, the ANPD says "não há um padrão para o mascaramento", and the Banco Central's Pix rules show the CNPJ in full where they mask the CPF; it hides the first 2 characters and the 2 check digits, after the CPF rule.
import { formatCnpj } from '@brazilian-utils/brazilian-utils';
formatCnpj('24522200000174'); // 24.522.200/0001-74
formatCnpj('245222000174', { pad: true }); // 00.245.222/0001-74
formatCnpj('12OUT345000199', { version: 2 }); // 12.OUT.345/0001-99
formatCnpj('12345678000195', { obfuscate: true }); // **.345.678/0001-**Try it with JavaScript formatCnpj
Shared test cases (99) and the result in each library cnpj.format
Parse
- JavaScript library
- Python library
- Go library
- Ruby library3 cases fail
- Rust library
- .NET library
- Erlang library
Removes CNPJ formatting and returns the normalized value, capped at 14 characters.
options.version:1(default) keeps digits only.2keeps letters and digits, upper-cased. Any other value is read as1.- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number returns an empty string (2.4.0 read the digits of any number).
- Since July 2026 new CNPJs may be alphanumeric. The default
version: 1drops their letters, so passversion: 2to keep them. A lower case letter is upper-cased first, since the official set isAtoZ.
| Parameter | Type | Required |
|---|---|---|
value | string | number | yes |
options | ParseCnpjOptions | no |
options.version | 1 | 2 | no |
| returns | string |
Remove CNPJ formatting, return a normalized value, and cap the result to 14 characters.
- Options (
ParseCnpjOptions):versionpicks the format:1(default) keeps digits only,2keeps letters and digits, a lower case letter upper-cased since the official set isAtoZ(parseCnpj('12.abc.345/01de-35', { version: 2 })returns'12ABC34501DE35'). Since July 2026 new CNPJs may be alphanumeric, so the default drops their letters: passversion: 2to keep them.
import { parseCnpj } from '@brazilian-utils/brazilian-utils';
parseCnpj('24.522.200/0001-74'); // 24522200000174
parseCnpj('12.OUT.345/0001-99', { version: 2 }); // 12OUT345000199Try it with JavaScript parseCnpj
Shared test cases (25) and the result in each library cnpj.parse
Generate
- JavaScript library
- Python library5 cases fail
- Go library
- Ruby library
- Rust library
- .NET library
- Erlang library5 cases fail
Generates a valid random CNPJ, unformatted.
versionOrParamspicks the version:1(default, numeric) or2(alphanumeric). It can also be an object{ version, branch }, wherebranchsets the branch (número de ordem), an integer from 1 to 9999. The branch is random by default, and an invalid branch is ignored.- A branch given in
branchis written as 4 digits in both versions (3gives0003). A random branch under version 2 can carry letters, like the root. - A random branch is never
0000: the establishments of a root are numbered from0001, the headquarters (matriz). 2.4.0 could return0000, about once in 10,000 numeric CNPJs. - Invalid
branchvalues (0, above 9999, fractional, not a number) are ignored and a random branch is used. A numberversionOrParamsother than2(or a value that is neither2nor an object) generates a numeric CNPJ.
| Parameter | Type | Required |
|---|---|---|
versionOrParams | 1 | 2 | GenerateCnpjParams | no |
| returns | string |
Generate a valid random CNPJ.
- The first argument is either the version,
1(default) numeric or2alphanumeric, or aGenerateCnpjParamsobject withversionplusbranch. branchis the "número de ordem" (filial) block, an integer from 1 to 9999 (random by default). An invalidbranchis ignored. The block stays numeric in both versions.- A random ordem block is never
0000: the establishments of a root are numbered from0001, the matriz, on, so that block is never assigned.
import { generateCnpj } from '@brazilian-utils/brazilian-utils';
generateCnpj();
generateCnpj(2); // alphanumeric CNPJ, e.g. 'Q0SLFMBD7VX439'
generateCnpj({ branch: 3 }); // ordem block '0003', e.g. '12345678000357'
generateCnpj({ version: 2, branch: 1 }); // alphanumeric CNPJ whose ordem block is '0001'Try it with JavaScript generateCnpj
Shared test cases (9) and the result in each library cnpj.generate
Decode
Reads the fields of a CNPJ: root, branch and check digits, and whether the branch is 0001. Returns null exactly when cnpj.isValid is false for the same arguments.
rootis positions 1 to 8.branchis positions 9 to 12, the número de ordem of the establishment.checkDigitsis positions 13 and 14. The namebranchis the same as incnpj.generate.options.versionworks as incnpj.isValid:1(default) reads numeric CNPJs only,2reads numeric and alphanumeric CNPJs, and any other value is read as1. An alphanumeric CNPJ read under version 1 returnsnull.- The fields of an alphanumeric CNPJ come back in upper case.
isInitialHeadquartersistruewhen the branch is0001. It marks the headquarters (matriz) only at the time the CNPJ was created: a filial can become the matriz without having the branch0001(question 25 of the Receita Federal Q&A on the alphanumeric CNPJ). Only the Receita Federal registry tells the current headquarters.- The result has no
formatfield. Usecnpj.formatfor the mask. - Returns a new object on every call.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
options | GetCnpjInfoOptions | no |
options.version | 1 | 2 | no |
| returns | CnpjInfo | null |
Parse a CNPJ into the fields the number encodes. Accepts the same input forms as isValidCnpj and returns null whenever it would return false for the same arguments, so an alphanumeric CNPJ read under version 1 is null.
- Options (
GetCnpjInfoOptions):versionis read the wayisValidCnpjreads it,1(default) the numeric-only format,2both the numeric and the alphanumeric one. - Returns a
CnpjInfo, the 14 positions as Anexo XV lays them out: 8 (root, the raiz that identifies the entity) + 4 (branch, the establishment, called número de ordem by the Receita Federal) + 2 (checkDigits, always numeric).branchis named after thebranchparameter ofgenerateCnpj, which fills the same four positions. isInitialHeadquarterstells whether the branch is0001, the one the Receita Federal gives the headquarters (matriz) when the root is registered. A filial can later become the headquarters while keeping its número de ordem, so only the Receita Federal registry tells the current headquarters.- The fields of an alphanumeric CNPJ are returned upper cased.
import { getCnpjInfo } from '@brazilian-utils/brazilian-utils';
getCnpjInfo('12.345.678/0001-95');
// {
// root: '12345678',
// branch: '0001',
// checkDigits: '95',
// isInitialHeadquarters: true
// }
getCnpjInfo('12.abc.345/01de-35', { version: 2 });
// {
// root: '12ABC345',
// branch: '01DE',
// checkDigits: '35',
// isInitialHeadquarters: false
// }
getCnpjInfo('12.ABC.345/01DE-35'); // null (alphanumeric, read under version 1)
getCnpjInfo('12.345.678/0001-90'); // null (bad check digits)Source: Instrução Normativa RFB nº 2.229/2024, whose Anexo Único is the Anexo XV of IN RFB nº 2.119/2022 and lays the 14 positions out, Receita Federal Q&A on the alphanumeric CNPJ (questions 21, 23 and 25).
Code: brazilian-utils/javascriptTry it with JavaScript getCnpjInfo
Shared test cases (26) and the result in each library cnpj.getInfo
Guides
- Document fieldA field that masks and validates a CPF, CNPJ, CEP or phone number as you type, with Brazilian Utils in React, Angular, Vue and plain JavaScript.
- Schema librariesThe validators of Brazilian Utils inside a Zod, Valibot or ArkType schema, or as a Standard Schema of their own.
Specification
Summary
The CNPJ is a unique identification number that the Brazilian Federal Revenue Service issues. It registers companies, public agencies and other entities in Brazil. It has 14 characters: 8 for the root, 4 for the order of the establishment and 2 check digits. CNPJs issued before the alphanumeric format started contain only digits. Since July 2026, new registrations can contain uppercase letters and digits in the first 12 characters. The 2 check digits stay numeric only.
Validation rules
-
The input must contain exactly 14 characters.
-
The first 12 characters can contain digits from
0to9and letters fromAtoZ. Withversion: 2, validation reads lowercase letters as uppercase. -
The last 2 characters are the check digits and must be numeric.
-
The check digits must come from the modulo 11 algorithm.
-
To calculate the check digits, convert the first 12 characters into numeric values. Use the decimal ASCII code of each character and subtract 48.
Examples:
0→48 - 48 = 09→57 - 48 = 9A→65 - 48 = 17B→66 - 48 = 18Z→90 - 48 = 42
Algorithm
- Check that the input contains exactly 14 characters.
- Check that the first 12 characters are alphanumeric and the last 2 are numeric.
- Convert the alphanumeric characters to numeric values:
- Digits keep their original values.
- Letters become their decimal ASCII values minus
48.
- Calculate the first check digit (DV1):
- For the first 12 characters, give weights from
2to9from right to left. Start again at2after weight9. - Multiply each value by its weight and add the results.
- Calculate the remainder of the sum divided by
11. - If the remainder is
0or1, DV1 is0. If not, DV1 is11 - remainder.
- For the first 12 characters, give weights from
- Calculate the second check digit (DV2):
- Add DV1 to the end of the sequence. For these 13 characters, give weights from
2to9from right to left. - Multiply each value by its weight and add the results.
- Calculate the remainder of the sum divided by
11. - If the remainder is
0or1, DV2 is0. If not, DV2 is11 - remainder.
- Add DV1 to the end of the sequence. For these 13 characters, give weights from
- Compare the calculated check digits with the last two characters of the CNPJ.
Fields of the number
IN RFB nº 2.229/2024 (Anexo XV of IN RFB nº 2.119/2022) lays the 14 positions out as:
| Positions | Field | getCnpjInfo key |
|---|---|---|
| 1 to 8 | root (raiz), shared by every establishment of the entity | root |
| 9 to 12 | número de ordem of the establishment | branch |
| 13 and 14 | check digits, always numeric | checkDigits |
getCnpjInfo(value, { version })returns these fields andisInitialHeadquarters. It returnsnullexactly whenisValidCnpj(value, { version })isfalse, so an alphanumeric CNPJ read under version 1 givesnull. The fields of an alphanumeric CNPJ come back in upper case. The result has noformatfield.isInitialHeadquartersistruewhen the branch is0001. The Receita Federal gives0001to the headquarters (matriz) when the root is registered. A filial can later become the matriz without having the branch0001(question 25 of the Receita Federal Q&A on the alphanumeric CNPJ), so the flag only says what the number said at creation.generateCnpj({ branch })uses the same name. A random branch is never0000, since establishments are numbered from0001. 2.4.0 could return0000(about once in 10,000 numeric CNPJs).
Examples:
getCnpjInfo("12.345.678/0001-95")returns{ root: "12345678", branch: "0001", checkDigits: "95", isInitialHeadquarters: true }.getCnpjInfo("12.abc.345/01de-35", { version: 2 })returns{ root: "12ABC345", branch: "01DE", checkDigits: "35", isInitialHeadquarters: false }.getCnpjInfo("12.ABC.345/01DE-35")returnsnull(alphanumeric, read under version 1).
Masking and numbers
formatCnpj(value, { obfuscate: true })hides the first 2 characters and the 2 check digits (**.345.678/0001-**). This is a convention of the library, with no official source: no law or Receita Federal act sets a masking rule for the CNPJ, whose data are public. It follows the rule the Leis de Diretrizes Orçamentárias set for the CPF.formatCnpjandparseCnpjalso take a number. It is read only when it is a non-negative safe integer. A negative, fractional, non-finite or unsafe number returns an empty string. 2.4.0 read the digits of any number.
Regex
- Unformatted CNPJ:
^[A-Z0-9]{12}[0-9]{2}$ - Formatted CNPJ:
^[A-Z0-9]{2}\.[A-Z0-9]{3}\.[A-Z0-9]{3}/[A-Z0-9]{4}-[0-9]{2}$
Examples
- Valid:
03560714000142(valid numeric CNPJ) - Valid:
9359QAG9000184(valid alphanumeric CNPJ) 03.560.714/0001-42: pending decision. The reference (JS) accepts it, the other libraries do not.- Invalid:
00111222000133(invalid check digits) - Invalid:
12ABC34501DE3X(the check digits must be numeric) - Invalid:
12ABC34501DE3(must contain exactly 14 characters) - Invalid:
12ABC34501DE345(must contain exactly 14 characters)
Official sources
- Instrução Normativa RFB nº 2119, de 6 de dezembro de 2022
- Instrução Normativa RFB nº 2229, de 15 de outubro de 2024
- Cálculo dos dígitos verificadores de CNPJ alfanumérico
- CNPJ, Receita Federal
- Manual de cálculo do dígito verificador do CNPJ, Receita Federal
- CNPJ Alfanumérico, Receita Federal
- Perguntas e respostas: CNPJ alfanumérico, Receita Federal
- Instrução Normativa RFB nº 2.229/2024, no Sijut2
See also CPF, State registration (IE), Legal nature
Last updated on
