Article type: How-to guide (one task: check EU VAT and UK EORI numbers from code)

Prerequisites: Python 3 with requests. No API key is needed for VIES or the HMRC EORI service. An Apify account only if you use the shortcut in section 5.

Tested on: 31 October 2026 (the run in section 4); the Python snippet was re-run on 1 November 2026

If you invoice EU business customers with reverse charge, or ship to the UK, you need to confirm their VAT or EORI number. The official services are free. The tricky part is handling their failures correctly.

1. The services

  • EU VAT: VIES, the European Commission's service. It has a REST endpoint: POST https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number with {"countryCode":"DE","vatNumber":"129273398"}.
  • GB EORI: HMRC's Check an EORI number API, open access: POST https://api.service.hmrc.gov.uk/customs/eori/lookup/check-multiple-eori with {"eoris":["GB220430231000"]}.
  • EU/XI EORI: the Commission's EOS validation service.
  • GB VAT: HMRC's Check a UK VAT number API, which needs an HMRC developer account and application.

2. The mistakes to avoid

  1. An outage is not "invalid". VIES relays each member state's database. When one is down you get errors like MS_UNAVAILABLE or MS_MAX_CONCURRENT_REQ. Record "not checked, try later", and never overwrite the last real answer with it.
  2. Validate locally first. Each country has a format and most have check digits. A typo caught locally never needs a network call.
  3. Go slowly. One number at a time, about one a second, and don't re-check the same number many times a day.
  4. Keep the proof. Pass your own VAT number as the requester and VIES returns a consultation number you can store with the invoice.
  5. Read the terms. VIES is for confirming the numbers of businesses you trade with; it forbids extracting or republishing its content.

3. A minimal VIES check

import requests, time def check(cc, num): r = requests.post("https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number", json={"countryCode": cc, "vatNumber": num}, timeout=30) if r.status_code >= 500: return "not_checked" # service down: try later  j = r.json() errors = [e.get("error") for e in j.get("errorWrappers", [])] if "INVALID_INPUT" in errors: return "bad_input" # fix the number; not an outage  if errors: return "not_checked" # MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ...: try later  return "valid" if j.get("valid") else "invalid" for cc, num in [("IE", "6388047V"), ("AT", "U13585627"), ("DE", "129273398")]: print(cc + num, check(cc, num)); time.sleep(1) 

4. A real run, 31 October 2026

Number Type Service Result
IE6388047V VAT VIES valid (cached from an earlier run that day, not re-asked)
ATU13585627 VAT VIES invalid ("not a valid VAT number for cross-border trade in AT on this date")
DE129273398 VAT VIES valid
GB220430231000 EORI HMRC valid

5. The shortcut (we built this)

We built an Apify Actor, VAT Number Checker & EORI Checker, that does the above for up to 500 numbers per run: local format and check-digit checks, outages returned as source_unavailable (free) instead of invalid, at most one VIES check per number per day, the official checkDate on every row, and a monitor mode that flags numbers that became_invalid. It's independent and not affiliated with the European Commission or HMRC, and it's for checking the businesses you trade with.

Pay per event: base price $0.002 per fresh valid or invalid answer, plus $0.00005 per run per GB of memory for the Actor start (one event at the default 256 MB) and $0.01 per monitor run in which a number changed. Higher Apify plans pay less. Cached answers, outages and local failures are free.

VAT Number Checker & EORI Checker on Apify

Your Evenings