eu-validate documentation
Validate EU identifiers locally in Node or the browser. The offline library has zero runtime dependencies; its validators make no network requests. Hosted VIES and KvK registration lookups are planned separately.
Install and validate
npm install @alosha/eu-validate@^0.6.0
import { validateVAT, validateIBAN, validateBSN } from '@alosha/eu-validate'
validateVAT('NL123456782B01').valid // true
validateIBAN('NL91ABNA0417164300').valid // true
validateBSN('111222334').errors // ['CHECKSUM_FAILED']ESM and CommonJS exports include TypeScript declarations. VAT, IBAN, BSN and KvK inputs are normalized by removing spaces, dots, dashes and slashes and converting letters to uppercase. Postal inputs are trimmed and uppercased.
Offline checks and coverage
- validateVAT
- EU VAT format and available checksum rules for all 27 country prefixes. Documented FR, CZ and LV sub-cases have no offline-verifiable checksum.
- validateIBAN
- National character layout, exact length and mod-97 for all 89 countries in SWIFT IBAN registry release 103 (September 2026).
- validateBSN
- Dutch eight/nine-digit format and 11-proof; all-zero values fail.
- validateKvK
- Eight-digit Dutch company-number format. It does not establish registration; checksum is null.
- validatePostalCode
- Format rules for NL, DE, FR, BE, ES and IT, with explicit coverage and an optional strict mode.
- validate
- Dispatch by type. Postal calls also accept country and strict options.
Passing checks does not establish company registration, bank-account existence, identity or account ownership. IBAN validation does not implement every domestic account checksum.
Read a validation result
{
valid: true,
input: 'NL91 ABNA 0417 1643 00',
normalized: 'NL91ABNA0417164300',
country: 'NL',
type: 'iban',
checks: { format: true, checksum: true },
errors: []
}Check valid for the validator's outcome. Require checks.checksum === true when your application needs a confirmed checksum; null means the checksum did not run or cannot be checked for that case. For postal codes, also inspect checks.formatSupported. isValid narrows valid: true, while assertValid throws ValidationError when valid is false.
Postal coverage and strict mode
Default mode preserves historical acceptance for EU countries without a format pattern and reports formatSupported: false. That acceptance does not confirm the format. Choose strict: true to reject an unchecked format with FORMAT_NOT_SUPPORTED. Supported patterns behave the same in both modes.
import { validatePostalCode, validate } from '@alosha/eu-validate'
validatePostalCode('1011 AB', { country: 'NL', strict: true })
// valid: true, checks.formatSupported: true
validatePostalCode('D02 AF30', { country: 'IE', strict: true })
// valid: false, errors: ['FORMAT_NOT_SUPPORTED']
validate('D02 AF30', { type: 'postalCode', country: 'IE' })
// legacy acceptance: valid: true, checks.formatSupported: falseCountry codes are trimmed and uppercased. EU_COUNTRIES uses ISO GR for Greece; VAT-specific tables and results use EL. Postal validation accepts GR or the historical EL alias and returns GR.
Inputs, errors and privacy
MAX_INPUT_LENGTH is 256 raw UTF-16 code units. Length is checked before trimming, so an excessive whitespace-only string returns INPUT_TOO_LONG. Validation reports the first applicable failure. Handle type: null from malformed dispatcher options before passing the result to helpers that expect a known identifier type.
- INVALID_INPUT
- A JavaScript caller supplied a non-string. The result has input: an empty string; no coercion is performed.
- INPUT_TOO_LONG
- The raw identifier exceeds 256 UTF-16 code units, before trimming or normalization.
- EMPTY_INPUT
- Empty or whitespace-only input within the raw length limit.
- INVALID_OPTIONS
- Malformed dispatcher or postal options. An unknown dispatcher type returns type: null.
- COUNTRY_REQUIRED
- Postal country is missing or blank.
- UNKNOWN_COUNTRY
- VAT or IBAN country has no supported rule.
- UNSUPPORTED_COUNTRY
- Postal country is outside the supported EU set.
- FORMAT_NOT_SUPPORTED
- Postal strict mode found no format rule. This reports missing coverage, not a known bad postal code.
- INVALID_FORMAT
- The identifier fails a supported character-layout or country-length rule.
- CHECKSUM_FAILED
- A performed checksum failed.
- CHECKSUM_NOT_VERIFIABLE
- Informational VAT checksum exception or a legacy postal coverage gap; valid can still be true.
ValidationError messages omit the identifier. Its result property remains accessible but is non-enumerable. Validation results themselves contain the original and normalized values: avoid explicitly logging sensitive result fields.
Upgrade from 0.5.0
Review the new input and option errors, the 256-code-unit limit, Greek country metadata and stricter IBAN acceptance. Costa Rica's IBAN length is corrected to 22. Postal strict mode is opt-in; the default compatibility behavior is retained. The release is verified by 400 tests and installed-package runtime and type checks on Node 22, 24 and 26.