Country Guide10 min readAlberto García

Netherlands VAT Number Validation: BTW-nummer Format, VIES, and Code Examples

Dutch BTW numbers have a unique format: NL + 9 digits + B + 2 digits. The literal 'B' is not a separator — it is a mandatory part of the number. Omitting it is the most common Dutch VAT format error.

netherlandsnlbtw

The Netherlands is one of the EU's most significant business hubs — home to a large number of EU headquarters, holding companies, and tech companies. Dutch VAT numbers (BTW-identificatienummer, shortened to BTW-nummer or BTW-nr) have a unique format that catches developers by surprise: the literal letter B embedded in the middle of the number is not a separator, it is a mandatory structural component. Omitting the B is the single most common Dutch VAT format error. This guide covers the exact format, what the B and the trailing digits mean, privacy-related VIES behaviour, and complete code examples.

Note

Dutch VAT numbers (BTW-identificatienummer) are issued and managed by the Belastingdienst (Dutch Tax and Customs Administration). VIES routes Dutch validation requests to the Belastingdienst system in real time.

The Dutch VAT Number Format (BTW-identificatienummer)

A Dutch VAT number consists of the prefix NL followed by 9 digits, then the literal letter B, then 2 more digits — 14 characters in total. The format is always NL[9 digits]B[2 digits]. A valid example is NL123456789B01. The B is always uppercase, always a literal B, and always present — there is no variation. A number like NL123456789 (missing B and 2 digits) is structurally invalid.

The 9-digit block is derived from the RSIN (Rechtspersonen en Samenwerkingsverbanden Identificatienummer) — the Dutch legal entity identification number maintained by the KvK (Kamer van Koophandel, the Dutch Chamber of Commerce). The 2 digits after B indicate the entity's fiscal unit number within the RSIN — for most standalone BV or NV companies the suffix is 01, but holding structures with multiple fiscal units may have 02, 03, etc. This means that a business group with a parent holding company (NL123456789B01) and a subsidiary fiscal unit (NL123456789B02) share the same RSIN base number but have different BTW numbers.

Dutch businesses often write their BTW number with a dot and spaces for readability — 'NL 123.456.789 B01' or 'NL123.456.789B01'. Strip all dots, spaces, and non-alphanumeric characters except the B before validation. The canonical form is NL followed immediately by 9 digits then B then 2 digits with no separators.

PropertyValue
PrefixNL
Total length14 characters (NL + 9 digits + B + 2 digits)
FormatNL + 9 digits + literal B + 2 digits
ExampleNL123456789B01
Common invoice formatNL 123.456.789 B01
Regex^NL[0-9]{9}B[0-9]{2}$
VIES country codeNL
National authorityBelastingdienst
Local nameBTW-identificatienummer (BTW-nummer / BTW-nr.)

Common Dutch VAT Format Errors

  • Missing the B: 'NL123456789' or 'NL12345678901' — the B is mandatory. Without it the number is 11 characters instead of 14 and will fail format validation.
  • Dots not stripped: 'NL123.456.789B01' — strip dots before validation. Dutch invoices commonly format the 9-digit block with dots.
  • Lowercase B: 'NL123456789b01' — normalise to uppercase. The TaxID API handles this, but strip client-side for consistency.
  • Only submitting the RSIN without B suffix: some Dutch company databases store just the 9-digit RSIN. Add B01 when constructing the BTW number from an RSIN. Verify this with the customer — their BTW suffix may be 01 or higher.
  • Confusing BTW-nummer with KvK-nummer: the KvK number (Kamer van Koophandel) is an 8-digit Chamber of Commerce registration number, not a VAT number. Format is entirely different.
  • Confusing BTW with BSN: the BSN (Burgerservicenummer) is an 8 or 9-digit personal citizen service number. Never a VAT number.

Dutch Company Types and VAT Registration

The most common Dutch legal forms for B2B customers are BV (besloten vennootschap — private limited company, equivalent to a GmbH or Ltd, the most common form for Dutch SMEs and EU subsidiaries), NV (naamloze vennootschap — public limited company for listed entities), eenmanszaak (sole trader / self-employed), and VOF (vennootschap onder firma — general partnership). The Netherlands is a very popular jurisdiction for EU holding companies and regional headquarters, so you may frequently encounter Dutch-registered entities that are actually the EU presence of non-Dutch groups.

Dutch fiscal unity (fiscale eenheid) deserves special mention. Multiple BV entities under common control can form a fiscal unity for VAT purposes, sharing a single BTW number. If a Dutch customer provides a BTW number that validates correctly via VIES but the company name returned does not match the entity named on the invoice, the invoice entity may be a member of a fiscal unity filing under the parent's BTW number. This is a legitimate Dutch VAT arrangement. Validate the number as provided — the responsibility for correct fiscal unity membership lies with the customer.

VIES and Netherlands' Belastingdienst: Privacy Behaviour

The Netherlands' Belastingdienst VIES endpoint is generally reliable with good uptime. Response times for live lookups are typically 200-500ms. The notable behaviour specific to the Netherlands is privacy-related: Dutch VIES responses frequently return null for the address field even when the number is valid and active. This is by design — the Belastingdienst applies privacy protections that limit which data is shared via VIES. The company name is usually returned, but address is often withheld.

Do not treat a null address from a Dutch VIES response as a validation problem. For Dutch numbers, a response of valid: true, status: active, company_name: 'Acme BV', address: null is normal and correct. Store the null address with a note indicating the Netherlands withholds address data via VIES — do not re-validate the number in an attempt to retrieve the address. For address verification of Dutch companies, use the KvK online register manually, or ask the customer to provide their registered address directly. Dutch VAT validation via TaxID caches results for 24 hours.

