Ir al contenido
nif-dni-nie-cif-validation: validación de NIF, DNI, NIE y CIF españolesnif-dni-nie-cif-validation: validación de NIF, DNI, NIE y CIF españoles

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é.

Instalar con npm
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-validation

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.

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.

Ejemplos de código
import { isValidNif } from "nif-dni-nie-cif-validation";
isValidNif("12345678Z"); // true
isValidNif(" 12.345.678-z "); // true: se eliminan espacios, puntos y guiones, y se convierten las minúsculas en mayúsculas
isValidNif("B12345675"); // false: el dígito de control no es correcto
isValidNif(null); // false: nunca lanza excepciones
import { 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 valor
import { 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 CIF
import * 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 CIF
import { 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 CIF
import { createGenerator, generateCif, generateDni, generateNie } from "nif-dni-nie-cif-validation/generate";
generateDni({ seed: 1 }); // "62707394X": el mismo en cada ejecución y plataforma
generateNie({ 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ón
gen.nif(); // "Y8524657C"
gen.nif(); // "X5265925Y"
Terminal window
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
# 44829056D

npx 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).

Rendimiento y tamaño de las librerías de identificadores españoles en npm
LibreríaDNI, M ops/sTamaño, cualquier tipo
nif-dni-nie-cif-validation esta versión60,12929 B
@maistik/validate-nif 2.0.19,46456 B
dni-js 1.0.08,90882 B
nif-dni-nie-cif-validation 1.0.118,591517 B
better-dni 4.4.28,441134 B
spain-id 1.1.146,96583 B
validator.js isIdentityCard(x, "ES") 13.15.355,732539 B
validator.js isTaxID(x, "es-ES") 13.15.354,226537 B
@kreyo/nif-validator 0.1.02,78533 B
jsvat (Spain) 2.5.42,101186 B
stdnum 1.12.60,4151.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.

Rendimiento y comparación completos →