Valida NIF, DNI, NIE y CIF españoles
Correcta, rápida, pequeña y tipada. Cada regla cita su fuente en SPEC.md o se identifica como una convención, y cada error explica por qué.
npm i nif-dni-nie-cif-validation yarn add nif-dni-nie-cif-validation pnpm add nif-dni-nie-cif-validation bun add nif-dni-nie-cif-validationDatos del 3 de octubre de 2026
Pruébalo
Escribe o pega un NIF, DNI, NIE o CIF. La propia librería lo comprueba mientras escribes y te dice por qué no es válido.
Puedes usar espacios, puntos, guiones y minúsculas, como en 12.345.678-z.
El resultado aparece aquí mientras escribes.
El validador en vivo necesita JavaScript. El resto de la página funciona sin él.
Se ejecuta por completo en tu navegador: ningún dato sale de él.
Los números generados son ficticios y solo sirven para tests: alguno podría coincidir por casualidad con el de una persona o empresa real.
Por qué esta librería
Correcta, con fuentes
24 reglas, cada una con un identificador (DNI-2, NIE-3, CIF-3…) y su fundamento documentado en SPEC.md: una fuente oficial, una convención identificada como tal o el contrato de la librería. Cada error indica la regla que ha fallado.
Rápida
Al menos 6,3 veces el rendimiento de cualquier otra librería probada
60,1 M ops/s con DNI (millones de validaciones por segundo; cuanto mayor sea la cifra, mayor es el rendimiento) y un rendimiento entre 7,0 y 8,9 veces el de la v1.
Pequeña
929 B min+gzip para isValidNif y 4,7 kB para toda la librería. Admite tree shaking, y cada idioma se importa por separado.
Algunas librerías de un solo propósito ocupan menos para un validador (@maistik/validate-nif 456 B, @kreyo/nif-validator 533 B, spain-id 583 B y dni-js 882 B). Algunas validan menos tipos: esta dedica bytes a normalizar la entrada, a los tipos de control de CIF-3 y a los NIF K/L/M.
0 dependencias
Sin dependencias en tiempo de ejecución. Zod, Valibot y Yup son dependencias peer opcionales, que solo necesitan sus adaptadores.
Tipada
Escrita en TypeScript, con declaraciones para import y require. Módulos ES y CommonJS, compilados a ES2016.
Nunca lanza excepciones
Los validadores aceptan unknown: null, números y objetos dan false, o NOT_A_STRING con validate(). Lo que escriba el usuario nunca la rompe.
5 idiomas
Mensajes de error y nombres de tipos de entidad en inglés, español, catalán, euskera y gallego. El validador de arriba habla el idioma de esta página.
Generadores y esquemas
Generadores de datos de prueba con semilla, y esquemas de Zod, Valibot y Yup que devuelven el valor normalizado y el mensaje en tu idioma.
Medido en un AMD EPYC 9V74 80-Core Processor con Node.js v24.21.0 el 2 de octubre de 2026, cada librería con sus opciones por defecto. Las proporciones entre librerías se mantienen mejor de una máquina a otra que las cifras absolutas.
Úsala
Comprobaciones booleanas para un sí o un no, validate() cuando necesitas saber por qué, puntos de entrada opcionales para esquemas y datos de prueba, y una línea de comandos para terminales, scripts y agentes de IA.
import { isValidNif } from "nif-dni-nie-cif-validation";
isValidNif("12345678Z"); // trueisValidNif(" 12.345.678-z "); // true: se eliminan espacios, puntos y guiones, y se convierten las minúsculas en mayúsculasisValidNif("B12345675"); // false: el dígito de control no es correctoisValidNif(null); // false: nunca lanza excepcionesimport { validate } from "nif-dni-nie-cif-validation";import { es } from "nif-dni-nie-cif-validation/locales/es";
validate(" b-1234567-4 ", { locale: es });// { valid: true, type: "CIF", normalized: "B12345674",// meta: { orgKey: "B", orgDescription: "Sociedad de responsabilidad limitada" } }
validate("12345678A", { locale: es }).error;// { code: "INVALID_CONTROL_CHARACTER", rule: "DNI-2", expected: "Z",// message: "El carácter de control no es correcto: para este DNI debería ser «Z»." }
validate(" 12.345.678-z ").normalized; // "12345678Z": guarda este valorimport { z } from "zod";import { es } from "nif-dni-nie-cif-validation/locales/es";import { zNif } from "nif-dni-nie-cif-validation/zod";
const schema = z.object({ nif: zNif({ types: ["DNI", "NIE"], locale: es }) });
schema.parse({ nif: " 12.345.678-z " }); // { nif: "12345678Z" }schema.safeParse({ nif: "B12345674" }).success; // false: aquí no se acepta un CIFimport * as v from "valibot";import { es } from "nif-dni-nie-cif-validation/locales/es";import { vNif } from "nif-dni-nie-cif-validation/valibot";
const schema = v.object({ nif: vNif({ types: ["DNI", "NIE"], locale: es }) });
v.parse(schema, { nif: " 12.345.678-z " }); // { nif: "12345678Z" }v.safeParse(schema, { nif: "B12345674" }).success; // false: aquí no se acepta un CIFimport { object } from "yup";import { es } from "nif-dni-nie-cif-validation/locales/es";import { yNif } from "nif-dni-nie-cif-validation/yup";
const schema = object({ nif: yNif({ types: ["DNI", "NIE"], locale: es }) });
schema.validateSync({ nif: " 12.345.678-z " }); // { nif: "12345678Z" }schema.isValidSync({ nif: "B12345674" }); // false: aquí no se acepta un CIFimport { createGenerator, generateCif, generateDni, generateNie } from "nif-dni-nie-cif-validation/generate";
generateDni({ seed: 1 }); // "62707394X": el mismo en cada ejecución y plataformagenerateNie({ seed: 1, prefix: "Z" }); // "Z6270739R"generateCif({ seed: 1, orgKey: "B" }); // "B62707393"generateDni({ seed: 1, format: true }); // "62707394-X"
const gen = createGenerator(42); // una secuencia con semilla: valores distintos, los mismos en cada ejecucióngen.nif(); // "Y8524657C"gen.nif(); // "X5265925Y"npx nif-dni-nie-cif-validation validate 12345678Z B12345674 12345678A --locale es# 12345678Z: valid DNI 12345678Z# B12345674: valid CIF B12345674 (Sociedad de responsabilidad limitada)# 12345678A: invalid [DNI-2 INVALID_CONTROL_CHARACTER] El carácter de control no es correcto: para este DNI debería ser «Z».npx nif-dni-nie-cif-validation generate dni --count 2 --seed 42# 60110375J# 44829056Dnpx descarga el paquete la primera vez. La salida JSON para scripts y agentes, los códigos de salida, los datos de prueba y la revisión de archivos CSV están en la guía de la línea de comandos.
Comparación
Rendimiento con el conjunto de DNI, en millones de validaciones por segundo (M ops/s; cuanto mayor sea la cifra, mayor es el rendimiento), y tamaño de un validador de cualquier tipo (min+gzip; cuanto menor sea la cifra, menor es el tamaño).
| Librería | DNI, M ops/s | Tamaño, cualquier tipo |
|---|---|---|
| nif-dni-nie-cif-validation esta versión | 929 B | |
| @maistik/validate-nif 2.0.1 | 456 B | |
| dni-js 1.0.0 | 882 B | |
| nif-dni-nie-cif-validation 1.0.11 | 1517 B | |
| better-dni 4.4.2 | 1134 B | |
| spain-id 1.1.14 | 583 B | |
| validator.js isIdentityCard(x, "ES") 13.15.35 | 2539 B | |
| validator.js isTaxID(x, "es-ES") 13.15.35 | 6537 B | |
| @kreyo/nif-validator 0.1.0 | 533 B | |
| jsvat (Spain) 2.5.4 | 1186 B | |
| stdnum 1.12.6 | 51.063 B |
Todas las cifras salen de bench/results/latest.json. La velocidad no lo es todo: la página de rendimiento enlaza los resultados completos, que también comparan la concordancia con SPEC.md y las funcionalidades.