npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kreyo/nif-validator

v0.1.0

Published

Reference implementation for validating Spanish tax IDs (DNI, NIE, CIF). Pure functions, no dependencies, fully typed.

Readme

nif-validator

Reference implementation for validating Spanish tax identification numbers (DNI, NIE, CIF) in .NET, TypeScript, and Python.

Zero dependencies. Pure functions. Verified against real public CIFs of Spanish companies.

License: MIT CI

🇪🇸 Para developers en español: esta librería valida números de identificación fiscal españoles (DNI, NIE, CIF) en .NET, JavaScript/TypeScript y Python. Implementación de referencia, sin dependencias, con tests sobre CIFs reales de empresas españolas. Documentación completa en español →


Why this library exists

Validating a Spanish NIF correctly is harder than it looks. The algorithm has three variants (DNI, NIE, CIF), the CIF check digit follows specific rules per organization type, and most snippets you find online are incomplete or wrong.

This is a clean reference implementation, kept identical across three languages, verified with the same fixtures, and tested against real public Spanish company CIFs (Banco Santander, BBVA, Inditex, Telefónica, Repsol, Iberdrola).

If you're building anything that touches Spanish tax IDs — invoicing software, accounting tools, KYC flows, e-commerce checkouts — this library is for you.

Install

.NET (multi-target: net8.0 + netstandard2.0)

dotnet add package Kreyo.NifValidator

TypeScript / JavaScript

npm install @kreyo/nif-validator
# or
pnpm add @kreyo/nif-validator
# or
yarn add @kreyo/nif-validator

Python (3.10+)

pip install kreyo-nif-validator

Usage

.NET

using Kreyo.NifValidator;

NifValidator.IsValid("12345678Z");          // true
NifValidator.IsValid("X1234567L");          // true (NIE)
NifValidator.IsValid("A39000013");          // true (Banco Santander)
NifValidator.IsValid("12345678A");          // false (wrong control letter)

NifValidator.Normalize(" 12345678-z ");     // "12345678Z"
NifValidator.GetNifType("X1234567L");       // "NIE"
NifValidator.GetNifType("invalid");         // null

// Optional: include deprecated types K, L, M, T (pre-2008)
NifValidator.IsValid("K12345674", new NifValidatorOptions { IncludeDeprecated = true });

TypeScript

import { isValid, normalize, getNifType } from "@kreyo/nif-validator";

isValid("12345678Z");           // true
isValid("X1234567L");           // true (NIE)
isValid("A39000013");           // true (Banco Santander)
isValid("12345678A");           // false

normalize(" 12345678-z ");      // "12345678Z"
getNifType("X1234567L");        // "NIE"
getNifType("invalid");          // null

isValid("K12345674", { includeDeprecated: true });  // true

Python

from nif_validator import is_valid, normalize, get_nif_type, ValidationOptions

is_valid("12345678Z")           # True
is_valid("X1234567L")           # True (NIE)
is_valid("A39000013")           # True (Banco Santander)
is_valid("12345678A")           # False

normalize(" 12345678-z ")       # "12345678Z"
get_nif_type("X1234567L")       # "NIE"
get_nif_type("invalid")         # None

is_valid("K12345674", ValidationOptions(include_deprecated=True))  # True

What gets validated

| Type | Format | Example | Notes | |------|--------|---------|-------| | DNI | 8 digits + control letter | 12345678Z | For Spanish citizens | | NIE | X/Y/Z + 7 digits + letter | X1234567L | For foreign residents | | CIF | Letter + 7 digits + letter or digit | A39000013 | For companies and other legal entities |

CIF type letters and their control rules:

| Type | Meaning | Control | |------|---------|---------| | A | Sociedad Anónima | digit only | | B | Sociedad Limitada | digit only | | C | Sociedad Colectiva | digit or letter | | D | Sociedad Comanditaria | digit or letter | | E | Comunidad de Bienes | digit only | | F | Cooperativa | digit or letter | | G | Asociación | digit or letter | | H | Comunidad de Propietarios | digit only | | J | Sociedad Civil | digit or letter | | N | No residente | letter only | | P | Corporación local | letter only | | Q | Organismo público | letter only | | R | Religiosa | letter only | | S | Órgano de la Administración | letter only | | U | Unión Temporal de Empresas | digit or letter | | V | Otros tipos | digit or letter | | W | Establecimiento permanente extranjero | letter only | | K, L, M, T | Deprecated by AEAT (pre-2008) | only with includeDeprecated |

What this library does NOT do

  • It does not check whether a NIF is registered with AEAT. This is a syntactic and check-digit validation. A NIF can be mathematically valid and still not exist in the tax registry. To verify that a NIF is active, query VIES (for EU tax IDs) or AEAT's services directly.
  • It does not validate the company name or address. Just the format of the identifier.
  • It does not detect "ghost" NIFs (mathematically valid but known to be unused). That's a business-rule concern, not a format-validation one.

API

All three implementations expose the same three functions:

| Function | Returns | Throws | |----------|---------|--------| | isValid(nif, options?) | boolean | never | | normalize(nif) | canonical string | on invalid | | getNifType(nif) | "DNI" | "NIE" | "CIF" | null | never |

Whitespace (spaces, tabs, newlines) and hyphens are ignored everywhere. Input is case-insensitive.

Algorithm details

For technical details on the validation algorithm (DNI letter calculation, NIE prefix mapping, CIF check digit/letter computation), see docs/algorithm.md.

Made by Kreyo

This library is part of Kreyo, a developer-first platform of APIs for Spanish electronic invoicing: VeriFactu, FacturaE, AI invoice extraction, and PDF generation.

If you're building software that needs Spanish tax compliance, you might also like:

  • Kreyo VeriFactu — generate, sign, and submit AEAT registros in real time
  • Kreyo FacturaE — generate signed FacturaE 3.2.2 XML for B2G and B2B
  • Kreyo Extract — extract structured data from received invoices with AI
  • Kreyo PDF — generate invoices and documents as PDFs

Contributing

Issues and PRs welcome. Please see CONTRIBUTING.md for details.

License

MIT © Kreyo