NFS-e access key

The 50-digit access key of the national NFS-e, the service invoice of the Sistema Nacional NFS-e.

  • Parity matrix

Validate

Validates the 50-digit access key of a national NFS-e: municipality code (7), generator environment ambGer (1), tax id type (1), tax id (14), NFS-e number nNFSe (13), year and month AAMM (4), numeric code (9) and check digit (1).

  • The key may start with NFS, the prefix of the XML Id attribute, in any case. Whitespace around the value is ignored.
  • The DANFSe prints the key as a single block, so it has no printed mask (there is no nfseKey.format). The 8 fields (municipality code, ambGer, tax id type, tax id, nNFSe, AAMM, numeric code and check digit) may be written apart: any run of whitespace, ., - or / is accepted between two fields, as cpf.isValid reads its mask. A separator inside a field, or between the NFS prefix and the key, makes the value invalid.
  • Only a string is read. Any other type returns false.
  • The municipality code must start with an IBGE state code. The function checks only that prefix and does not look the municipality up.
  • ambGer must be 1 (municipality system) or 2 (Sistema Nacional NFS-e).
  • Tax id type 1 is a CPF, left-padded with 000. Type 2 is a CNPJ. The CPF or CNPJ must have valid check digits of its own.
  • An alphanumeric CNPJ is accepted with type 2, as cnpj.isValid with version 2 reads it: letters only in the 14 tax id positions, in any case. The alphanumeric schema comes from the restricted-production (RTC) package of 2026-07-27. The service has handled the alphanumeric CNPJ in production since 2026-08-10, while the production XSD of 2026-02-09 still types the key as digits only.
  • The letters of an alphanumeric CNPJ stand in the 14 positions of the tax id (10 to 23 of the key), as TSIdNFSe of the schema bundle of 2026-07-27 types them.
  • The NFS-e number cannot be all zeros. The month must be 01 to 12.
  • The check digit is a modulus 11 over the first 49 characters, weights 2 to 9 from the right. A remainder of 0 or 1 gives 0. A letter counts as its ASCII code minus 48 (A is 17), by analogy with NT Conjunta 2025.001.
  • No official document states the weights or the remainder rule; the documents only say "módulo 11". The rule was confirmed against more than a hundred NFS-e keys from public repositories, from both environments, with remainders 0, 1 and 10 among them.
  • The example key in item 9.1 of the Guia do Emissor v1.2 is not valid: its check digit does not match and its CNPJ is invalid.
  • The keys of the municipal NFS-e models that are not the national standard are out of scope, and so is the 44-digit DF-e key (use nfeKey.isValid).
ParameterTypeRequired
valuestringyes
returnsboolean

Check if the access key (chave de acesso) of a national NFS-e, the Nota Fiscal de Serviço eletrônica of the Sistema Nacional NFS-e, is valid.

  • The key is one block of 50 characters, Cód.Mun.(7) Amb.Ger.(1) Tipo de Inscrição Federal(1) Inscrição Federal(14) nNFSe(13) AAMM(4) Cód.Num.(9) DV(1), all digits except an alphanumeric CNPJ in the Inscrição Federal.
  • The NFS literal the Id attribute of infNFSe puts in front of the key is stripped, with surrounding whitespace.
  • The DANFSe prints the key as a single block, so it has no printed mask. The boundaries between its 8 fields accept the mask characters isValidCpf reads (whitespace, ., - or /, alone or in a run), while a separator inside a field makes the value invalid.
  • The municipality code must start with an IBGE UF code; it is not looked up in the IBGE table.
  • ambGer must be 1 (the system of the municipality) or 2 (the Sistema Nacional NFS-e), and the registration type 1 (a CPF, left padded with 000) or 2 (a CNPJ, numeric or alphanumeric), with a CPF or CNPJ whose own check digits are valid. Letters are accepted in a CNPJ only, and lower case is read as upper case, as isValidCnpj with { version: 2 } reads it.
  • nNFSe must not be all zeros and the month must be 01 to 12.
  • The check digit is a modulus 11 over the first 49 characters, weights 2 to 9 cycling from the right, where a remainder of 0 or 1 gives 0. A letter counts as its ASCII code minus 48 (A is 17). No official document states it: the NFS-e technical notes 001 to 009, the Anexo I and the Perguntas e Respostas of 08/09/2026 are silent, and Nota Técnica Conjunta 2025.001, whose ASCII minus 48 rule covers the DF-e key, lists the documents it covers (NF-e, NFC-e, CT-e, CT-e OS, GTV-e, MDF-e, BP-e, BP-e TM, NF3e and NFCom) without the NFS-e. The rule is taken by analogy with that NT and the CNPJ's own check digits.
  • The letters follow TSIdNFSe of the schema bundle of 2026-07-27, in the positions of the Inscrição Federal (10 to 23). The production bundle of 09/02/2026 still types the key [0-9]{50}.
  • The municipal NFS-e models that are not the national standard are out of scope.
import { isValidNfseKey } from '@brazilian-utils/brazilian-utils';

isValidNfseKey('35503082258716523000119000000000001226011357924683'); // true (CNPJ issuer, SP)
isValidNfseKey('NFS35503082258716523000119000000000001226011357924683'); // true (XML Id prefix)
isValidNfseKey('43149021100040364478829000000000105725120484407255'); // true (CPF issuer, RS)
isValidNfseKey('35503082212ABC34501DE35000000000001226091357924682'); // true (alphanumeric CNPJ issuer)
isValidNfseKey('35503082258716523000119000000000001226011357924684'); // false (check digit)
isValidNfseKey('3550308 2 2 58716523000119 0000000000012 2601 135792468 3'); // true (separators between the fields)
Code: brazilian-utils/javascript
Try it with JavaScript isValidNfseKey
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 (29) and the result in each library nfseKey.isValid

