Toda NF-e autorizada no Brasil carrega uma chave de acesso de 44 posições. É ela que o seu sistema usa para achar a nota na SEFAZ (a Secretaria da Fazenda que autoriza a nota), conferir se foi cancelada ou, quando você participa da operação, baixar o XML. Parece só um número comprido, mas cada trecho tem significado, do estado ao dígito verificador. Quem entende essa estrutura valida a chave de acesso localmente em microssegundos e só gasta requisição com chaves bem formadas.
Os 44 dígitos da chave de acesso da NF-e
A chave de acesso é a concatenação de nove campos da própria nota. O Manual de Orientação do Contribuinte (MOC), publicado na seção de manuais do Portal da NF-e, define a ordem e o tamanho de cada um. A mesma estrutura vale para a NF-e (modelo 55) e para a NFC-e (modelo 65, a nota de consumidor do varejo). Por isso, um único validador atende as duas.
| Campo | Posições | Dígitos | O que guarda | Exemplo |
|---|---|---|---|---|
| cUF | 1 a 2 | 2 | Código IBGE da UF do emitente | 35 (SP) |
| AAMM | 3 a 6 | 4 | Ano e mês de emissão | 2609 |
| CNPJ ou CPF | 7 a 20 | 14 | Documento do emitente | 11222333000181 |
| mod | 21 a 22 | 2 | Modelo do documento | 55 |
| serie | 23 a 25 | 3 | Série da nota | 001 |
| nNF | 26 a 34 | 9 | Número da nota | 000012345 |
| tpEmis | 35 | 1 | Forma de emissão | 1 (normal) |
| cNF | 36 a 43 | 8 | Código numérico aleatório | 48213075 |
| cDV | 44 | 1 | Dígito verificador | 5 |
Juntando a última coluna, sai a chave de acesso fictícia usada nos exemplos: 35260911222333000181550010000123451482130755.

UF, data e emitente
Os dois primeiros dígitos seguem a tabela de UF do IBGE: 35 é São Paulo, 31 é Minas Gerais, 43 é Rio Grande do Sul. Só existem 27 códigos válidos, e qualquer outro valor indica uma chave de acesso corrompida.
O AAMM traz ano e mês da emissão (2609 para setembro de 2026), e o mês precisa estar entre 01 e 12.
As 14 posições seguintes guardam o CNPJ do emitente. Quando o emitente é pessoa física, como o produtor rural em alguns estados, o CPF ocupa o campo, completado com zeros à esquerda. Por isso, o validador não pode assumir que aquele trecho sempre é um CNPJ.
Modelo, série e número
O modelo 55 é NF-e, e o 65, NFC-e. A série tem três dígitos, de 000 a 999, e o número da nota tem nove, com zeros à esquerda. Juntos, CNPJ, modelo, série e número apontam uma única nota daquele emitente.
Forma de emissão, código numérico e DV
O tpEmis indica se a nota saiu em emissão normal (1), no Regime Especial da Nota Fiscal Fácil (3) ou em contingência, o modo usado quando a SEFAZ está fora do ar: FS-IA (2), EPEC (4), FS-DA (5), SVC-AN (6), SVC-RS (7) ou a contingência off-line da NFC-e (9). O valor 8 não é usado na NF-e. Reemitir a nota em outra forma de emissão muda a chave de acesso.
O cNF é um código de oito dígitos que o sistema emissor gera ao acaso, para que ninguém deduza chaves de terceiros só incrementando o número da nota. Gerá-lo em sequência anula essa proteção. Por fim, o DV protege a chave de acesso contra erro de digitação.
Na prática: a chave de acesso já traz UF, mês, emitente e modelo. Antes de qualquer chamada de rede, seu código consegue responder se a nota é de São Paulo, se é NFC-e e se o CNPJ bate com o fornecedor esperado.
Dígito verificador NF-e: cálculo pelo módulo 11
O dígito verificador da chave de acesso usa módulo 11 (o resto da divisão por 11), com pesos de 2 a 9. O erro mais comum é aplicar os pesos da esquerda para a direita.
O passo a passo do cálculo
- Pegue os 43 primeiros caracteres da chave.
- Percorra da direita para a esquerda, multiplicando cada dígito pelos pesos 2, 3, 4, 5, 6, 7, 8, 9 e recomeçando em 2 depois do 9.
- Some todos os produtos.
- Calcule o resto da divisão da soma por 11.
- Se o resto for 0 ou 1, o DV é 0. Caso contrário, o DV é 11 menos o resto.
No nosso exemplo, a soma ponderada dá 589. 589 dividido por 11 deixa resto 6, e o DV é 11 menos 6, ou seja, 5, o último dígito da chave.
Código em Python
A função abaixo já está pronta para o CNPJ alfanumérico e para o prefixo NFe do XML, dois pontos detalhados na próxima seção. Em vez de int(ch), ela usa o código ASCII do caractere menos 48. Como 48 é o código do “0”, os dígitos continuam valendo 0 a 9, e as letras seguem a regra da Nota Técnica.
import re
UFS = {"11", "12", "13", "14", "15", "16", "17", "21", "22", "23", "24",
"25", "26", "27", "28", "29", "31", "32", "33", "35", "41", "42",
"43", "50", "51", "52", "53"}
def calcular_dv(base43):
soma, peso = 0, 2
for ch in reversed(base43):
soma += (ord(ch) - 48) * peso
peso = 2 if peso == 9 else peso + 1
resto = soma % 11
return 0 if resto < 2 else 11 - resto
def normalizar_chave(entrada):
s = str(entrada).strip().upper()
if s.startswith("NFE"): # atributo Id do XML: "NFe" + chave
s = s[3:]
return re.sub(r"[^0-9A-Z]", "", s)
def valida_chave(chave):
# 6 dígitos (UF + AAMM), 12 que aceitam letra (raiz e ordem do CNPJ), 26 dígitos
if not re.fullmatch(r"[0-9]{6}[A-Z0-9]{12}[0-9]{26}", chave):
return False
if chave[:2] not in UFS or not 1 <= int(chave[4:6]) <= 12:
return False
if chave[20:22] not in ("55", "65"):
return False
return calcular_dv(chave[:43]) == int(chave[43])
print(valida_chave(normalizar_chave("3526 0911 2223 3300 0181 5500 1000 0123 4514 8213 0755"))) # True

