VAT rates for 44 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")- 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)
pip install eu-vat-rates-data
# or
uv add eu-vat-rates-data
# or
poetry add eu-vat-rates-datafrom 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 44 countries)
if has_rate(user_input):
rate = get_rate(user_input)
# All 44 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"from eu_vat_rates_data import VatRate
rate: VatRate = get_rate("FI") # type checker knows this is a TypedDictclass 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 | Nonereduced 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).
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
# }- 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)
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
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" }MIT
If you find this useful, a ⭐ on GitHub is appreciated.