VAT rates for 45 European countries — EU-27 plus Norway, Switzerland, UK, and more. Updated daily. From vatnode.dev — live VIES validation via API.
Project description
eu-vat-rates-data · Python
VAT rates for 45 European countries — EU-27 plus Norway, Switzerland, UK, and more. EU rates sourced from the European Commission TEDB and checked daily. Non-EU rates maintained manually.
- Standard, reduced, super-reduced, and parking rates
eu_memberflag on every country —Truefor EU-27,Falsefor non-EUvat_name— official name of the VAT tax in the country's primary official languagevat_abbr— short abbreviation used locally (e.g. "ALV", "MwSt", "TVA")format— human-readable VAT number format (e.g."ATU + 8 digits") — unique to this packagepattern— regex for VAT number validation + built-invalidate_format()— free, no API key needed — unique to this package- Full type hints — works with mypy and pyright out of the box
- Data embedded in the package — works offline, no network calls
- EU rates checked daily via GitHub Actions, new version published only when rates change
Also available in: JavaScript/TypeScript (npm) · PHP (Packagist) · Go · Ruby (RubyGems)
Need live VIES validation?
This package gives you VAT rates and format checks for free, offline, in your code. It does not call VIES — validate_format() only checks the shape of a VAT number, not whether it actually exists.
For live VIES validation — confirming a VAT ID is real, pulling the registered company name and address, and getting a VIES consultation number (audit-grade proof of validation) — there's vatnode:
- Live VIES validation, with national-database fallback when VIES is down
- Registered company name, address, registration date
- VIES consultation number for compliance and audit trails
- Webhooks for VAT status changes
- Official MCP server so AI agents (Claude, Cursor, ChatGPT) can validate VAT IDs directly
- Free tier — no credit card needed
curl https://api.vatnode.dev/v1/vat/IE6388047V \
-H "Authorization: Bearer YOUR_API_KEY"
Installation
pip install eu-vat-rates-data
# or
uv add eu-vat-rates-data
# or
poetry add eu-vat-rates-data
Usage
from eu_vat_rates_data import get_rate, get_standard_rate, get_all_rates, is_eu_member, has_rate, data_version
# Full rate object for a country
fi = get_rate("FI")
# {
# "country": "Finland",
# "currency": "EUR",
# "eu_member": True,
# "vat_name": "Arvonlisävero",
# "vat_abbr": "ALV",
# "standard": 25.5,
# "reduced": [10.0, 13.5],
# "super_reduced": None,
# "parking": None
# }
# Just the standard rate
get_standard_rate("DE") # → 19.0
# EU membership check — False for non-EU countries (GB, NO, CH, ...)
if is_eu_member(user_input):
rate = get_rate(user_input)
# Dataset membership check (all 45 countries)
if has_rate(user_input):
rate = get_rate(user_input)
# All 45 countries at once
all_rates = get_all_rates()
for code, rate in all_rates.items():
print(f"{code}: {rate['standard']}%")
# When were EU rates last fetched?
print(data_version) # e.g. "2026-03-27"
# VAT number format validation — no API key, no network call
from eu_vat_rates_data import validate_format
validate_format("ATU12345678") # → True
validate_format("DE123456789") # → True
validate_format("INVALID") # → False
# Access format metadata directly
at = get_rate("AT")
print(at["format"]) # "ATU + 8 digits"
print(at["pattern"]) # "^ATU\\d{8}$"
# Flag emoji from a 2-letter country code — no lookup table, computed from regional indicator symbols
from eu_vat_rates_data import get_flag
get_flag("FI") # => "🇫🇮"
get_flag("DE") # => "🇩🇪"
get_flag("XX") # => "" (empty string for unknown/invalid codes)
Type hints
from eu_vat_rates_data import VatRate
rate: VatRate = get_rate("FI") # type checker knows this is a TypedDict
class VatRate(TypedDict):
country: str
currency: str
eu_member: bool
vat_name: str
vat_abbr: str
standard: float
reduced: list[float]
super_reduced: float | None
parking: float | None
format: str # "FI + 8 digits"
pattern: str # "^FI\\d{8}$" — always present for all 45 countries
Data structure
reduced may contain rates for special territories (e.g. French DOM departments, Azores/Madeira for Portugal). For EU countries, all values come from EC TEDB.
Standard ISO 3166-1 alpha-2 country codes. Greece is GR (TEDB internally uses EL, which this package normalises).
Example
get_rate("NO")
# {
# "country": "Norway",
# "currency": "NOK",
# "eu_member": False,
# "vat_name": "Merverdiavgift",
# "vat_abbr": "MVA",
# "standard": 25.0,
# "reduced": [12.0, 15.0],
# "super_reduced": None,
# "parking": None
# }
Data source & update frequency
- EU-27 rates: European Commission TEDB, refreshed daily at 07:00 UTC
- Non-EU rates: maintained manually, updated on official rate changes
- Published to PyPI only when actual rates change (not on date-only updates)
Keeping rates current
Rates are bundled at install time. A new package version is published automatically whenever rates change — but your installed version will not update itself.
Recommended: add Renovate or Dependabot to your repo. They detect new versions and open a PR automatically whenever rates change — no manual update commands needed.
Need real-time accuracy? Fetch the always-current JSON directly:
https://cdn.jsdelivr.net/gh/vatnode/eu-vat-rates-data@main/data/eu-vat-rates-data.json
No package needed — parse it with a single fetch() / http.get() / file_get_contents() call and cache locally.
Covered countries
EU-27 (daily auto-updates via EC TEDB):
AT BE BG CY CZ DE DK EE ES FI FR GR HR HU IE IT LT LU LV MT NL PL PT RO SE SI SK
Non-EU Europe (manually maintained):
AD AL BA CH GB GE IS LI MC MD ME MK NO RS TR UA XK
Need to validate VAT numbers?
This package provides VAT rates only. If you also need to validate EU VAT numbers against the official VIES database — confirming a business is VAT-registered — check out vatnode.dev, a simple REST API with a free tier.
curl https://api.vatnode.dev/v1/vat/FI17156132 \
-H "Authorization: Bearer vat_live_..."
# → { "valid": true, "companyName": "Suomen Pehmeä Ikkuna Oy" }
Changelog
2026-04-25
- fix: Corrected Sweden (SE) VAT number regex — was
^SE\d{12}$, now correctly requires the mandatory01suffix:^SE\d{10}01$.
License
MIT
If you find this useful, a ⭐ on GitHub is appreciated.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file eu_vat_rates_data-2026.5.20.tar.gz.
File metadata
- Download URL: eu_vat_rates_data-2026.5.20.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8306465ba4388fbc05eaa14d9536fa2822c50ddf1cc993a1fc42544a9dd5d47
|
|
| MD5 |
112892b3bccac49fe04ec1c729e6c933
|
|
| BLAKE2b-256 |
8f622b5ab9fb8deab7cbe95550606ad7e1959ec8537f191bdebc9d5db25a6d48
|
File details
Details for the file eu_vat_rates_data-2026.5.20-py3-none-any.whl.
File metadata
- Download URL: eu_vat_rates_data-2026.5.20-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed75a4b3638cc8e6e4fa2e246c88819221a1da0ba0edebfaf50346d88e206ef8
|
|
| MD5 |
b269817d0b3f9053a1b8e6aaebe1bec3
|
|
| BLAKE2b-256 |
aec4ac2126aa41edf6a5d5edf986c9d867217b9593a844e0311039c3ff08ca8a
|