Most official identifiers are self-checking. A national ID, a tax number, an IBAN, a credit-card number all end in a digit computed from the digits before it — a checksum. Type a real one into any validator and it passes; change a single digit and it fails. That self-check is the whole point: it catches transcription errors before they cost anyone money.
So the question for any fake-data tool is not “does it look like an identifier?” but “does it satisfy the checksum?” This is exactly where a general-purpose faker and a validity-first generator part ways.
What Faker actually provides
Faker (@faker-js/faker) ships no national-ID generator at all — there is no PESEL, no NIP, no SSN, no country tax-number or VAT module in the library. Its API is organised into modules like person, location, finance, and internet; none of them cover government or tax identifiers. If you need a PESEL from Faker, you assemble it yourself from string helpers, and nothing computes the check digit for you.
Where Faker does touch checksummed data, it is candid about the limits. Its finance.iban() documentation states plainly that the generated IBAN “might be invalid due to randomly generated bank codes / other country specific validation rules.” It does compute a Luhn check digit for values like credit-card numbers, so not everything is unchecked — but the identifiers most test suites actually need, the national and tax numbers, are simply not in the library. The honest summary: Faker gives you correctly-shaped strings, not a guarantee that the identifier you needed is valid.
What Real Fake Data does instead
Every identifier generator here computes the real check digit from the real algorithm. An IBAN carries correct ISO 7064 mod-97 check digits; each country’s national ID carries its own correct checksum (and, where the format encodes a birth date or sex, those are valid too); each tax number carries its own weighted checksum. The value is synthetic — it belongs to no real person — but it is valid by format, so it flows through the exact validators your production code runs.
That is the property that makes a fixture useful. Your registration form, your import routine, your database constraint — all of them check the identifier, and all of them should accept it, because the whole point of the test is to exercise the path that runs when the input is good.
Why it bites in practice
The failure is quiet and late. Your test seeds a user with a Faker-shaped national ID, submits the form, and the form’s own validation rejects it — so the test never reaches the behaviour it was written to check. Or worse, the invalid value slips past a weak fixture and only fails in a downstream system that validates more strictly, days later, in someone else’s test run.
With checksum-valid data, that entire class of flakiness disappears: the fixture is indistinguishable from real input as far as every validator is concerned.
Numeric identifiers we generate — all checksum-valid
Every one of these is a numeric, self-checking identifier, generated with its correct check digit. Follow any link for that generator’s page.
Austrian data: Austrian IBAN , Austrian SVNR
Belgian data: Belgian IBAN , Belgian Rijksregisternummer
Bulgarian data: Bulgarian EGN , Bulgarian IBAN
Croatian data: Croatian IBAN , Croatian JMBG , Croatian OIB
Cypriot data: Cypriot IBAN , Cyprus TIC
Czech data: Czech IBAN , Czech rodné číslo
Danish data: Danish CPR , Danish IBAN
Dutch data: Dutch BSN , Dutch IBAN
Estonian data: Estonian IBAN , Estonian isikukood
Finnish data: Finnish henkilötunnus , Finnish IBAN , Finnish Y-tunnus
French data: French IBAN , French NIR
German data: German IBAN , German Steuer-IdNr
Greek data: Greek AFM , Greek AMKA , Greek IBAN
Hungarian data: Hungarian adóazonosító jel , Hungarian IBAN , Hungarian személyi azonosító , Hungarian TAJ
Irish data: Irish IBAN , Irish PPSN
Italian data: Italian Codice Fiscale , Italian IBAN
Latvian data: Latvian IBAN , Latvian personas kods
Lithuanian data: Lithuanian asmens kodas , Lithuanian IBAN
Luxembourg data: Luxembourg IBAN , Luxembourg matricule
Maltese data: Maltese IBAN
Polish data: Polish IBAN , Polish PESEL
Portuguese data: Portuguese IBAN , Portuguese NIF
Romanian data: Romanian CNP , Romanian IBAN
Slovak data: Slovak IBAN , Slovak rodné číslo
Slovenian data: Slovenian davčna številka , Slovenian EMŠO , Slovenian IBAN
Spanish data: Spanish DNI , Spanish IBAN , Spanish NIE
Swedish data: Swedish IBAN , Swedish personnummer
Try it
Generate any of these in the Playground and check the result against its real validator — no key required. Every national-ID, tax-number and IBAN generator returns checksum-valid values by default.
To be precise about Faker
Faker never claims to generate valid national IDs or tax numbers — it simply has no such generators, and it explicitly documents that its IBANs may be invalid. This is not a bug in Faker; it is a different design goal. The point is only that if you need identifiers that validate, Faker is not the tool that promises them.