Getting started
nif-dni-nie-cif-validation checks Spanish tax IDs (NIF, DNI, K/L/M NIF, NIE and CIF) against the official rules, and tells you why a number is wrong. It has no dependencies, ships its own TypeScript types, and works with import and require in Node.js 20 or newer, in every current browser, and in Deno and Bun.
Install
Section titled “Install”npm install nif-dni-nie-cif-validationpnpm add nif-dni-nie-cif-validationyarn add nif-dni-nie-cif-validationbun add nif-dni-nie-cif-validationdeno add npm:nif-dni-nie-cif-validationTo validate from a terminal or a shell script instead, with no code to write, run npx nif-dni-nie-cif-validation validate 12345678Z: the Command line guide has every command and option.
Check a number
Section titled “Check a number”The isValid… functions answer yes or no. They accept any value and never throw, so you can pass them what a user typed:
import { isValidNif } from "nif-dni-nie-cif-validation";
isValidNif("12345678Z"); // true: a DNIisValidNif("X1234567L"); // true: an NIEisValidNif("B12345674"); // true: a CIFisValidNif(" 12.345.678-z "); // true: spaces, dots, hyphens and lower case are fineisValidNif("12345678A"); // false: wrong check letterisValidNif(null); // false: never throwsWith CommonJS, require works the same way:
const { isValidNif } = require("nif-dni-nie-cif-validation");
isValidNif("12345678Z"); // truePick the right function
Section titled “Pick the right function”isValidNif accepts every type. When a field only takes some types, use the narrower function:
| The field takes… | Use |
|---|---|
| Any NIF: DNI, K/L/M NIF, NIE or CIF | isValidNif(value) |
| People only: DNI, K/L/M NIF or NIE | isValidNaturalPersonNif(value) |
| A DNI (or a K/L/M NIF) | isValidDni(value) |
| An NIE | isValidNie(value) |
| Companies and other entities (CIF) | isValidCif(value) |
A Spanish VAT number (ES + NIF, the format only) |
isValidSpanishVat(value) |
import { isValidCif, isValidNaturalPersonNif } from "nif-dni-nie-cif-validation";
isValidNaturalPersonNif("X1234567L"); // trueisValidNaturalPersonNif("B12345674"); // false: a CIF is not a personisValidCif("P2807900B"); // true: Ayuntamiento de MadridNot sure which document is which? See DNI, NIE, NIF and CIF.
Know why, and store the canonical form
Section titled “Know why, and store the canonical form”validate() returns the type, the canonical form to store and, for an invalid value, an error with a code, the SPEC.md rule that failed, a message and the expected control character:
import { validate } from "nif-dni-nie-cif-validation";
validate(" 12.345.678-z ");// { valid: true, type: "DNI", normalized: "12345678Z" }
validate("12345678A").error;// { code: "INVALID_CONTROL_CHARACTER", rule: "DNI-2", expected: "Z",// message: 'The control character is not correct: for this DNI it should be "Z".' }Store normalized, not what the user typed: it is upper case, without separators, and the same for every way of writing the same document.
Show the message in your user’s language
Section titled “Show the message in your user’s language”The messages are in English by default. Spanish, Catalan, Basque and Galician are separate imports, so your bundle only has the languages you use:
import { validate } from "nif-dni-nie-cif-validation";import { es } from "nif-dni-nie-cif-validation/locales/es";
validate("12345678A", { locale: es }).error?.message;// "El carácter de control no es correcto: para este DNI debería ser «Z»."