Skip to main content

VAT rates for 44 European countries — EU-27 plus Norway, Switzerland, UK, and more. Updated daily, published automatically when rates change.

Project description

eu-vat-rates-data · Python

PyPI version Python versions Last updated License: MIT

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_member flag on every country — True for EU-27, False for non-EU
  • vat_name — official name of the VAT tax in the country's primary official language
  • vat_abbr — short abbreviation used locally (e.g. "ALV", "MwSt", "TVA")
  • format — human-readable VAT number format (e.g. "ATU + 8 digits") — unique to this package
  • pattern — regex for VAT number validation + built-in validate_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)


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 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"

# 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 44 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 mandatory 01 suffix: ^SE\d{10}01$.

License

MIT

If you find this useful, a ⭐ on GitHub is appreciated.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eu_vat_rates_data-2026.4.25.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eu_vat_rates_data-2026.4.25-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file eu_vat_rates_data-2026.4.25.tar.gz.

File metadata

  • Download URL: eu_vat_rates_data-2026.4.25.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for eu_vat_rates_data-2026.4.25.tar.gz
Algorithm Hash digest
SHA256 43f27e409294222e3d298afc69030ca086bb63627247920e0e7f8aede463aa16
MD5 9c747124d9126b65f4209108bb195e47
BLAKE2b-256 f1ffdb4a76e874359ec1b5f2786c99e7f6531c2dacac4ced1779eba486ce740d

See more details on using hashes here.

File details

Details for the file eu_vat_rates_data-2026.4.25-py3-none-any.whl.

File metadata

File hashes

Hashes for eu_vat_rates_data-2026.4.25-py3-none-any.whl
Algorithm Hash digest
SHA256 6cae2895f997a581ddaa9d1d221b70e03aaa7d7b697aa01fd1261610a44728e0
MD5 afe0cbe0a2bd6407cdf4b5d2e4783929
BLAKE2b-256 230273d33ec5fe2f3effa3d6a88b890dc0a832cf956d469ec59e46c81e8ad3ea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page