Awesome Go

eu-vat-rates-data-go

CategoryFinancial
SubcategoryFinancial
Stars1

VAT rates and VAT number formats for 45 European countries, embedded at compile time and refreshed daily from the European Commission TEDB

About eu-vat-rates-data-go

eu-vat-rates-data-go

Go Reference Test Last updated License: MIT

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.

Part of VATNode VAT Rates · canonical dataset · methodology · other languages: JavaScript, Python, PHP, Ruby

  • Standard, reduced, super-reduced, and parking rates
  • EUMember field on every country — true for EU-27, false for non-EU
  • VATName — official name of the VAT tax in the country's primary official language
  • VATAbbr — 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
  • Zero dependencies — data embedded with //go:embed
  • Fully typed — works with Go 1.21+
  • EU rates checked daily via GitHub Actions, new version tagged only when rates change

Also available in: JavaScript/TypeScript (npm) · Python (PyPI) · PHP (Packagist) · 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 — ValidateFormat() 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 the VIES consultation number as your reference for the check — there's vatnode:

  • Live VIES validation, with national-database fallback when VIES is down
  • Registered company name, address, registration date
  • VIES consultation number — a timestamped record that the check was made against VIES
  • 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"

See what the API adds → · Get a free API key


Installation

go get github.com/vatnode/eu-vat-rates-data-go

Usage

package main

import (
    "fmt"
    euvatrates "github.com/vatnode/eu-vat-rates-data-go"
)

func main() {
    // Full rate struct for a country
    fi, ok := euvatrates.GetRate("FI")
    if ok {
        fmt.Printf("%s: %.1f%% (EU member: %v, tax: %s / %s)\n", fi.Country, fi.Standard, fi.EUMember, fi.VATName, fi.VATAbbr)
        // Finland: 25.5% (EU member: true, tax: Arvonlisävero / ALV)
    }

    // Just the standard rate
    standard, ok := euvatrates.GetStandardRate("DE")
    fmt.Println(standard) // 19

    // EU membership check — false for non-EU countries (GB, NO, CH, ...)
    if euvatrates.IsEUMember(userInput) {
        rate, _ := euvatrates.GetRate(userInput)
        _ = rate
    }

    // Dataset membership check (all 45 countries)
    if euvatrates.HasRate(userInput) {
        rate, _ := euvatrates.GetRate(userInput)
        _ = rate
    }

    // All 45 countries
    all := euvatrates.GetAllRates()
    for code, rate := range all {
        fmt.Printf("%s: %.1f%%\n", code, rate.Standard)
    }

    // When were EU rates last fetched?
    fmt.Println(euvatrates.DataVersion()) // "2026-03-27"

    // VAT number format validation — no API key, no network call
    euvatrates.ValidateFormat("ATU12345678") // → true
    euvatrates.ValidateFormat("DE123456789") // → true
    euvatrates.ValidateFormat("INVALID")     // → false

    // Access format metadata directly
    at, _ := euvatrates.GetRate("AT")
    fmt.Println(at.Format)   // "ATU + 8 digits"
    fmt.Println(at.Pattern) // "^ATU\\d{8}$"

    // Flag emoji from a 2-letter country code — no lookup table, computed from regional indicator symbols
    fmt.Println(euvatrates.GetFlag("FI")) // "🇫🇮"
    fmt.Println(euvatrates.GetFlag("DE")) // "🇩🇪"
    fmt.Println(euvatrates.GetFlag("XX")) // "" (empty string for unknown/invalid codes)
}

Example: charging VAT on an invoice

Rates alone do not determine invoice treatment. Resolve place-of-supply, customer status, category, exemptions, and any reverse-charge eligibility in your tax logic first; then use the dataset for the applicable numeric rate.

import (
    "math"

    euvatrates "github.com/vatnode/eu-vat-rates-data-go"
)

// Money in minor units (cents). Never floats.
type Invoice struct {
    VATCents      int64
    TotalCents    int64
    ReverseCharge bool
}

func InvoiceTotal(netCents int64, buyerCountry string, reverseChargeEligible bool) Invoice {
    if reverseChargeEligible {
        return Invoice{VATCents: 0, TotalCents: netCents, ReverseCharge: true}
    }

    rate, ok := euvatrates.GetStandardRate(buyerCountry)
    if !ok {
        return Invoice{VATCents: 0, TotalCents: netCents}
    }

    vatCents := int64(math.Round(float64(netCents) * rate / 100))
    return Invoice{VATCents: vatCents, TotalCents: netCents + vatCents}
}

// Domestic sale in Finland — 25.5%
InvoiceTotal(10000, "FI", false)
// → {VATCents: 2550, TotalCents: 12550, ReverseCharge: false}

// Finnish seller, German business buyer — reverse charge
InvoiceTotal(10000, "DE", true)
// → {VATCents: 0, TotalCents: 10000, ReverseCharge: true}

reverseChargeEligible must come from applicable tax logic and evidence. ValidateFormat() only checks a number's shape; it does not establish registration or eligibility.


Types

type VatRate struct {
    Country      string    `json:"country"`
    Currency     string    `json:"currency"`
    EUMember     bool      `json:"eu_member"`
    VATName      string    `json:"vat_name"`
    VATAbbr      string    `json:"vat_abbr"`
    Standard     float64   `json:"standard"`
    Reduced      []float64 `json:"reduced"`
    SuperReduced *float64  `json:"super_reduced"`
    Parking      *float64  `json:"parking"`
    Format       string    `json:"format"`   // "ATU + 8 digits"
    Pattern      string    `json:"pattern"`  // "^ATU\\d{8}$" — always present for all 45 countries
    Identifiers  Identifiers `json:"identifiers"` // names of the registrar, register and identifiers
}

identifiers holds names, never numbers: registry_authority_name, registry_name, registry_code_name, tax_id_name and vat_id_name — the company registrar, the company register, the register number, the business tax number and the VAT identification number. Each is keyed by ISO 639-1 language (every official language, plus en) with the name as the value; for Finland registry_code_name is { fi: "Y-tunnus", sv: "FO-nummer", en: "Business ID" }. A nil map means no official name could be confirmed.


Data source & update frequency

How the daily check works, and what changed when: vatnode.dev/data.

  • EU-27 rates: European Commission TEDB, checked against the source daily at 07:00 UTC, updated on any change
  • Non-EU rates: maintained manually, updated on official rate changes
  • New git tag + pkg.go.dev version published only when rates change

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 (checked daily against EC TEDB, updated on any change):

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


Changelog

See CHANGELOG.md.


License

MIT

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

Frequently Asked Questions

What is eu-vat-rates-data-go?

eu-vat-rates-data-go is a Financial library for the Go programming language. VAT rates and VAT number formats for 45 European countries, embedded at compile time and refreshed daily from the European Commission TEDB

How do I install eu-vat-rates-data-go?

Install eu-vat-rates-data-go with the Go module system using `go get vatnode/eu-vat-rates-data-go`. Check the repository for the current installation instructions.

What category does eu-vat-rates-data-go belong to?

eu-vat-rates-data-go is listed under Financial, specifically Financial.

← Back to Financial