EU VAT Rates Data
Rates for 45 European countries — plus VAT number format descriptions and built-in format validation for every country. Checked daily against the European Commission TEDB and updated on any change. MIT licensed — here is how that pipeline works.
Quick Start
Pick your language and copy-paste to get started.
npm install eu-vat-rates-dataimport { getRate, getStandardRate, getAllRates, isEUMember, validateFormat, dataVersion } from 'eu-vat-rates-data'
// Get full record for a country
const fi = getRate('FI')
console.log(fi.standard) // 25.5
console.log(fi.reduced) // [10,13.5]
console.log(fi.eu_member) // true
console.log(fi.vat_abbr) // 'ALV'
console.log(fi.format) // 'FI + 8 digits'
console.log(fi.pattern) // '^FI\d{8}$'
// Shorthand for the standard rate
const de = getStandardRate('DE') // 19
// Iterate all 45 countries
const all = getAllRates()
for (const [code, rate] of Object.entries(all)) {
console.log(`${code}: ${rate.standard}%`)
}
// VAT number format validation — free, no API key
validateFormat('FI12345678') // true
validateFormat('INVALID') // false
// Type guards
isEUMember('NO') // false — Norway is in dataset but not EU
isEUMember('DE') // true
// Dataset freshness
console.log(`Rates as of ${dataVersion}`) // 2026-08-13What's in the Dataset
Each country record contains the following fields.
standardStandard VAT rate in percent (e.g. 25.5)reducedReduced rates, sorted ascending. Empty array when none.super_reducedSuper-reduced rate applied to a narrow set of essentials.parkingTransitional parking rate. Null for most countries.eu_memberWhether this is an EU-27 member state.currencyISO 4217 currency code (EUR for eurozone).vat_nameLocal name of the tax (e.g. 'Arvonlisävero').vat_abbrShort abbreviation (e.g. 'ALV', 'MwSt', 'TVA').formatHuman-readable VAT number format (e.g. 'ATU + 8 digits').built inpatternRegex string for VAT number format validation (e.g. '^ATU\\d{8}$').built in{
"country": "Finland",
"currency": "EUR",
"eu_member": true,
"vat_name": "Arvonlisävero",
"vat_abbr": "ALV",
"standard": 25.5,
"reduced": [
10,
13.5
],
"super_reduced": null,
"parking": null,
"format": "FI + 8 digits",
"pattern": "^FI\\d{8}$"
}EU VAT Rates 2026
Standard, reduced, and super-reduced rates for all 27 EU member states. Checked daily against the European Commission TEDB and updated on any change. Last confirmed: 13.08.2026.
| Country | Standard | Reduced | Super Reduced |
|---|---|---|---|
| 🇦🇹ATAustria | 20% | 10%, 13%, 19% | 4.9% |
| 🇧🇪BEBelgium | 21% | 6%, 12% | — |
| 🇧🇬BGBulgaria | 20% | 9% | — |
| 🇭🇷HRCroatia | 25% | 5%, 13% | — |
| 🇨🇾CYCyprus | 19% | 5%, 9% | 3% |
| 🇨🇿CZCzech Republic | 21% | 12% | — |
| 🇩🇰DKDenmark | 25% | — | — |
| 🇪🇪EEEstonia | 24% | 9%, 13% | — |
| 🇫🇮FIFinland | 25.5% | 10%, 13.5% | — |
| 🇫🇷FRFrance | 20% | 0.9%, 1.05%, 5.5%, 8.5%, 10%, 13% | 2.1% |
| 🇩🇪DEGermany | 19% | 7% | — |
| 🇬🇷GRGreece | 24% | 6%, 13%, 17% | 4% |
| 🇭🇺HUHungary | 27% | 5%, 18% | — |
| 🇮🇪IEIreland | 23% | 9%, 13.5% | — |
| 🇮🇹ITItaly | 22% | 5%, 10% | 4% |
| 🇱🇻LVLatvia | 21% | 5%, 12% | — |
| 🇱🇹LTLithuania | 21% | 5%, 12% | — |
| 🇱🇺LULuxembourg | 17% | 8%, 14% | 3% |
| 🇲🇹MTMalta | 18% | 5%, 7% | — |
| 🇳🇱NLNetherlands | 21% | 9% | — |
| 🇵🇱PLPoland | 23% | 5%, 8% | 8% |
| 🇵🇹PTPortugal | 23% | 6%, 13%, 16%, 22% | 6% |
| 🇷🇴RORomania | 21% | 11% | — |
| 🇸🇰SKSlovakia | 23% | 5%, 19% | — |
| 🇸🇮SISlovenia | 22% | 5%, 9.5% | — |
| 🇪🇸ESSpain | 21% | 10% | 4% |
| 🇸🇪SESweden | 25% | 6%, 12% | — |
Checked daily against EC TEDB — the official European Commission tax database — and updated on any change.
Reduced rates include all territorial variants (e.g. French overseas departments, Portuguese Azores).
European VAT Rates 2026 (Non-EU)
Standard and reduced VAT rates for European countries outside the EU — including Norway, Switzerland, United Kingdom, Ukraine, Turkey, and more. Last updated: 13.08.2026.
| Country | Standard | Reduced | Super Reduced |
|---|---|---|---|
| 🇦🇱ALAlbania | 20% | 6%, 10% | — |
| 🇦🇩ADAndorra | 4.5% | 1%, 2.5% | — |
| 🇧🇦BABosnia and Herzegovina | 17% | — | — |
| 🇬🇪GEGeorgia | 18% | — | — |
| 🇮🇸ISIceland | 24% | 11% | — |
| 🇽🇰XKKosovo | 18% | 8% | — |
| 🇱🇮LILiechtenstein | 8.1% | 2.6%, 3.8% | — |
| 🇲🇩MDMoldova | 20% | 8% | — |
| 🇲🇨MCMonaco | 20% | 5.5%, 10% | 2.1% |
| 🇲🇪MEMontenegro | 21% | 7%, 15% | — |
| 🇲🇰MKNorth Macedonia | 18% | 5%, 10% | — |
| 🇬🇧XINorthern Ireland | 20% | 5% | — |
| 🇳🇴NONorway | 25% | 12%, 15% | — |
| 🇷🇸RSSerbia | 20% | 10% | — |
| 🇨🇭CHSwitzerland | 8.1% | 2.6%, 3.8% | — |
| 🇹🇷TRTurkey | 20% | 1%, 10% | — |
| 🇺🇦UAUkraine | 20% | 7%, 14% | — |
| 🇬🇧GBUnited Kingdom | 20% | 5% | — |
Data sourced from the European Commission TEDB where available, supplemented by official national tax authority sources for non-EU countries.
VAT Number Formats & Validation
Every country's VAT number follows a different format — FR for France, ATU for Austria, 45 different patterns in total. Keeping those patterns accurate as tax authorities update them is maintenance work that belongs in a package, not your codebase. Every entry in this dataset includes a human-readable format description and a tested regex pattern. The built-in validateFormat() function runs locally — no latency, no rate limits.
import { validateFormat } from 'eu-vat-rates-data'
validateFormat('ATU12345678') // true
validateFormat('DE123456789') // true
validateFormat('INVALID') // false| Country | Format | Pattern |
|---|---|---|
| 🇦🇱ALAlbania | 1 letter + 8 digits + 1 letter | ^[A-Z]\d{8}[A-Z]$ |
| 🇦🇩ADAndorra | 1 letter + 6 digits + 1 letter | ^[A-Z]\d{6}[A-Z]$ |
| 🇦🇹ATAustria | ATU + 8 digits | ^ATU\d{8}$ |
| 🇧🇪BEBelgium | BE + 0/1 + 9 digits | ^BE[01]\d{9}$ |
| 🇧🇦BABosnia and Herzegovina | 12 digits | ^\d{12}$ |
| 🇧🇬BGBulgaria | BG + 9–10 digits | ^BG\d{9,10}$ |
| 🇭🇷HRCroatia | HR + 11 digits | ^HR\d{11}$ |
| 🇨🇾CYCyprus | CY + 8 digits + 1 letter | ^CY\d{8}[A-Z]$ |
| 🇨🇿CZCzech Republic | CZ + 8–10 digits | ^CZ\d{8,10}$ |
| 🇩🇰DKDenmark | DK + 8 digits | ^DK\d{8}$ |
| 🇪🇪EEEstonia | EE + 9 digits | ^EE\d{9}$ |
| 🇫🇮FIFinland | FI + 8 digits | ^FI\d{8}$ |
| 🇫🇷FRFrance | FR + 2 alphanumeric + 9 digits | ^FR[A-HJ-NP-Z0-9]{2}\d{9}$ |
| 🇬🇪GEGeorgia | 9 digits | ^\d{9}$ |
| 🇩🇪DEGermany | DE + 9 digits | ^DE\d{9}$ |
| 🇬🇷GRGreece | EL + 9 digits | ^EL\d{9}$ |
| 🇭🇺HUHungary | HU + 8 digits | ^HU\d{8}$ |
| 🇮🇸ISIceland | 5–6 digits | ^\d{5,6}$ |
| 🇮🇪IEIreland | IE + 7 digits + 1–2 letters | ^IE\d{7}[A-W][A-IW]?$|^IE\d[A-Z+*]\d{5}[A-W]$ |
| 🇮🇹ITItaly | IT + 11 digits | ^IT\d{11}$ |
| 🇽🇰XKKosovo | 9 digits | ^\d{9}$ |
| 🇱🇻LVLatvia | LV + 11 digits | ^LV\d{11}$ |
| 🇱🇮LILiechtenstein | 5 digits | ^\d{5}$ |
| 🇱🇹LTLithuania | LT + 9 or 12 digits | ^LT(\d{9}|\d{12})$ |
| 🇱🇺LULuxembourg | LU + 8 digits | ^LU\d{8}$ |
| 🇲🇹MTMalta | MT + 8 digits | ^MT\d{8}$ |
| 🇲🇩MDMoldova | 7 digits | ^\d{7}$ |
| 🇲🇨MCMonaco | FR + 2 alphanumeric + 9 digits | ^FR[A-HJ-NP-Z0-9]{2}\d{9}$ |
| 🇲🇪MEMontenegro | 8 digits | ^\d{8}$ |
| 🇳🇱NLNetherlands | NL + 9 digits + B + 2 digits | ^NL\d{9}B\d{2}$ |
| 🇲🇰MKNorth Macedonia | MK + 13 digits | ^MK\d{13}$ |
| 🇬🇧XINorthern Ireland | XI + 9 digits, 12 digits, or GD/HA + 3 digits | ^XI(\d{9}|\d{12}|(GD|HA)\d{3})$ |
| 🇳🇴NONorway | 9 digits + MVA | ^\d{9}MVA$ |
| 🇵🇱PLPoland | PL + 10 digits | ^PL\d{10}$ |
| 🇵🇹PTPortugal | PT + 9 digits | ^PT\d{9}$ |
| 🇷🇴RORomania | RO + 2–10 digits | ^RO\d{2,10}$ |
| 🇷🇸RSSerbia | 9 digits | ^\d{9}$ |
| 🇸🇰SKSlovakia | SK + 10 digits | ^SK\d{10}$ |
| 🇸🇮SISlovenia | SI + 8 digits | ^SI\d{8}$ |
| 🇪🇸ESSpain | ES + letter/digit + 7 digits + letter/digit | ^ES[A-Z0-9]\d{7}[A-Z0-9]$ |
| 🇸🇪SESweden | SE + 10 digits + 01 | ^SE\d{10}01$ |
| 🇨🇭CHSwitzerland | CHE-NNN.NNN.NNN (+ MWST/TVA/IVA) | ^CHE-?\d{3}\.?\d{3}\.?\d{3}[ ]?(MWST|TVA|IVA)?$ |
| 🇹🇷TRTurkey | 10 digits | ^\d{10}$ |
| 🇺🇦UAUkraine | 9 digits | ^\d{9}$ |
| 🇬🇧GBUnited Kingdom | GB + 9 digits, 12 digits, or GD/HA + 3 digits | ^GB(\d{9}|\d{12}|GD\d{3}|HA\d{3})$ |
Note: the "GR" code shown here is the ISO rates code. Greek VAT numbers themselves use the "EL" prefix, not "GR".
Format validation is step 1 of 2
It confirms the number is structured correctly. For production B2B workflows — invoicing, supplier onboarding, checkout tax exemption — you also need to verify the business is currently VAT-registered. The vatnode API checks against the official EU VIES database in real time.
Everything You Need, Nothing You Don't
A self-contained dataset — no network calls, no rate limits, no account.
45 Countries
EU-27 plus Norway, Switzerland, UK, Turkey, Ukraine and 13 more non-EU European countries.
6 Languages
Native packages for JavaScript/TypeScript, Python, PHP, Go, Ruby, and a WordPress plugin.
Checked Daily
A scheduled job compares the data against the EC TEDB every morning. A new package version goes out when a rate actually moves, not on a timer.
TypeScript Types
Full type safety with CountryCode, VatRate, and helper type guards included.
VAT Format Validation
Every country includes a format description and regex pattern. Built-in validateFormat() — free, no API key.
Available Packages
All packages ship the same dataset — pick the one for your stack.
WordPress / WooCommerce
Canonical dataset repo
Raw JSON data, update scripts, and GitHub Actions workflow for all packages.
Where the Package Stops
The dataset answers what a rate is. It cannot answer whether a VAT number in front of you belongs to a real, registered business — that check has to reach VIES.
The package, free and offline
- Standard, reduced, super-reduced and parking rates for 45 countries
validateFormat()— does this string look like a VAT number- EU membership flag, local VAT name and abbreviation
- No account, no key, no network call, MIT licensed
What the API adds
- Live VIES lookup — is this number registered right now
- Registered company name, address and registration date
- The VIES consultation number, your reference if the check is ever questioned
- National registry fallback when VIES is down, plus webhooks on status change
A format check catches typos. It does not catch a number that was valid last quarter and has since been deregistered — which is the case that costs money on a reverse-charge invoice.
Need VAT Number Validation Too?
The vatnode API validates EU VAT numbers against the official VIES database — real-time, with caching and webhook support.