NF-e access key

The 44-character access key of NF-e, NFC-e, CT-e, MDF-e and the other DF-e models.

  • Parity matrix

Validate

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 on nSiteAutoriz and leave 7 digits for cNF.
  • 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 a cNF equal 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 XML Id prefixes (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 0 to 9, and 17 to 42 for A to Z, as in the alphanumeric CNPJ.
  • GTV-e (64) accepts tpEmis 1, 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 with nfeKey.getInfo and check its taxId with cnpj.isValid, or the last 11 digits of a zero-padded taxId with cpf.isValid).
ParameterTypeRequired
valuestringyes
returnsboolean

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, as isValidCnpj does 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 XML Id prefixes (NFe, CTe, MDFe, BPe, NF3e, NFCom) are stripped first.
  • tpEmis must be one the MOC of that model assigns (table below).
  • For NF-e and NFC-e the cNF must 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 a cNF equal 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 getNfeKeyInfo and pass its taxId to isValidCnpj, or the last 11 digits of a zero padded taxId to isValidCpf, 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.
ModeltpEmis 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.

Code: brazilian-utils/javascript
Try it with JavaScript isValidNfeKey
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (60) and the result in each library nfeKey.isValid

Format

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.pad first left-pads the key with zeros to 44 characters ("12345" gives "0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 2345").
  • The XML Id prefixes (NFe, CTe, MDFe, BPe, NF3e, NFCom) are stripped first, with the whitespace around them, the way nfeKey.parse reads them. Until 2.4.0 the prefix was not stripped, so the digit of NF3e ended 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: true returned the full zero mask.
ParameterTypeRequired
valuestringyes
optionsFormatNfeKeyOptionsno
options.padbooleanno
returnsstring

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): pad left pads the value with zeros up to the 44 characters of a complete access key (default false). An empty value, or one without digits, gives '' even with pad.
  • 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, NF3e and NFCom prefixes of the Id attribute of the XML are stripped first, as parseNfeKey reads them.
  • A value that is neither a string nor a non-negative safe integer (-1, 1.5, a bigint, an object) gives ''.
  • Use isValidNfeKey to 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'
Code: brazilian-utils/javascript
Try it with JavaScript formatNfeKey
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (31) and the result in each library nfeKey.format

Parse

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 Id prefixes (NFe, CTe, MDFe, BPe, NF3e, NFCom), with any whitespace around them. The prefix has to go first because NF3e carries 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).
ParameterTypeRequired
valuestring | numberyes
returnsstring

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 Id prefixes (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)
Code: brazilian-utils/javascript
Try it with JavaScript parseNfeKey
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (20) and the result in each library nfeKey.parse

Decode

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) and number (1 to 999999999) as numbers, emissionType (the tpEmis code, a number), code (the numeric code as a string, keeping its leading zeros) and checkDigit (a number). An alphanumeric CNPJ keeps its uppercase letters.
  • For NFCom and NF3e (models 62 and 66), code has 7 digits and the result also carries authorizationSite (nSiteAutoriz, a number from 0 to 9). The other models have no authorizationSite.
  • taxId is 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. A taxId with a letter is always an alphanumeric CNPJ. A padded CPF and a CNPJ that starts with 000 look alike, so check it with cpf.isValid (on the last 11 digits) or cnpj.isValid when the type matters.
  • It returns null exactly when nfeKey.isValid returns false.
ParameterTypeRequired
valuestringyes
returnsNfeKeyInfo | 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, code and checkDigit.
  • For NFCom and NF3e (models '62' and '66') the result also carries authorizationSite and code is 7 digits instead of 8.
  • taxId is 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. A taxId with a letter is always an alphanumeric CNPJ; a padded CPF and a CNPJ starting with 000 look alike, so check it with isValidCpf or isValidCnpj when 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'); // null
Code: brazilian-utils/javascript
Try it with JavaScript getNfeKeyInfo
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (22) and the result in each library nfeKey.getInfo

Official sources

See also CNPJ

Last updated on

On this page