Parse

Removes the formatting of a national NFS-e access key and keeps digits and upper-case letters, capped at 50 characters.

  • Letters before the first digit are dropped, the NFS prefix of the XML Id attribute included. Letters after it are kept in upper case, because an alphanumeric CNPJ carries them. nfseKey.isValid checks where they stand.
  • Every other character is removed. A partial key is kept as far as it goes.
  • A number is read only when it is a safe non-negative integer. Any other number returns an empty string.
  • The result is the single block the DANFSe prints, so there is no nfseKey.format.
ParameterTypeRequired
valuestring | numberyes
returnsstring

Remove everything but the digits and the letters of an alphanumeric CNPJ from the access key of a national NFS-e, and cap the result to 50 characters.

  • Letters are upper cased, as parseCnpj with { version: 2 } does, and the letters in front of the first digit are dropped, the NFS prefix of the XML Id attribute included, since the key opens with digits. isValidNfseKey checks that the letters left stand in a CNPJ.

  • That is the form the leiaute stores the key in and the one the DANFSe prints, a single block, which is why there is no formatNfseKey.

import { parseNfseKey } from '@brazilian-utils/brazilian-utils';

parseNfseKey('NFS35503082258716523000119000000000001226011357924683');
// '35503082258716523000119000000000001226011357924683'

parseNfseKey('3550308 2 2 58716523000119 0000000000012 2601 135792468 3');
// '35503082258716523000119000000000001226011357924683'

parseNfseKey('nfs3550308 2 2 12.abc.345/01de-35 0000000000012 2609 135792468 2');
// '35503082212ABC34501DE35000000000001226091357924682'
Code: brazilian-utils/javascript
Try it with JavaScript parseNfseKey
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 (16) and the result in each library nfseKey.parse

Decode

Parses a national NFS-e access key into its fields. It accepts the same input as nfseKey.isValid and returns null exactly when that function returns false.

  • The separators between fields are accepted as in nfseKey.isValid. The NFS prefix must touch the key. Only a string is read: any other type returns null.
  • Fields: municipalityCode (7 digits, a string), stateCode (the 2-letter UF read from the first 2 digits of the municipality code), generatorEnvironment (1 municipality, 2 Sistema Nacional NFS-e), taxIdType (cpf or cnpj), taxId, number (the NFS-e number, a number from 1 to 9999999999999), year, month (1 to 12), code (the numeric code, a string) and checkDigit (a number).
  • The tax id is the 11-digit CPF without the 000 padding of the key, or the 14-character CNPJ, numeric or alphanumeric, in upper case.
  • The year is 2000 plus the 2 digits of the key. The numeric code keeps its 9 digits, leading zeros included.
ParameterTypeRequired
valuestringyes
returnsNfseKeyInfo | null

Parse the access key of a national NFS-e into its fields, as an NfseKeyInfo. Accepts the same input forms as isValidNfseKey.

  • Returns municipalityCode, stateCode, generatorEnvironment, taxIdType, taxId, number, year, month, code and checkDigit.
  • generatorEnvironment is an NfseKeyGeneratorEnvironment: 1 the system of the municipality, 2 the Sistema Nacional NFS-e.
  • taxIdType is an NfseKeyTaxIdType, 'cpf' or 'cnpj', and taxId is the 11 digit CPF, without the 000 that pads it in the key, or the 14 character CNPJ, numeric or alphanumeric, in upper case.
  • Returns null when the key is not valid.
import { getNfseKeyInfo } from '@brazilian-utils/brazilian-utils';

getNfseKeyInfo('35503082258716523000119000000000001226011357924683');
// { municipalityCode: '3550308', stateCode: 'SP', generatorEnvironment: 2, taxIdType: 'cnpj',
//   taxId: '58716523000119', number: 12, year: 2026, month: 1, code: '135792468', checkDigit: 3 }

getNfseKeyInfo('43149021100040364478829000000000105725120484407255');
// { municipalityCode: '4314902', stateCode: 'RS', generatorEnvironment: 1, taxIdType: 'cpf',
//   taxId: '40364478829', number: 1057, year: 2025, month: 12, code: '048440725', checkDigit: 5 }

getNfseKeyInfo('35503082212ABC34501DE35000000000001226091357924682');
// { municipalityCode: '3550308', stateCode: 'SP', generatorEnvironment: 2, taxIdType: 'cnpj',
//   taxId: '12ABC34501DE35', number: 12, year: 2026, month: 9, code: '135792468', checkDigit: 2 }

getNfseKeyInfo('invalid'); // null

Source: the technical documentation of the Sistema Nacional NFS-e, whose schema types TSIdNFSe and TSChaveNFSe and ANEXO I field NFSe/infNFSe/id define the layout and the rules E1280 and E1284, the manual da emissão por decisão administrativa ou judicial, which names the modulus 11 check digit, Nota Técnica SE/CGNFS-e 008 (item 2.1.1), which prints the key as a single block, the schemas updated for the alphanumeric CNPJ (the restricted-production bundle v1.01-20260727; the service handles the alphanumeric CNPJ in production since 2026-08-10, while the production bundle of 2026-02-09 is still digits only) and Nota Técnica Conjunta 2025.001, whose ASCII minus 48 rule for the NF-e key the check digit borrows.

Code: brazilian-utils/javascript
Try it with JavaScript getNfseKeyInfo
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 (28) and the result in each library nfseKey.getInfo

Official sources

See also NF-e access key, Municipalities

Last updated on

On this page