Código em JavaScript
A versão em Node faz as mesmas checagens, confere também a forma de emissão (tpEmis) e devolve o motivo da recusa, útil para a mensagem ao usuário.
const UFS = new Set(['11','12','13','14','15','16','17','21','22','23','24','25','26','27','28','29','31','32','33','35','41','42','43','50','51','52','53']);
const TP_EMIS = new Set(['1','2','3','4','5','6','7','9']);
function normalizarChave(entrada) {
let s = String(entrada).trim().toUpperCase();
if (s.startsWith('NFE')) s = s.slice(3);
return s.replace(/[^0-9A-Z]/g, '');
}
function dvChave(base43) {
let soma = 0, peso = 2;
for (let i = base43.length - 1; i >= 0; i--) {
soma += (base43.charCodeAt(i) - 48) * peso;
peso = peso === 9 ? 2 : peso + 1;
}
const resto = soma % 11;
return resto < 2 ? 0 : 11 - resto;
}
function validarChave(entrada) {
const chave = normalizarChave(entrada);
if (!/^[0-9]{6}[A-Z0-9]{12}[0-9]{26}$/.test(chave)) return { ok: false, erro: 'formato' };
if (!UFS.has(chave.slice(0, 2))) return { ok: false, erro: 'cUF' };
const mes = Number(chave.slice(4, 6));
if (mes < 1 || mes > 12) return { ok: false, erro: 'AAMM' };
const modelo = chave.slice(20, 22);
if (modelo !== '55' && modelo !== '65') return { ok: false, erro: 'modelo' };
if (!TP_EMIS.has(chave[34])) return { ok: false, erro: 'tpEmis' };
if (dvChave(chave.slice(0, 43)) !== Number(chave[43])) return { ok: false, erro: 'DV' };
return { ok: true, chave, modelo: modelo === '55' ? 'NF-e' : 'NFC-e' };
}
Com as duas funções prontas, sobram as armadilhas da entrada real e, depois, a consulta de verdade. Se você quer os dados completos da nota sem resolver captcha, a API de consulta NF-e do Hub do Desenvolvedor devolve o resultado em JSON ou XML. Dá para testar grátis antes de colocar em produção.
Como validar chave de acesso NF-e antes de consultar
Validar a chave de acesso localmente é o filtro mais barato do pipeline: barra erro de digitação, lixo de planilha e chave truncada antes que virem requisição. A regra de ouro é normalizar primeiro e validar depois.
Máscara, espaços e o prefixo NFe
No DANFE (a versão impressa da nota), ela aparece em 11 grupos de quatro dígitos separados por espaço. Em planilha, às vezes vem com ponto ou traço. No XML autorizado, o atributo Id da tag infNFe tem 47 caracteres, porque traz o prefixo NFe antes dos 44 dígitos.
Por isso, as funções acima removem o prefixo e depois descartam tudo que não é letra ou número. As letras ficam, porque com o CNPJ alfanumérico apagá-las corromperia uma chave válida.
Excel e LibreOffice convertem sequências longas de dígitos em notação científica e guardam só 15 dígitos significativos. Os demais viram zero. Importe a coluna como texto, sempre.
CNPJ alfanumérico dentro da chave de acesso
A Receita Federal mudou a regra de formação do CNPJ pela Instrução Normativa RFB 2.229/2024, e a página oficial do CNPJ alfanumérico explica o novo formato. As oito posições da raiz e as quatro da ordem passam a aceitar letras maiúsculas e números. Os dois dígitos verificadores continuam numéricos, e os CNPJs já existentes não mudam.
Como o CNPJ ocupa as posições 7 a 20, a chave de acesso também muda. A Nota Técnica Conjunta 2025.001, publicada no Portal da NF-e, define três pontos que afetam o seu código:
- A chave continua com 44 posições, e a expressão regular passa a ser
[0-9]{6}[A-Z0-9]{12}[0-9]{26}. Só as 12 primeiras posições do CNPJ aceitam letra. - O cálculo do DV troca cada caractere pelo seu código ASCII menos 48 antes do módulo 11. Dessa forma, “0” a “9” continuam valendo 0 a 9, “A” (ASCII 65) vale 17, “B” vale 18 e assim por diante.
- O código de barras do DANFE, em CODE-128C, só aceita números, e a NT sugere alternar para o CODE-128A quando aparecem letras.
Para NF-e e NFC-e, a NT 2026.004, que complementa a Conjunta com os schemas, pôs a mudança em produção em 01/07/2026. Ou seja, seu sistema já precisa aceitar essas chaves. Um exemplo fictício, com o CNPJ de demonstração 12ABC34501DE35, fica assim: 35260912ABC34501DE35550010000123451482130756. As funções acima validam essa chave sem adaptação.
Se o seu validador também confere o CNPJ extraído da chave, ele precisa seguir a mesma regra do ASCII menos 48. Com emitente pessoa física, esse trecho é 000 seguido do CPF, e aí a validação é a de CPF. O post sobre como validar um CNPJ, inclusive o alfanumérico traz esse algoritmo em detalhe.
Atenção: guardar a chave de acesso em coluna
BIGINTouNUMERICquebra com o CNPJ alfanumérico. UseCHAR(44)ouVARCHAR(44). Mesmo sem letras, guardar como número já apagava os zeros à esquerda.
NF-e ou NFC-e: o modelo muda o caminho
Uma chave de acesso com modelo 65 passa no mesmo cálculo de DV, mas nem todo serviço de consulta trata os dois modelos da mesma forma. Em muitos estados, a NFC-e tem portal próprio, consultado por QR Code. Ler as posições 21 e 22 e rotear a consulta para o serviço certo evita um falso “nota não encontrada”.
Chave válida não significa nota autorizada
O DV só prova que a sequência foi montada de forma consistente. Qualquer pessoa gera uma chave de acesso matematicamente perfeita para uma nota que nunca existiu. Por isso, a validação local serve de filtro, e a resposta final sobre a nota vem sempre da consulta.
A consulta pode trazer situações diferentes de “autorizada”:
- Cancelada: a nota foi autorizada e depois recebeu evento de cancelamento. A chave continua existindo, mas a operação não vale.
- Denegada: a SEFAZ registrou a nota e negou o uso por irregularidade fiscal do emitente ou do destinatário. Aquele número não pode ser reaproveitado em outra nota.
- Não encontrada: a chave não consta na base consultada. Pode ser erro, nota ainda em processamento ou chave inventada.
| Situação | Sintoma | O que fazer |
|---|---|---|
| Chave com espaços ou pontos | Erro de formato com 44 dígitos corretos | Normalizar antes de validar |
| Id do XML colado inteiro | 47 caracteres começando com NFe | Remover o prefixo NFe |
| Dígito trocado | DV não confere | Pedir a chave de novo, sem consultar |
| Dígito faltando | Erro de formato com 43 caracteres | Pedir a chave de novo, sem consultar |
| Chave vinda do Excel | Final da chave zerado | Importar a coluna como texto |
| Modelo 65 no serviço de NF-e | Nota não encontrada | Rotear pelo modelo |
| Nota cancelada | Evento de cancelamento na resposta | Bloquear a entrada no ERP |
| Nota denegada | Uso denegado | Tratar como nota sem validade |
O outro lado, quando a sua própria nota volta recusada, está no artigo sobre como evitar rejeições na emissão de NF-e.

