Skip to content

vatnode/eu-vat-rates-data-js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

123 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

eu-vat-rates-data

npm version Last updated License: MIT

VAT rates for 44 European countries — all EU-27 member states plus Norway, Switzerland, the United Kingdom, and more. EU rates sourced from the European Commission TEDB and checked daily. Published automatically when rates change.

  • 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 validateFormat() — free, no API key needed — unique to this package
  • TypeScript types included — works in Node.js and the browser
  • JSON file committed to git — full rate-change history via git log
  • Checked daily via GitHub Actions, new npm version published only when rates change

Available in 5 ecosystems:

Language Package Install
JavaScript / TypeScript npm npm install eu-vat-rates-data
Python PyPI pip install eu-vat-rates-data
PHP Packagist composer require vatnode/eu-vat-rates-data
Go pkg.go.dev go get github.com/vatnode/eu-vat-rates-data-go
Ruby RubyGems gem install eu_vat_rates_data

Why eu-vat-rates-data?

Package Auto-updates VAT number format Source
eu-vat-rates-data ✅ daily (GitHub Actions) format + pattern + validateFormat() EC TEDB (official)
sales-tax ❌ manual hardcoded
eu-vat-rates ❌ last 2023 hardcoded
eu-vat ❌ last 2018 external API
vat-calculator ❌ last 2015 hardcoded

Two key differences: (1) every other package relies on manual updates or is abandoned — eu-vat-rates-data publishes automatically when rates change, same day. (2) This is the only package that includes VAT number format descriptions and regex patterns for all 44 countries, with a built-in validateFormat() function — no API key or network call needed.


Installation

npm install eu-vat-rates-data
# or
yarn add eu-vat-rates-data
# or
pnpm add eu-vat-rates-data

Usage

TypeScript / ESM

import { getRate, getStandardRate, getAllRates, isEUMember, isKnownCountry, dataVersion } from 'eu-vat-rates-data'

// Full rate object for a country
const fi = getRate('FI')
// {
//   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
// }

// Just the standard rate
getStandardRate('DE') // → 19

// EU membership check — false for non-EU countries (GB, NO, CH, ...)
if (isEUMember(userInput)) {
  const rate = getRate(userInput) // type narrowed to EUMemberCode
}

// Dataset membership check — true for any of the 44 European countries
if (isKnownCountry(userInput)) {
  const rate = getRate(userInput) // type narrowed to CountryCode
}

// All 44 countries at once
const all = getAllRates()
Object.entries(all).forEach(([code, rate]) => {
  console.log(`${code}: ${rate.standard}%`)
})

// When were these rates last fetched?
console.log(dataVersion) // e.g. "2026-03-27"

// VAT number format validation — no API key, no network call
import { validateFormat } from 'eu-vat-rates-data'
validateFormat('ATU12345678')  // → true
validateFormat('DE123456789')  // → true
validateFormat('INVALID')      // → false

// Access format metadata directly
const at = getRate('AT')
console.log(at.format)   // "ATU + 8 digits"
console.log(at.pattern)  // "^ATU\\d{8}$"

// Flag emoji from a 2-letter country code — no lookup table, computed from regional indicator symbols
import { getFlag } from 'eu-vat-rates-data'
getFlag('FI')  // → '🇫🇮'
getFlag('DE')  // → '🇩🇪'
getFlag('XX')  // → '' (empty string for unknown/invalid codes)

CommonJS

const { getRate, isEUMember, isKnownCountry } = require('eu-vat-rates-data')

console.log(getRate('FR').standard) // 20

Direct JSON — always the latest data

# Served directly from GitHub CDN:
https://cdn.jsdelivr.net/gh/vatnode/eu-vat-rates-data@main/data/eu-vat-rates-data.json

# Raw GitHub (always latest commit):
https://raw.githubusercontent.com/vatnode/eu-vat-rates-data/main/data/eu-vat-rates-data.json
const res = await fetch(
  'https://cdn.jsdelivr.net/gh/vatnode/eu-vat-rates-data@main/data/eu-vat-rates-data.json'
)
const { rates } = await res.json()
console.log(rates.DE.standard) // 19

Data structure

interface VatRate {
  country:       string        // "Finland"
  currency:      string        // "EUR" (or "DKK", "GBP", …)
  eu_member:     boolean       // true for EU-27, false for non-EU
  vat_name:      string        // "Arvonlisävero" — official name in primary local language
  vat_abbr:      string        // "ALV" — short abbreviation used locally
  standard:      number        // 25.5
  reduced:       number[]      // [10, 13.5] — sorted ascending
  super_reduced: number | null // null when not applicable
  parking:       number | null // null when not applicable
  format:        string        // "FI + 8 digits" — human-readable VAT number format
  pattern:       string        // "^FI\\d{8}$" — regex for format validation, always present
}

reduced may contain rates for special territories (e.g. French DOM departments, Azores/Madeira for Portugal, Canary Islands for Spain). All values come verbatim from EC TEDB.

Country codes

Standard ISO 3166-1 alpha-2, with one EU convention: Greece is GR (TEDB internally uses EL, which this package normalises).

Example JSON entry

{
  "version": "2026-03-31",
  "source": "European Commission TEDB",
  "rates": {
    "FI": {
      "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}$"
    }
  }
}

Data source & update frequency

Rates are fetched from the European Commission Taxes in Europe Database (TEDB) via its official SOAP web service:

  • Refreshed: daily at 07:00 UTC
  • Published: new npm version only when actual rates change (not on date-only updates)
  • History: git log -- data/eu-vat-rates-data.json gives a full audit trail of VAT changes across the EU

Data is fetched by the eu-vat-rates-data repository and synced here daily.


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 member states:

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

Additional European countries:

AD AL BA CH GB GE IS LI MC MD ME MK NO RS TR UA XK

44 countries total.


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

License

MIT

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

About

VAT rates for 44 European countries — EU-27 plus Norway, Switzerland, UK, and more. Updated daily from EC TEDB.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors