nationid
v2.2.1
Published
TypeScript-first, zero-dependency validator for national identity and tax documents from every country.
Maintainers
Readme
nationid
Validador TypeScript-first e zero-dependency para documentos de identidade e fiscais de qualquer país.
🎮 Demo ao vivo: https://lu1tr0n.github.io/nationid_example/ — teste todos os países e helpers em 3 idiomas. 📖 Referência da API: https://lu1tr0n.github.io/nationid/ 📊 Benchmarks: ver BENCHMARKS.md
nationid é uma biblioteca focada e abrangente para validar documentos de identidade e CPF/CNPJ. Vem com verificação de checksum (não apenas regex), formatação e normalização adequadas, e funciona em Node, browsers, Bun, Deno e edge runtimes.
Por quê
As ferramentas existentes cobrem uma fração do mundo. validator.js valida apenas 6 tax IDs de LATAM. cpf-cnpj-validator cobre o Brasil. rut.js cobre o Chile. Nenhuma traz El Salvador, Guatemala, Honduras, República Dominicana ou Costa Rica com verificação de checksum.
nationid preenche essa lacuna. A partir da v2.2 traz 54 países com ~145 códigos de documento, todos com algoritmos documentados de fontes oficiais — e promete estabilidade de API mais um teste de governança no CI que exige que cada spec com confidence: "high" cite uma fonte de primeira mão do emissor.
Novidades na v2.2
- 🇸🇬 Singapura — segundo país da Ásia fase 2. Três novos specs sob
nationid/sg:SG_NRIC(número de identidade de 9 caracteres para cidadãos e residentes permanentes, letra de verificação mod-11 ponderada, ICA) eSG_FIN(número de identidade de 9 caracteres para estrangeiros, incluindo a série M de 2022, ICA/MOM), ambospersonal; eSG_UEN(Número Único de Entidade, três formatos por categoria, cada um com sua própria letra de verificação, ACRA),tax. Os três emconfidence: "high". - Letras de verificação do UEN —
SG_UENpassa de validação apenas de formato para validação completa da letra de verificação nas três categorias (Negócio, Empresa Local, Outra Entidade), com a lista branca de 38 códigos de tipo de entidade. As constantes vêm literalmente depython-stdnum/stdnum/sg/uen.py; os quatro fixtures de doctest (00192200M,197401143C,S16FC0121D,T01FC6132D) ancoram a suíte, junto com os UEN reais de categoria B196800306E(DBS) e199201624D(Singtel). - Tests de oracle-agreement — cada spec SG roda um property test contra uma reimplementação independente do algoritmo publicado (NRIC/FIN mod-11 ponderado, mais as três categorias do UEN). Todas as URLs oficiais de Singapura estão em hosts
*.gov.sg, então o teste de governança passa sem alterar a lista de hosts. - 7000+ → 7800+ testes, 54 países × 145 códigos.
Novidades na v2.1 (2026-05-24)
- 🇯🇵 Japão — primeiro país da Ásia fase 2. Dois novos specs sob
nationid/jp:JP_MY_NUMBER(Número Individual de 12 dígitos, mod-11 ponderado, Portaria MIC 85/2014) eJP_CORPORATE_NUMBER(Número Corporativo de 13 dígitos, mod-9 ponderado, NTA). Ambos emconfidence: "high". O número corporativo7000012050002da própria NTA é verificável no registro público e é usado como anchor canônico nos tests. - Tests de oracle-agreement — cada spec JP roda um property test de 10k amostras contra um port inline de
python-stdnum/stdnum/jp/in_.py(My Number) epython-stdnum/stdnum/jp/cn.py(Corporate Number). Cross-validação independente built-in no CI. - 6970+ → 7000+ tests, 53 países × ~147 códigos.
Novidades na v2.0 (2026-05-24)
- 🇪🇺 EU-VAT completo — 16 membros UE + 1 participante EEA enviam validadores de IVA em um release batched:
IE_VAT,AT_UID,LU_VAT,GR_VAT,CZ_DIC,HU_VAT,RO_VAT,BG_VAT,HR_OIB,SK_VAT,SI_VAT,LT_VAT,LV_VAT,EE_VAT,MT_VAT,CY_VAT,IS_VSK. Desbloqueia paridade EU VIES como um único tagline. - Primitiva ISO/IEC 7064 MOD 11,10 —
mod11_10CheckDigit+mod11_10Validexportados denationid/algorithms. Length-generic; usada por HR_OIB, DE_USTID, DE_STEUER_ID. - Tratamento do prefixo grego
EL/GRbuilt-in — aceita ambos na entrada, normaliza paraEL(forma canônica VIES). Fecha o #1 bug histórico de EU-VAT. - Toda URL em todo JSDoc v2.0+ verificada ao vivo via
browser_fetch(firefox133 TLS impersonation) antes do publish — corrige 5 URLs quebradas em India v1.2 e 3 em v2.0. Snapshots deweb.archive.orgaceitos como citação suplementar onde o cert do emissor bloqueia checks programáticos. Specs anteriores à v2.0 estão sendo back-filled ao mesmo padrão país por país como parte da auditoria arquitetônica pós-v2.1.
Novidades na v1.2 (2026-05-23)
- 🇮🇳 Suporte à Índia — primeiro país da Ásia. Cinco specs novos sob
nationid/in:IN_AADHAAR(Verhoeff + rejeição de palíndromos, UIDAI),IN_VID(alias de 16 dígitos para Aadhaar),IN_PAN(whitelist por tipo de entidade, Income Tax Department),IN_GSTIN(Luhn mod-36 + PAN embutido + código de estado, CBIC),IN_EPIC(somente formato, ECI). - Primitiva Verhoeff —
verhoeffValideverhoeffCheckDigitexportados denationid/algorithms. Tabelas canônicas D₅ + permutações tiradas literalmente de Verhoeff (1969). - 6488 → 6606 tests, 35 países × ~125 códigos. Tarball 2,9 MB unpacked (+200 KB).
Novidades na v1.1 (2026-05-22)
- Catálogo de países sob
nationid/catalog—getCountryInfo,listCountries,countryName,flagEmoji. UsaIntl.DisplayNames(CLDR), portanto qualquer locale que o runtime suporte funciona out-of-the-box — não apenases / en / pt.
Novidades na v1.0
- Inferência de TypeScript aprimorada.
parse("BR_CPF", x).codeagora infere o literal"BR_CPF", não a união de 124 membros.extractDOB / extractSex / extractRegionrestringem o primeiro argumento aos códigos que realmente codificam cada campo. Os bundles por país expõem tipos literais paracountry/defaultPersonal/defaultTax. - Tarball npm 76% menor. De 1,7 MB → 414 KB ao remover sourcemaps do tarball e quebrar a dependência de
extract/pii/catalogcom o REGISTRY raiz.nationid/extractsozinho cai -90% em raw. - Três breaking changes pequenos, documentados em
MIGRATION.md§0:pii.maskagora lança erro em códigos desconhecidos (simétrico comhash/lastN); o campoexportsdopackage.jsonnega subpaths não documentados;CA_PASAPORTEeES_PASAPORTEbaixam dehighparamoderate(sem spec oficial do emissor para citar). - Teste de governança. Novo
tests/governance/confidence-citations.test.tsfalha o CI se algum spec comconfidence: "high"não citar uma URL no TLD do emissor ou um estatuto legal reconhecido no JSDoc.
Leia MIGRATION.md §0 antes de atualizar a partir da v0.x.
Instalar
npm i nationid
# ou
pnpm add nationid
# ou
yarn add nationidRequer Node 20+.
Início rápido
import { validate, format, normalize, parse } from "nationid";
validate("BR_CPF", "529.982.247-25"); // true
validate("BR_CNPJ", "11.222.333/0001-81"); // true
validate("PT_NIF", "123456789"); // true (com checksum)
validate("MX_CURP", "GOMC850315HDFRRR07"); // true
format("BR_CPF", "52998224725"); // "529.982.247-25"
normalize("BR_CNPJ", "11.222.333/0001-81"); // "11222333000181"
const result = parse("BR_CNPJ", "11.222.333/0001-81");
if (result.ok) {
console.log(result.normalized); // "11222333000181"
console.log(result.formatted); // "11.222.333/0001-81"
console.log(result.confidence); // "high"
}parse() retorna uma união discriminada — a API pública nunca lança exceções. Em caso de falha traz um reason.kind tipado:
const r = parse("BR_CPF", "");
if (!r.ok) r.reason.kind; // "empty" | "too_short" | "too_long" | "invalid_format" | "invalid_checksum"Playground ao vivo
Teste todos os países e helpers sem instalar nada: https://lu1tr0n.github.io/nationid_example/
O playground cobre:
- ✅
validate / parse / format / normalizepara cada país suportado - 🎯
extract(data de nascimento, sexo, região) quando o documento codifica - 🔒
piimascaramento + hash SHA-256 para exibição e armazenamento seguros - 🌍
i18nmensagens de erro emes,en,pt - 📚
catalog— metadados de documentos consultáveis para dropdowns - 6 exemplos prontos para produção (formulários React, validação server-side, KYC, etc.)
Código-fonte do showcase: https://github.com/lu1tr0n/nationid_example
Imports tree-shakable por subpath
Um único país, ~3-5 KB gzip:
import { validate } from "nationid/br";
validate("CPF", "52998224725");
validate("CNPJ", "11222333000181");Primitivas de algoritmos:
import { luhnValid, mod11WeightedSum } from "nationid/algorithms";Helpers DX — extract / pii / i18n / catalog
Quatro módulos tree-shakable para necessidades comuns (disponíveis desde v0.3):
// Extrair dados estruturados de documentos válidos
import { extractDOB, extractSex, extractRegion } from "nationid/extract";
extractDOB("MX_CURP", "GOMC850315HDFRRR07"); // { year: 1985, month: 3, day: 15 }
extractSex("AR_CUIT", "20-12345678-3"); // "M"
// Mascarar + hash para exibição e armazenamento seguros
import { mask, hash, lastN } from "nationid/pii";
mask("BR_CPF", "12345678901"); // "***.***.**9-01"
await hash("BR_CPF", "12345678901", { salt: "tenant" }); // SHA-256 em hex
// Mensagens de erro localizadas (es, en, pt)
import { getErrorMessage } from "nationid/i18n";
getErrorMessage({ kind: "too_short" }, "pt", "CPF"); // "O CPF é muito curto."
// Catálogo de documentos com nomes localizados — para dropdowns
import { listDocuments } from "nationid/catalog";
listDocuments("BR", "pt");
// [{ code: "BR_CPF", displayName: "CPF",
// longName: "Cadastro de Pessoas Físicas",
// purpose: "identity", confidence: "high", ... }, ...]
// Catálogo de países (v1.1) — nomes + bandeiras para os 35 países.
// Usa Intl.DisplayNames (CLDR), portanto qualquer locale do runtime funciona.
import { getCountryInfo, listCountries, flagEmoji } from "nationid/catalog";
getCountryInfo("BR", "pt");
// { code: "BR", alpha3: "BRA", name: "Brasil", flag: "🇧🇷" }
flagEmoji("MX"); // "🇲🇽"
listCountries("pt").length; // 54Cada subpath é tree-shakable de forma independente. Locales soltos (nationid/i18n/es, /en, /pt) pesam menos de 200 B cada.
Cobertura (54 países)
| País | Pessoal | Fiscal |
|------|---------|--------|
| 🇸🇻 El Salvador | DUI | NIT |
| 🇲🇽 México | CURP, Clave de Elector | RFC (PF + PM) |
| 🇨🇴 Colômbia | CC, CE, TI, Passaporte, PEP, PPT | NIT |
| 🇧🇷 Brasil | CPF, CNH, Título de Eleitor | CNPJ, PIS |
| 🇵🇪 Peru | DNI, CE | RUC |
| 🇦🇷 Argentina | DNI, CUIL | CUIT, CDI |
| 🇨🇱 Chile | RUT/RUN | RUT/RUN |
| 🇩🇴 Rep. Dominicana | Cédula | RNC |
| 🇬🇹 Guatemala | DPI | NIT |
| 🇭🇳 Honduras | DNI | RTN |
| 🇨🇷 Costa Rica | Cédula física, DIMEX | Cédula jurídica |
| 🇪🇸 Espanha | DNI, NIE | NIF (CIF), NUSS |
| 🇺🇸 Estados Unidos | SSN, ITIN | EIN |
| 🇧🇴 Bolívia | CI | NIT |
| 🇪🇨 Equador | Cédula | RUC |
| 🇵🇾 Paraguai | CI | RUC |
| 🇳🇮 Nicarágua | Cédula | RUC |
| 🇵🇦 Panamá | Cédula | RUC |
| 🇺🇾 Uruguai | CI | RUT |
| 🇨🇦 Canadá | SIN | BN |
| 🇵🇹 Portugal | CC | NIF |
| 🇻🇪 Venezuela | Cédula | RIF |
| 🇬🇧 Reino Unido | NINO, NHS Number | UTR, VAT |
| 🇫🇷 França | NIR | SIREN, SIRET, TVA |
| 🇩🇪 Alemanha | Steuer-ID | Steuernummer, USt-IdNr |
| 🇮🇹 Itália | Codice Fiscale | Partita IVA |
| 🇳🇱 Países Baixos | BSN | BTW |
| 🇧🇪 Bélgica | NRN | BTW |
| 🇨🇭 Suíça | AHV | UID, MWST |
| 🇵🇱 Polônia | PESEL | NIP, REGON |
| 🇸🇪 Suécia | Personnummer | Organisationsnummer, Moms |
| 🇳🇴 Noruega | Fødselsnummer, D-nummer | Organisasjonsnummer, MVA |
| 🇩🇰 Dinamarca | CPR | CVR, Moms |
| 🇫🇮 Finlândia | HETU | Y-tunnus, ALV |
| 🇮🇳 Índia (v1.2) | Aadhaar, VID, EPIC (eleitoral) | PAN, GSTIN |
| 🇯🇵 Japão (v2.1) | My Number | Corporate Number |
| 🇸🇬 Singapura (v2.2) | NRIC, FIN | UEN |
| 🇮🇪 Irlanda (v2.0) | — | IVA |
| 🇦🇹 Áustria (v2.0) | — | UID (USt-IdNr) |
| 🇱🇺 Luxemburgo (v2.0) | — | TVA |
| 🇬🇷 Grécia (v2.0) | — | IVA (AFM, prefixo VIES EL) |
| 🇨🇿 Chéquia (v2.0) | — | DIČ (pessoa jurídica) |
| 🇭🇺 Hungria (v2.0) | — | IVA (közösségi adószám) |
| 🇷🇴 Romênia (v2.0) | — | IVA (CUI / CIF) |
| 🇧🇬 Bulgária (v2.0) | — | IVA (pessoa jurídica) |
| 🇭🇷 Croácia (v2.0) | OIB | OIB |
| 🇸🇰 Eslováquia (v2.0) | — | IVA (IČ DPH) |
| 🇸🇮 Eslovênia (v2.0) | — | IVA (DDV) |
| 🇱🇹 Lituânia (v2.0) | — | IVA (PVM) |
| 🇱🇻 Letônia (v2.0) | — | IVA (PVN, pessoa jurídica high / pessoal moderate) |
| 🇪🇪 Estônia (v2.0) | — | IVA (KMKR) |
| 🇲🇹 Malta (v2.0) | — | IVA |
| 🇨🇾 Chipre (v2.0) | — | IVA |
| 🇮🇸 Islândia (v2.0) | — | VSK (somente formato, EEA sem VIES) |
Documentação completa por país com algoritmos e fontes citadas em docs/countries/.
Flag de confiança
Cada spec carrega um valor confidence que reflete o quão verificado está seu algoritmo:
high— fonte oficial E biblioteca madura concordam (na v1.0, também exige cita first-party verificada pelo CI).moderate— uma fonte oficial OU biblioteca madura concorda; a outra está ausente.low— apenas community / engenharia reversa. Validação só de formato.unconfirmed— nenhum algoritmo verificado. Validação só de formato.
A UI pode optar por exibir um aviso quando um documento de baixa confiança valida apenas por formato.
Usado por
- Emiso — plataforma multi-tenant de notas fiscais eletrônicas para a América Central. Usa
nationidpara validação de DUI / NIT / RUC do receptor e mascaramento KYC.
Se seu produto usa nationid e quer aparecer aqui, abra um PR adicionando uma entrada de uma linha acima.
Comparação
| | nationid | validator.js | cpf-cnpj-validator | rut.js | |---|---|---|---|---| | Países LATAM | 22 | 6 | 1 | 1 | | Países europeus | 31 (UE-27 VIES + UK/CH/NO/IS) | 8 | 0 | 0 | | Cobertura EU-VIES IVA | UE-27 completa | parcial | 0 | 0 | | Países da Ásia | 3 (IN, JP, SG; KR/TW seguem) | 0 | 0 | 0 | | El Salvador | ✅ | ❌ | ❌ | ❌ | | Guatemala | ✅ | ❌ | ❌ | ❌ | | Honduras | ✅ | ❌ | ❌ | ❌ | | Costa Rica | ✅ | ❌ | ❌ | ❌ | | Tamanho bundle (1 país) | ~3-5 KB | ~40 KB full | ~5 KB | ~5 KB | | Tipos TypeScript | First-class | Sim | Limitados | Limitados | | Subpaths tree-shakable | ✅ | ❌ | N/A | N/A | | Zero dependências | ✅ | ✅ | ✅ | ✅ |
Roadmap
- v0.1 — 13 países: SV, MX, CO, BR, PE, AR, CL, DO, GT, HN, CR, ES, US ✅
- v0.2 — 8 códigos adicionais em países cobertos ✅
- v0.3 — subpaths
extract+pii+i18n+catalog✅ - v0.4 — 9 países novos: UY, VE, PA, EC, BO, PY, NI, CA, PT ✅
- v0.5 — Família passaporte + algoritmo ICAO 9303 + BR_CNPJ alfanumérico + MX_NSS + correções do audit ✅
- v0.6 — Europa principal: GB, FR, DE, IT, NL, BE, CH, PL, SE, NO, DK, FI ✅
- v1.0 — API estabilizada. Cada spec com
confidence: "high"respaldado por uma cita first-party (verificado no CI). Tarball -76%. Inferência com narrowing paraparse/getSpec/extract*. ✅ - v1.1 — Catálogo de países sob
nationid/catalog: nomes + bandeiras + ISO alpha-3; qualquer locale BCP 47 viaIntl.DisplayNames. ✅ - v1.2 — Ásia fase 1: Índia (Aadhaar, VID, PAN, GSTIN, EPIC) + primitiva Verhoeff. ✅
- v2.0 — EU-VAT completo: 16 membros UE + Islândia (EEA). Primitiva ISO/IEC 7064 MOD 11,10. Padrão de URL liveness audit. ✅
- v2.1 — Ásia fase 2 — Japão (My Number + 法人番号). Algoritmos MIC + NTA cross-validados contra
python-stdnum. ✅ - v2.2 — Ásia fase 2 — Singapura (NRIC, FIN, UEN). Algoritmos ICA/ACRA, UEN cross-validado contra
python-stdnum/stdnum/sg/uen.py. ✅ - v2.3-v2.4 — Ásia fase 2 (research + verification completos): KR (RRN/BRN), TW (ID/Tax). Implementando em seguida.
- v2.5 — Bálcãs via primitiva JMBG (RS/BA/MK/ME) + prefixo GB Northern Ireland
XI+BG_EGN+CZ_RC(desbloqueia as ramificações 10-digit BG e full CZ DIC). - v2.x —
@nationid/reactcom<DocumentInput>, mais locales i18n, mutation testing (Stryker), REGISTRY lazy para tree-shaking completo a partir do root.
Contribuir
Veja CONTRIBUTING.md. PRs de novos países são bem-vindos — cada país adicionado deve incluir fontes oficiais citadas e um conjunto completo de fixtures de teste.
Licença
MIT — veja LICENSE.