Consulta NF-e por chave de acesso: portal, webservice ou API
Validada, a chave de acesso pode seguir por três caminhos, com custos bem diferentes.
Portal da NF-e
O caminho manual é o Consultar NF-e do Portal Nacional. Você cola a chave, resolve o captcha e vê o resumo. Para a versão completa, o portal exige certificado digital. Serve para conferência pontual, não para integração.
Webservice da SEFAZ
O serviço oficial de consulta de protocolo recebe a chave e responde com o código de situação (cStat), o protocolo e os eventos vinculados. Para usá-lo, você precisa de certificado digital ICP-Brasil, conexão com autenticação mútua, montagem de envelope SOAP e um mapa dos endereços de cada autorizador. O XML completo vem por outro serviço, a distribuição de DF-e (documentos fiscais eletrônicos), disponível apenas para quem participa da operação, como o destinatário.
As situações vistas acima chegam do webservice como códigos, e alguns aparecem o tempo todo:
100e150: autorizado o uso da NF-e (o 150 indica autorização fora de prazo).101: cancelamento homologado.110,301,302e303: uso denegado.217: a nota não consta na base de dados da SEFAZ.656: consumo indevido, bloqueio temporário de quem repete consultas demais.
Quem reconsulta a mesma chave de acesso em loop recebe o 656 e fica um tempo sem resposta para todas as notas, não só para a problemática.
API de consulta
Uma API NF-e de terceiros esconde essa infraestrutura atrás de uma chamada HTTP. Você manda a chave de acesso e recebe o resultado em JSON ou XML, sem captcha.
| Critério | Portal da NF-e | Webservice SEFAZ | API de consulta |
|---|---|---|---|
| Captcha | Sim | Não | Não |
| Certificado digital | Na consulta completa | Sempre | Depende do fornecedor |
| Formato | Página HTML | SOAP e XML | JSON ou XML |
| Automação | Não é o objetivo | Sim, com esforço | Sim |
| Esforço inicial | Nenhum | Alto | Baixo |
Na API, os erros chegam no status HTTP, além do corpo da resposta. 4xx indica problema na sua requisição, e repetir não resolve. 5xx indica falha do servidor e pede nova tentativa. O guia de HTTP status codes para APIs ajuda a montar essa regra.
Quer testar com as suas próprias chaves? A consulta de NF-e por API do Hub entra no mesmo plano que os webservices de CPF, CNPJ, CEP e frete, e você pode fazer chamadas de quantos IPs precisar. Crie a conta de teste e use o validador deste artigo como filtro antes de cada chamada.
Consulta em lote com cache e idempotência
O cenário típico é a conciliação de uma planilha com 3 mil notas. Um loop que chama a API linha a linha desperdiça consultas com chaves duplicadas, chaves inválidas e notas que você consultou ontem.
A abordagem que funciona tem quatro etapas:
- Normalizar e validar cada entrada, separando as inválidas num relatório próprio.
- Deduplicar, porque a mesma chave aparece várias vezes em planilhas reais.
- Buscar no cache antes de ir à rede.
- Consultar em ritmo constante, sem rajadas (é o que evita o
656), gravando o resultado no cache.

