NF-e access key
The 44-character access key of NF-e, NFC-e, CT-e, MDF-e and the other DF-e models.
Validate
- JavaScript library
- Python library
- Go library13 cases fail
- Ruby library12 cases fail
- Rust library14 cases fail
- .NET library13 cases fail
- Erlang library
Validates a 44-character DF-e access key: NF-e (55), NFC-e (65), CT-e (57), MDF-e (58), CT-e OS (67), GTV-e (64), BP-e (63), NF3e (66) and NFCom (62). The CF-e-SAT (59) is not accepted.
- The cUF must be a state and the month (
AAMM) must be 01 to 12. The model must be one of the above. The emission type (tpEmis) must be one that the MOC of that model assigns: 1 to 7 and 9 for NF-e and NFC-e; 1, 3, 4, 5, 7 and 8 for CT-e; 1, 5, 7 and 8 for CT-e OS; 1, 2, 7 and 8 for GTV-e; 1, 2 and 3 for MDF-e; 1 and 2 for BP-e, NF3e and NFCom. - The key is
cUF(2) AAMM(4) CNPJ/CPF(14) mod(2) serie(3) nNF(9) tpEmis(1) cNF(8) cDV(1). NFCom and NF3e spend position 36 onnSiteAutorizand leave 7 digits forcNF. - For NF-e and NFC-e, the numeric code (
cNF) must pass rule B03-10 of the MOC (no repeated or sequential values from the list of 20 the rule gives, and not equal to the document number). The rule applies to the documents sent after NT 2019.001, and NF-e software commonly used acNFequal to the document number before it, so a key authorized earlier can be rejected. - The function rejects a document number of all zeros. The check digit is a modulus 11 over the first 43 characters, with weights 2 to 9 cycling from the right; a remainder of 0 or 1 gives check digit 0.
- The 44 characters may be grouped in 4 by whitespace,
.,-or/, alone or in a run ("3517 - 0458 ..."). A separator inside a group of 4, or any other character, makes the key invalid. The function first strips the XMLIdprefixes (NFe,CTe,MDFe,BPe,NF3e,NFCom, in any letter case), with any whitespace between the prefix and the first group. - Positions 7 to 18 (the root and order of the issuer's CNPJ) may hold the letters of an alphanumeric CNPJ. The current schemas type the key as
[0-9]{6}[0-9A-Z]{12}[0-9]{26}(NT Conjunta 2025.001, NF-e package PL_010), where older ones had 44 digits. A letter anywhere else, including the CNPJ check digits in positions 19 and 20, is rejected. Lowercase is read as uppercase, but a non-ASCII letter that upper-cases into an ASCII one (ſ,ß) is rejected. A CPF issuer is always 11 digits left-padded with zeros, so a letter there always belongs to an alphanumeric CNPJ. 2.4.0 accepted digits only. - In the check digit, each character counts as its ASCII code minus 48: the digit itself for
0to9, and 17 to 42 forAtoZ, as in the alphanumeric CNPJ. - GTV-e (64) accepts
tpEmis1, 2, 7 and 8 (CT-e MOC, field D15). The current package PL_CTe_400_RTC lists only 1 and 2, but 7 (SVC-RS) and 8 (SVC-SP) are kept so keys authorized under PL_CTe_400 still validate, since a key carries no schema version. This is the 2.4.0 behavior. - A value that is not a string returns
false. The CPF or CNPJ check digits of the issuer are not checked, only the check digit of the key (read the key withnfeKey.getInfoand check itstaxIdwithcnpj.isValid, or the last 11 digits of a zero-paddedtaxIdwithcpf.isValid).
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
| returns | boolean |
Check if a DF-e access key (chave de acesso) is valid. Covers every DF-e with a 44 character access key; the CF-e-SAT (59) is out.
- Models: NF-e (55), NFC-e (65), CT-e (57), MDF-e (58), CT-e OS (67), GTV-e (64), BP-e (63), NF3e (66) and NFCom (62).
- Every character is a digit except positions 7 to 18, the root and order of the issuer's CNPJ, which may hold the letters of an alphanumeric CNPJ: the current schemas (NF-e PL_010
TChNFe, CT-e PL_CTe_400_RTC, MDF-e 3.00b, NFCom) type the key as[0-9]{6}[0-9A-Z]{12}[0-9]{26}, in production for the NF-e from 01/07/2026 (NT 2026.004). A letter anywhere else, the CNPJ check digits in positions 19 and 20 included, is rejected. The schema admits upper case only; lower case is read as upper case, asisValidCnpjdoes with{ version: 2 }. A non-ASCII letter that upper cases into an ASCII one (ſ,ß) is rejected. - The 44 characters may be grouped in 4 by whitespace,
.,-or/. The XMLIdprefixes (NFe,CTe,MDFe,BPe,NF3e,NFCom) are stripped first. tpEmismust be one the MOC of that model assigns (table below).- For NF-e and NFC-e the
cNFmust pass rule B03-10 of the MOC (no repeated or sequential values, not the document number). The rule applies to the documents sent after NT 2019.001, and NF-e software commonly used acNFequal to the document number before it, so a key authorised earlier can be turned down. - The check digits of the issuer's CPF or CNPJ are not checked, only the key's own check digit. Read the key with
getNfeKeyInfoand pass itstaxIdtoisValidCnpj, or the last 11 digits of a zero paddedtaxIdtoisValidCpf, to check the issuer as well. - A document number of all zeros is rejected. The check digit is a modulus 11 over the first 43 characters, each valued at its ASCII code minus 48 (
A= 17 ...Z= 42), as NT Conjunta 2025.001 sets it.
| Model | tpEmis accepted |
|---|---|
| NF-e (55), NFC-e (65) | 1 to 7 and 9 |
| CT-e (57) | 1, 3, 4, 5, 7, 8 |
| CT-e OS (67) | 1, 5, 7, 8 |
| GTV-e (64) | 1, 2, 7, 8 (see below) |
| MDF-e (58) | 1, 2, 3 |
| BP-e (63), NF3e (66), NFCom (62) | 1, 2 |
For the GTV-e, the current CT-e schema package (PL_CTe_400_RTC) enumerates tpEmis 1 (normal) and 2 (contingência off-line) only; the earlier PL_CTe_400 also had 7 and 8 (autorização pela SVC-RS and SVC-SP). The key carries no schema version, so the library accepts all four, and the keys of GTV-e authorised under the earlier package keep validating.
import { isValidNfeKey } from '@brazilian-utils/brazilian-utils';
isValidNfeKey('35170458716523000119550010000000121000123458'); // true (NF-e, SP)
isValidNfeKey('NFe35170458716523000119550010000000121000123458'); // true (XML Id prefix)
isValidNfeKey('CTe35170458716523000119570010000000128000123452'); // true (CT-e authorised by the SVC-SP)
isValidNfeKey('3517 0458 7165 2300 0119 5500 1000 0000 1210 0012 3458'); // true (masked)
isValidNfeKey('3517.0458.7165.2300.0119.5500.1000.0000.1210.0012.3458'); // true (any of the mask characters)
isValidNfeKey('35260712ABC34501DE35550010000001231102030403'); // true (alphanumeric CNPJ 12ABC34501DE35)
isValidNfeKey('35260712ABC34501DEA5550010000001231102030408'); // false (a letter in position 19, a CNPJ check digit)
isValidNfeKey('351 70458716523000119550010000000121000123458'); // false (a separator inside a group of 4)
isValidNfeKey('99170458716523000119550010000000121000123458'); // false (invalid cUF)
isValidNfeKey('35170458716523000119010010000000121000123450'); // false (invalid mod)
isValidNfeKey('35170458716523000119550010000000128000123455'); // false (the NF-e MOC does not assign tpEmis 8)
isValidNfeKey('35170458716523000119550010000000121000000003'); // false (cNF 00000000, rule B03-10)Source: MOC NF-e, NF-e schemas, NT Conjunta 2025.001 (CNPJ alfanumérico) and the MOCs cited in src/is-valid-nfe-key/is-valid-nfe-key.ts.
Try it with JavaScript isValidNfeKey
Shared test cases (60) and the result in each library nfeKey.isValid
Format
- JavaScript library
- Python library
- Go library5 cases fail
- Ruby library9 cases fail
- Rust library5 cases fail
- .NET library5 cases fail
- Erlang library
Formats a DF-e access key into groups of 4 characters separated by spaces, as the DANFE and the other auxiliary documents print it. It does not validate the key (use nfeKey.isValid).
Every auxiliary document prints the key in this form: the DANFE of the NF-e and the NFC-e, the DACTE of the CT-e, the CT-e OS and the GTV-e, the DAMDFE of the MDF-e, the DABPE of the BP-e, the DANF3E of the NF3e and the DANFE-COM of the NFCom.
- The function groups a masked or partial key as far as its characters go.
options.padfirst left-pads the key with zeros to 44 characters ("12345"gives"0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 2345"). - The XML
Idprefixes (NFe,CTe,MDFe,BPe,NF3e,NFCom) are stripped first, with the whitespace around them, the waynfeKey.parsereads them. Until 2.4.0 the prefix was not stripped, so the digit ofNF3eended up in the key. - The upper-cased letters of an alphanumeric CNPJ are kept in positions 7 to 18. A letter anywhere else is dropped, and the positions are counted on the characters kept. 2.4.0 dropped every letter.
- A value that is neither a string nor a safe non-negative integer (an object,
true,-1,1.5, a bigint) returns an empty string instead of throwing. A number is read as the string of its digits. Characters after the 44th are dropped. - Returns an empty string when there is nothing to format. Until 2.4.0 a value with no digits and
pad: truereturned the full zero mask.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
options | FormatNfeKeyOptions | no |
options.pad | boolean | no |
| returns | string |
Format a DF-e (Documento Fiscal eletrônico) access key into groups of 4 characters separated by spaces, the form the DANFE, DACTE, DAMDFE, DABPE, DANF3E and DANFE-COM print it in.
- Options (
FormatNfeKeyOptions):padleft pads the value with zeros up to the 44 characters of a complete access key (defaultfalse). An empty value, or one without digits, gives''even withpad. - A masked or partial key is grouped as far as its characters go.
- The letters of an alphanumeric CNPJ are kept, upper cased, in positions 7 to 18; a letter anywhere else is dropped.
- The
NFe,CTe,MDFe,BPe,NF3eandNFComprefixes of theIdattribute of the XML are stripped first, asparseNfeKeyreads them. - A value that is neither a string nor a non-negative safe integer (
-1,1.5, a bigint, an object) gives''. - Use
isValidNfeKeyto check a key.
import { formatNfeKey } from '@brazilian-utils/brazilian-utils';
formatNfeKey('35170458716523000119550010000000121000123458');
// '3517 0458 7165 2300 0119 5500 1000 0000 1210 0012 3458'
formatNfeKey('35260712abc34501de35550010000001231102030403');
// '3526 0712 ABC3 4501 DE35 5500 1000 0001 2311 0203 0403' (alphanumeric CNPJ)
formatNfeKey('NF3e35170458716523000119550010000000121000123458');
// '3517 0458 7165 2300 0119 5500 1000 0000 1210 0012 3458' (XML Id prefix)
formatNfeKey('12345'); // '1234 5'
formatNfeKey('12345', { pad: true });
// '0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 2345'Try it with JavaScript formatNfeKey
Shared test cases (31) and the result in each library nfeKey.format
Parse
- JavaScript library
- Python library
- Go library4 cases fail
- Ruby library6 cases fail
- Rust library4 cases fail
- .NET library4 cases fail
- Erlang library
Removes the formatting of a DF-e access key and keeps only the characters of the key, capped at 44: digits, plus the upper-cased letters of an alphanumeric CNPJ in positions 7 to 18.
- The function first strips the XML
Idprefixes (NFe,CTe,MDFe,BPe,NF3e,NFCom), with any whitespace around them. The prefix has to go first becauseNF3ecarries a digit of its own that is not part of the key. - A letter anywhere else is dropped, like any other character outside the key. 2.4.0 dropped every letter.
- A shorter value passes through as far as it goes, so the grouping of a key still being typed can be stripped with it. It does not check the key (use
nfeKey.isValid). - A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number gives an empty string (2.4.0 read the digits of any number, sign and decimal point dropped).
| Parameter | Type | Required |
|---|---|---|
value | string | number | yes |
| returns | string |
Remove the formatting of a DF-e access key (chave de acesso), keep only its characters, and cap the result to 44 characters.
-
The characters kept are the digits and, in positions 7 to 18, the letters of an alphanumeric CNPJ, upper cased; a letter anywhere else is dropped.
-
The XML
Idprefixes (NFe,CTe,MDFe,BPe,NF3e,NFCom) are stripped first.
import { parseNfeKey } from '@brazilian-utils/brazilian-utils';
parseNfeKey('3517 0458 7165 2300 0119 5500 1000 0000 1210 0012 3458');
// '35170458716523000119550010000000121000123458'
parseNfeKey('NFe35170458716523000119550010000000121000123458');
// '35170458716523000119550010000000121000123458'
parseNfeKey('3526 0712 abc3 4501 de35 5500 1000 0001 2311 0203 0403');
// '35260712ABC34501DE35550010000001231102030403' (alphanumeric CNPJ)Try it with JavaScript parseNfeKey
Shared test cases (20) and the result in each library nfeKey.parse
Decode
- JavaScript library
- Python library
- Go library9 cases fail
- Ruby library9 cases fail
- Rust library
- .NET library9 cases fail
- Erlang library
Parses a DF-e access key into its fields. It accepts the same input as nfeKey.isValid and returns null when the key is not valid.
- Fields:
stateCode(the 2-letter UF read from the cUF),year(4 digits),month(1 to 12),taxId(issuer tax id),model(the 2-digit model as a string, such as"55"),series(0 to 999) andnumber(1 to 999999999) as numbers,emissionType(thetpEmiscode, a number),code(the numeric code as a string, keeping its leading zeros) andcheckDigit(a number). An alphanumeric CNPJ keeps its uppercase letters. - For NFCom and NF3e (models 62 and 66),
codehas 7 digits and the result also carriesauthorizationSite(nSiteAutoriz, a number from 0 to 9). The other models have noauthorizationSite. taxIdis the 14 characters of positions 7 to 20 as written: a numeric CNPJ, an alphanumeric CNPJ (upper-cased) or a CPF left-padded with zeros. AtaxIdwith a letter is always an alphanumeric CNPJ. A padded CPF and a CNPJ that starts with000look alike, so check it withcpf.isValid(on the last 11 digits) orcnpj.isValidwhen the type matters.- It returns
nullexactly whennfeKey.isValidreturnsfalse.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
| returns | NfeKeyInfo | null |
Parse a DF-e access key into its fields. Accepts the same input forms as isValidNfeKey and returns null when the key is not valid.
- Returns an
NfeKeyInfo:stateCode,year,month,taxId,model(NfeKeyModel),series,number,emissionType,codeandcheckDigit. - For NFCom and NF3e (models
'62'and'66') the result also carriesauthorizationSiteandcodeis 7 digits instead of 8. taxIdis the 14 characters of positions 7 to 20 as written: a numeric CNPJ, an alphanumeric CNPJ (upper cased), or a CPF left padded with zeros. AtaxIdwith a letter is always an alphanumeric CNPJ; a padded CPF and a CNPJ starting with000look alike, so check it withisValidCpforisValidCnpjwhen the type matters.
import { getNfeKeyInfo } from '@brazilian-utils/brazilian-utils';
getNfeKeyInfo('35170458716523000119550010000000121000123458');
// { stateCode: 'SP', year: 2017, month: 4, taxId: '58716523000119', model: '55',
// series: 1, number: 12, emissionType: 1, code: '00012345', checkDigit: 8 }
getNfeKeyInfo('35170458716523000119620010000000121000123450');
// { stateCode: 'SP', year: 2017, month: 4, taxId: '58716523000119', model: '62',
// series: 1, number: 12, emissionType: 1, code: '0012345', checkDigit: 0, authorizationSite: 0 }
getNfeKeyInfo('35260712ABC34501DE35550010000001231102030403');
// { stateCode: 'SP', year: 2026, month: 7, taxId: '12ABC34501DE35', model: '55',
// series: 1, number: 123, emissionType: 1, code: '10203040', checkDigit: 3 }
getNfeKeyInfo('invalid'); // nullTry it with JavaScript getNfeKeyInfo
Shared test cases (22) and the result in each library nfeKey.getInfo
Official sources
- confaz.fazenda.gov.br/legislacao/arquivo-manuais/…/moc7-visao-geral.pdf
- confaz.fazenda.gov.br/legislacao/ajustes/…/AJ_009_07
- confaz.fazenda.gov.br/legislacao/ajustes/…/AJ036_19
- confaz.fazenda.gov.br/legislacao/ajustes/…/ajuste-sinief-03-20
- dfe-portal.svrs.rs.gov.br/CTE/Documentos
- dfe-portal.svrs.rs.gov.br/BPE/Documentos
- dfe-portal.svrs.rs.gov.br/NF3e/Documentos
- dfe-portal.svrs.rs.gov.br/NFCOM/Documentos
- dfe-portal.svrs.rs.gov.br/NFE/Documentos
- nfe.fazenda.gov.br/portal/exibirArquivo.aspx
- nfe.fazenda.gov.br/portal/listaConteudo.aspx
See also CNPJ
Last updated on
