Generator · Dutch data

Dutch btw-id

Endpoint GET /v1/nl/btw-id

What it covers

Returns a valid Dutch btw-id (VAT identification number), e.g. `NL123456789B01`. Use `standard` to pick `modern` (default, MOD 97-10 checked) or `legacy` (elfproef core, `B01` suffix). Set `invalid=true` for a btw-id that fails validation, or `edge=true` for valid edge-case numbers.

This documents the generator's default 'modern' standard (params.standard defaults to 'modern' in create-generator.ts). The generator can also emit 'legacy' ids, which use the elfproef mod-11 core check and a fixed 'B01' suffix instead of the MOD 97-10 pair.

How it’s calculated

The modern (post-2020) Dutch btw-id is protected by an IBAN-style ISO 7064 MOD 97-10 check whose two digits make the alphanumeric-expanded value of 'NL{core}B' plus the check pair ≡ 1 (mod 97).

Algorithm

  1. Start from a 9-character numeric core (the drawn payload; the default 'modern' standard leaves the core unconstrained — any 9 digits).
  2. Form the letter-bearing string to be checked: 'NL' + core + 'B' (the country prefix NL, the 9-digit core, then the literal letter B that precedes the check pair).
  3. Convert every character of that string to its ISO 7064 / ICAO-9303 alphanumeric value: digits 0-9 map to 0-9, and letters map A=10 … Z=35 — so N=23, L=21, B=11. Concatenate each value's decimal representation (multi-digit values contribute both digits) into one long numeric string. For 'NL{9 digits}B' this yields '23' + '21' + the 9 core digits + '11'.
  4. Compute the two check digits with ISO 7064 MOD 97-10: take the numeric string as a big integer, multiply by 100, take that modulo 97, and subtract from 98: check = 98 - ((numeric × 100) mod 97).
  5. Left-pad the result to two digits with a leading zero if needed. This two-digit string is the check pair.
  6. The final btw-id is 'NL' + core + 'B' + checkPair. It satisfies the property that the numeric conversion of the whole letter-bearing string with the check pair appended is ≡ 1 (mod 97).

Worked example

NL123456782B?? (9-digit core 123456782, modern standard)

Core = 123456782. Letter-bearing string to check = 'NL123456782B'.
Convert characters: N=23, L=21, then the digits 1,2,3,4,5,6,7,8,2 as-is, then B=11. Concatenate → '23' '21' '123456782' '11' = 232112345678211.
Multiply by 100: 232112345678211 × 100 = 23211234567821100.
Modulo 97: 23211234567821100 mod 97 = 22.
Check = 98 - 22 = 76.
76 already has two digits, so the check pair is '76'.
Full btw-id = NL123456782B76. Verify: 23211234567821176 mod 97 = 1. Correct.

The check pair is 76, giving the full btw-id NL123456782B76.

Edge cases

  • The core itself carries no constraint under the modern standard; the entire integrity guarantee lives in the two trailing check digits over 'NL{core}B'.
  • The legacy (pre-2020) standard is a different scheme entirely: its 9-digit core is validated by the Dutch 'elfproef' (weighted mod-11, weights 9,8,7,6,5,4,3,2 over the first 8, check digit = weighted sum mod 11 as a remainder), and the suffix is always the literal 'B01' rather than a computed pair. A core whose mod-11 remainder is 10 has no single-digit check and is redrawn.
  • Because the letters N, L, B convert to two-digit values (23, 21, 11), the numeric string fed to MOD 97-10 is longer than the visible id and always begins '2321…' and ends '…11'.

Gotchas

  • Do NOT run MOD 97-10 over the literal characters of 'NL123456782B'. Each letter must first be expanded to its alphanumeric value (N→23, L→21, B→11) and those decimal digits concatenated. Skipping the expansion gives the wrong modulus.
  • The formula is 98 - ((numeric × 100) mod 97), not 97 - (…). Using 97 or forgetting the ×100 both produce a check pair that fails the ≡ 1 (mod 97) validation.
  • The check pair must be zero-padded to two characters; a computed value like 7 must render as '07'.

Parameters

ParameterTypeDescription
countinteger1–1000Number of records to return, 1–1000 (your plan may lower this). Omitted returns a single record; set it for a batch.
edgebooleanRestrict output to valid edge-case btw-ids from the rare corners.
extremebooleanReturn a correct value wrapped in a hostile encoding (untrimmed whitespace, invisible/zero-width characters, BOM, or bidi/combining marks). Homoglyphs are excluded so the value stays machine-parseable; it still validates after normalisation.
invalidbooleanReturn a btw-id that deliberately fails validation.
seedintegerInteger seed for reproducible output: the same seed always yields the same record.
standard"legacy" | "modern" | "both"Numbering standard: `modern` (default), `legacy`, or `both` (random per record).

Response fields

FieldTypeDescription
valuestringThe full btw-id, e.g. `NL123456789B01`.
digitsstringThe bare 9-character core between `NL` and `B`.
standard"legacy" | "modern"Which standard the value was built to.

Other generators for Netherlands

See all generators for Netherlands →

The same kind of identifier elsewhere

Try it

Generate a live example below — every response is valid by format and entirely synthetic.