Validating a Spanish NIF: a person, a foreigner, or a company
Ask a Spanish customer for their NIF — número de identificación fiscal — and you will get one of six
different things. A citizen gives you a DNI, 12345678Z. A foreign resident gives you a NIE,
X1234567L. A company gives you something else again, B12345674.
Most NIF validators, and ours until this month, check only the first shape: eight digits and a letter. On a B2B form that rejects every company and every foreign-born founder. This page is about getting all six right — and about the question a valid NIF still does not answer.
One field, six kinds of number
The first character tells you what you are holding:
| First character | Kind | Who |
|---|---|---|
| A digit | DNI | A Spanish national |
X, Y, Z | NIE | A foreign national |
K, L, M | NIF K / L / M | A Spanish national under 14 without a DNI · resident abroad · a foreigner without a NIE |
A–W, except I, K, L, M, O and T | Entity | A company, an association, a public body… |
Persons and entities are checked differently:
- A person’s NIF ends with a letter: the number modulo 23, looked up in
TRWAGMYFPDXBNJZSQVHLCKE. For a NIE,X,YandZcount as 0, 1 and 2 first. - An entity’s NIF ends with a control computed from its seven digits — even positions summed, odd
positions doubled with their digits summed, and 10 minus the last digit of the total — written as
that digit, or as a letter from
JABCDEFGHI.
VerifNow reports which kind it found:
{
"valid": true,
"normalizedValue": "B12345674",
"nifDetails": {
"type": "ENTITY",
"natural_person": false,
"checksum_valid": true,
"entity_letter": "B",
"entity_type": "Private limited company (Sociedad de responsabilidad limitada)"
}
}The letter is the legal form
For an entity, the first letter is not decoration: it is the legal form, as set by Orden EHA/451/2008.
A is a sociedad anónima, B a sociedad limitada — by far the most common for small companies —
G an association, N a foreign entity, W the Spanish branch of a non-resident company. The full
table is in the NIF guide.
That is useful on a B2B form. A P (local authority) or a Q (public body) signing up to your SaaS
is probably a procurement process, not a self-serve trial. A W is a foreign company’s Spanish
branch, which may be invoiced differently from its parent.
Do not reject persons on a B2B form. Spain’s self-employed — autónomos — trade under their own
NIF, which is their DNI or NIE. natural_person: true tells you who you are dealing with; it is not
a reason to turn a freelancer away.
Digit or letter?
One rule is genuinely unsettled. The Orden that defines entity NIFs says there is “un carácter de
control” and nothing more — not whether it is a digit or a letter for a given legal form. Published
sources agree on two groups only: a digit for A, B, E and H, a letter for P, Q and
S. For the others they disagree.
VerifNow enforces the two agreed groups and accepts either form for every other letter. A validator that picks a side on a disputed rule will, sooner or later, reject a real company — and that costs more than accepting a rare form.
A valid NIF is not a valid VAT number
This is the part that catches B2B billing.
A Spanish company’s EU VAT number is its NIF with ES in front. In the Agencia Tributaria’s words,
“el código NIF-IVA coincidirá con el NIF español al que se antepondrá el prefijo ES”. But a company
only gets a NIF-IVA once it registers for intra-community operations, in the Registro de Operadores
Intracomunitarios. And “la asignación del NIF-IVA supondrá que el operador constará en el censo VIES”.
So B12345674 can be a perfectly valid NIF while ESB12345674 comes back from VIES as not
registered. That is not a typo and not an outage: the company simply is not registered to trade
across EU borders.
It matters because the reverse charge depends on it. The Agencia Tributaria is explicit about the Spanish side: an intra-community supply is only exempt if the customer gave “un número de operador intracomunitario (VAT number) válido” — “en caso contrario, la entrega intracomunitaria está sujeta y no exenta”. Your own member state’s rule will be similar. Check both:
import { VerifNow } from '@verifnow/sdk';
const client = new VerifNow({ apiKey: process.env.VERIFNOW_API_KEY! });
export async function checkSpanishCustomer(input: string) {
// The VAT number is ES + the NIF. Build it from the bare NIF, without the user's punctuation.
const nif = input.toUpperCase().replace(/[\s.\-]/g, '').replace(/^ES/, '');
const [nifResult, vatResult] = await Promise.all([
client.validateNif(nif),
client.validateVat(`ES${nif}`),
]);
if (!nifResult.valid) {
return { ok: false as const, error: nifResult.message };
}
const details = nifResult.nifDetails!;
const vat = vatResult.vatDetails;
return {
ok: true as const,
nif: nifResult.normalizedValue!,
isCompany: !details.naturalPerson,
legalForm: details.entityType, // e.g. 'Private limited company (…)'
// Reverse charge only when VIES confirms the VAT number. null means VIES could not be
// asked: record it and re-check, but do not treat it as registered.
reverseCharge: vat?.registered === true,
vatRegistration: vat?.registered ?? null,
};
}The two answers mean different things, and you usually want both: the NIF says who the customer is and whether the number is well formed; VIES says whether you may invoice without VAT.
Needs @verifnow/sdk 1.5.0 or later, which models nifDetails. For Java,
io.verifnow:verifnow-spring 2.5.0 or later exposes the same fields through getNifDetails().
Storing it
A company NIF is public business data. A person’s NIF is not: a DNI or NIE is a national identity number, and personal data under the GDPR. Treat it the way you would treat any national identifier — store it only where you need it (invoicing a self-employed customer is a legitimate need), keep it out of logs and analytics, and show it masked.
On our side, the usage log that meters your calls stores every NIF as ***.
Testing without anyone’s NIF
Use the conventional samples: 12345678Z for a DNI, X1234567L for a NIE. Do not invent others: about
one random number in twenty-three has the right letter, so a made-up valid NIF may belong to a real
person. Company NIFs identify businesses and are public, so a real one is fine in a fixture — and
B12345674 is a convenient well-formed one.
In short
- Accept all six kinds, not only the DNI. A NIF check that rejects
X1234567LorB12345674rejects foreign founders and companies. - Read the first letter: it tells you whether you are dealing with a person or an entity, and which legal form.
- Do not reject persons on a B2B form — autónomos invoice under their own NIF.
- A valid NIF is not a valid VAT number. For the reverse charge, check
ES+ NIF in VIES.
Next: Validate NIF · Validate VAT · VAT number and IBAN in one call
Sources: Orden EHA/451/2008 (BOE) · Operaciones intracomunitarias y consulta de operadores (Agencia Tributaria) · Identificación para realizar operaciones con otros empresarios dentro de la UE (Agencia Tributaria)