O código abaixo reaproveita normalizar_chave e valida_chave do exemplo em Python. Endereço e autenticação são ilustrativos: confira os valores reais no painel do Hub. Se a base mistura NF-e e NFC-e, separe as chaves pelo modelo antes do laço e chame o serviço certo para cada grupo.
import time
import requests
URL_DA_API = "https://URL_DA_API/nfe" # ilustrativo: confira no painel do Hub
TOKEN = "SEU_TOKEN"
TTL_RECENTE = 3600 # mês atual ou anterior: ainda pode ser cancelada
TTL_ANTIGA = 7 * 24 * 3600 # nota mais antiga muda pouco
cache = {} # em produção, use Redis ou uma tabela
def meses_recentes():
agora = time.localtime()
ano, mes = agora.tm_year, agora.tm_mon - 1
if mes == 0:
ano, mes = ano - 1, 12
return {time.strftime("%y%m", agora), f"{ano % 100:02d}{mes:02d}"}
def ttl_para(chave):
return TTL_RECENTE if chave[2:6] in meses_recentes() else TTL_ANTIGA
def consultar(chave, sessao):
"""Devolve (dados, foi_a_rede)."""
item = cache.get(chave)
if item and time.time() < item["expira"]:
return item["dados"], False
resp = sessao.get(URL_DA_API, params={"chave": chave, "token": TOKEN}, timeout=15)
resp.raise_for_status()
dados = resp.json()
cache[chave] = {"dados": dados, "expira": time.time() + ttl_para(chave)}
return dados, True
def consultar_lote(entradas):
validas, invalidas = {}, []
for entrada in entradas:
chave = normalizar_chave(entrada)
if valida_chave(chave):
validas[chave] = None # dict remove duplicadas e mantém a ordem
else:
invalidas.append(entrada)
resultados = {}
with requests.Session() as sessao:
for chave in validas:
resultados[chave], foi_a_rede = consultar(chave, sessao)
if foi_a_rede:
time.sleep(0.5) # pausa só quando saiu para a rede
return resultados, invalidas
O TTL (o tempo de validade no cache) vem do AAMM da chave. Como o AAMM não traz o dia, notas do mês corrente e do anterior contam como recentes, porque uma nota do dia 30 ainda pode ser cancelada no dia 1º, e ficam pouco no cache. As mais antigas raramente mudam de situação e ficam mais. No exemplo, qualquer erro HTTP interrompe o lote. Em produção, capture a exceção por chave, registre as falhas 4xx como definitivas e recoloque as 5xx numa fila de nova tentativa. Expiração e invalidação estão no texto sobre o que é cache e suas estratégias.
Dica: use a própria chave de acesso como chave de idempotência. Com o cache em Redis ou numa tabela, se o job cair no meio e for reiniciado, a nota já gravada não gera nova consulta nem registro duplicado no ERP.
A chave de acesso é naturalmente única, e isso a torna perfeita para UPSERT (inserir ou atualizar) e para restrição de unicidade no banco. O artigo sobre idempotência em APIs e como evitar registros duplicados mostra o padrão completo para quem recebe as notas por webhook ou fila.
Perguntas frequentes sobre a chave de acesso
Quantos dígitos tem a chave de acesso da NF-e?
A chave de acesso tem 44 posições: duas para a UF, quatro para ano e mês, 14 para o CNPJ ou CPF do emitente, duas para o modelo, três para a série, nove para o número, uma para a forma de emissão, oito para o código numérico e uma para o dígito verificador.
Como calcular o dígito verificador da NF-e?
Use módulo 11 sobre os 43 primeiros caracteres, com pesos de 2 a 9 aplicados da direita para a esquerda e reiniciados após o 9. Divida a soma por 11. Se o resto for 0 ou 1, o DV é 0; senão, o DV é 11 menos o resto.
Uma chave de acesso com DV correto garante que a nota existe?
Não. O dígito verificador só confirma que a sequência é consistente. Para saber se a nota foi autorizada, cancelada ou denegada, é preciso consultar a SEFAZ ou uma API que consulte por você.
O CNPJ alfanumérico muda a chave de acesso?
Muda o conteúdo, não o tamanho. As 12 primeiras posições do CNPJ dentro da chave passam a aceitar letras maiúsculas. O DV passa a ser calculado com o valor ASCII de cada caractere menos 48, conforme a Nota Técnica Conjunta 2025.001.
Dá para consultar NF-e pela chave de acesso sem captcha?
Pelo portal, não. O captcha existe para impedir automação. Sem captcha, as opções são o webservice da SEFAZ, que exige certificado digital, ou uma API de consulta que faça essa ponte.
Qual a diferença entre a chave da NF-e e a da NFC-e?
A estrutura da chave de acesso é a mesma. O que muda é o modelo nas posições 21 e 22: 55 para NF-e e 65 para NFC-e. Essa diferença decide para qual serviço a consulta deve ir.
Resumo para levar ao código
Normalize a entrada, valide a chave de acesso e o DV localmente, descarte duplicadas, consulte o cache e só então vá à rede. Com isso, a chave de acesso deixa de ser um campo de texto qualquer e vira um identificador confiável no seu sistema.
Antes de ir para produção, teste com dados reais. Abra sua conta grátis na API de Consulta NF-e do Hub do Desenvolvedor, use o validador deste artigo como primeira camada e veja a chave de acesso das suas notas voltar com os dados completos em JSON.