Dutch VAT Rates

The Netherlands applies a standard VAT rate of 21% (BTW — Belasting over de Toegevoegde Waarde) to most goods and services. A reduced rate of 9% applies to food and beverages for human consumption, medicines and medical aids, books (print and digital), newspapers, passenger transport, hotel accommodation, and admission to cultural events (museums, concerts, sports). The Netherlands does not have a super-reduced rate or a zero rate for domestic supplies (other than the standard EU zero-rate for qualifying intra-EU B2B supplies).

For SaaS and digital services sold to Dutch consumers (B2C), the applicable rate is 21%. For Dutch B2B customers with a valid BTW-nummer that validates active via VIES, zero-rate reverse charge applies. The Netherlands participates in the EU OSS scheme for B2C digital services.

Code Examples

cURL

bash
# Validate a Dutch VAT number (BTW-nummer)
curl https://taxid.dev/api/v1/validate/NL/NL123456789B01 \
  -H "Authorization: Bearer YOUR_API_KEY"

# Expected response (NL withholds address data via VIES):
# {
#   "valid": true,
#   "status": "active",
#   "vat": "NL123456789B01",
#   "country_code": "NL",
#   "company_name": "Voorbeeld BV",
#   "address": null,
#   "cached": false,
#   "request_id": "req_01j..."
# }

Node.js / TypeScript

typescriptvalidate-dutch-vat.ts
export async function validateDutchVat(vatNumber: string): Promise<{
  valid: boolean;
  companyName: string | null;
  address: string | null;
  status: string;
}> {
  // Strip dots and spaces — Dutch invoices format as NL 123.456.789 B01
  const normalised = vatNumber.replace(/[\s.]/g, '').toUpperCase();

  // NL + 9 digits + literal B + 2 digits
  if (!/^NL[0-9]{9}B[0-9]{2}$/.test(normalised)) {
    return { valid: false, companyName: null, address: null, status: 'format_invalid' };
  }

  const res = await fetch(
    `https://taxid.dev/api/v1/validate/NL/${normalised}`,
    {
      headers: { Authorization: `Bearer ${process.env.TAXID_API_KEY}` },
      signal: AbortSignal.timeout(5000),
    }
  );

  const data = await res.json();
  return {
    valid: data.valid,
    companyName: data.company_name,
    address: data.address, // NL often returns null for address — this is normal
    status: data.status,
  };
}

Python

pythonvalidate_dutch_vat.py
import re, os, requests
from dataclasses import dataclass
from typing import Optional

# NL + 9 digits + literal B + 2 digits
NL_PATTERN = re.compile(r'^NL[0-9]{9}B[0-9]{2}$')

@dataclass
class DutchVatResult:
    valid: bool
    company_name: Optional[str]
    address: Optional[str]  # NL often returns None — expected behaviour
    status: str

def validate_dutch_vat(vat: str) -> DutchVatResult:
    # Strip dots and spaces — Dutch invoices use NL 123.456.789 B01 format
    normalised = re.sub(r'[\s.]', '', vat).upper()
    if not NL_PATTERN.match(normalised):
        return DutchVatResult(False, None, None, 'format_invalid')

    r = requests.get(
        f'https://taxid.dev/api/v1/validate/NL/{normalised}',
        headers={'Authorization': f'Bearer {os.environ["TAXID_API_KEY"]}'},
        timeout=5,
    )
    r.raise_for_status()
    d = r.json()
    return DutchVatResult(
        valid=d['valid'],
        company_name=d.get('company_name'),
        address=d.get('address'),
        status=d['status'],
    )

Frequently Asked Questions

  • Why is there a 'B' in the Dutch VAT number? The B separates the RSIN (9-digit entity identifier) from the fiscal unit suffix (2 digits). It is a structural part of the number, not a separator. It has always been part of the format.
  • What does the 2-digit suffix after B mean? It indicates the fiscal unit within the company group. Most standalone companies use B01. Dutch fiscal unity structures (multiple BV entities under one VAT registration) may use B02, B03, etc. for subsidiary entities.
  • Why does Dutch VIES return null for the address? The Belastingdienst applies privacy protections that limit address data shared via VIES. A null address is normal and correct for Dutch validations. Do not treat it as a validation failure.
  • What is the difference between BTW-nummer and KvK-nummer? The BTW-nummer (NL + 9 digits + B + 2 digits) is the VAT registration number used for VIES. The KvK-nummer is the 8-digit Chamber of Commerce registration number used for company identification. They are derived from different registries.
  • How long does VIES take for Dutch validations? Cached Dutch numbers respond in under 10ms. Uncached live Belastingdienst lookups typically complete in 200-500ms. The Dutch endpoint is one of the more reliable in the EU.

Validating Dutch VAT Numbers at Scale

The Netherlands is a top-three EU B2B market for many European platforms, particularly given its role as a hub for EU subsidiaries of non-EU companies. Dutch numbers have the longest format in the EU (14 characters) and the most distinctive structure — the B is a reliable distinguishing feature that makes Dutch numbers easy to identify in a mixed-country database. At scale, normalise all Dutch numbers by stripping dots before storage. Null addresses are expected and should not trigger re-validation or customer support workflows. Store the request_id from each API response. For the complete format reference and live validator, see validate-vat/nl.

Start validating EU VAT numbers

Free plan — 100 validations/month. No credit card required.

AG
Alberto García

Founder, TaxID

Building EU VAT validation tools for developers. Obsessed with compliance automation and developer experience.