EU VAT Number Validator — VIES, Bulk, With Company Name
Pricing
Pay per event
EU VAT Number Validator — VIES, Bulk, With Company Name
Validate EU VAT numbers in bulk against the European Commission's VIES service. Returns the registered company name and address where the member state discloses them, a consultation number that is legal proof of the check, and an optional trader name and address match. Checks the national.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Benjamin Jerez
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
20 hours ago
Last modified
Categories
Share
EU VAT Number Validator — VIES, Bulk, With Company Name and Address
Validate EU VAT numbers in bulk against VIES, the European Commission's front end to the 27 national VAT registers plus Northern Ireland. For each number you get validity, the registered company name and address where the member state discloses them, the consultation number that is your legal record of the check, and an optional match of the company details you hold against the register.
No API key. No scraping. The Commission's own REST service, queried live.
What a check returns
IT00159560366:
| Field | Value |
|---|---|
countryCode, vatNumber | IT · 00159560366 |
formatValid, checksumChecked, checksumValid | true · true · true |
viesChecked, valid, status | true · true · VALID |
companyName | FERRARI S.P.A. |
companyAddress | VIA EMILIA EST 1163 41122 MODENA MO |
requestDate | 2026-09-18T13:12:45.845Z |
requestIdentifier | WAPIAAAAaC0peNOd |
The same run also returned SA SODIMAS for FR40303265045, NV Anheuser-Busch InBev in Leuven for BE0417497106, ORLEN SPÓŁKA AKCYJNA for PL7740001454, Carlsberg A/S for DK61056416, Telefonaktiebolaget LM Ericsson for SE556016068001, Hrvatski Telekom d.d. for HR81793146560, ČEZ, a. s. for CZ45274649 and ΟΡΓΑΝΙΣΜΟΣ ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ ΤΗΣ ΕΛΛΑΔΟΣ for EL094019245.
A summary row comes first with the counts, the number of VIES calls made, and the availability of every national database at the moment of the run.
Which countries release the company name
This surprises people, so the Actor states it on the row rather than leaving a blank. From live runs against all 27 member states:
Name and address returned: AT, BE, BG, CY, CZ, DK, EE, EL, FI, FR, HR, HU, IE, IT, LU, LV, MT, NL, PL, PT, RO, SE, SI, SK.
Name only: LT, which returns the company name and the literal N/A in place of the address.
Nothing returned, by policy: DE and ES. Both answer --- for every trader. A German number is valid or it is not, and that is all you get.
When that happens the row carries detailsDisclosed: false and an explanation saying the field is empty by policy, not because the record is thin. The three different sentinels member states use for "no value" — ---, an empty string and N/A — are all normalised to null, so nothing downstream ever has to treat N/A as a company name.
Verifying the company details you already hold
This is the part an auditor wants, and it is the reason the non-disclosing countries are not a dead end.
Supply traderDetails alongside the numbers and VIES compares each field against the register and answers VALID or INVALID per field — without ever revealing the registered value. So you can prove that the VAT number on an invoice belongs to the company named on that invoice, even in Spain, where the name is never disclosed.
From the test run, ESA28015865 with {"name": "TELEFONICA SA", "city": "MADRID"}:
traderNameMatch: VALIDtraderCityMatch: VALIDcompanyName: null (Spain does not disclose)requestIdentifier: bb948748-c43f-4724-9421-2aee5672709b
And ESA15022510 with a deliberately wrong name but the right address:
traderNameMatch: INVALIDtraderPostalCodeMatch: VALIDtraderCityMatch: VALID
Only some member states run this comparison. In testing, Spain processed it and returned real VALID/INVALID flags. France, Italy, Belgium, Poland, Luxembourg, Denmark, Ireland and Germany all answered NOT_PROCESSED for every field. When that happens the Actor sets matchProcessed: false and says which country declined, rather than leaving five empty columns that look like failures. The VAT number itself is still checked normally.
The match needs requesterVatNumber — your own valid EU VAT number. Without it VIES ignores the trader fields silently.
The consultation number, and why it matters
requestIdentifier is the reference VIES issues for a consultation. Under EU VAT rules the supplier carries the burden of proving that a zero-rated intra-Community supply went to a genuinely VAT-registered customer. A screenshot is weak evidence; the consultation number is the reference a tax authority can look up in the Commission's own logs to confirm that you checked, what you asked, and on which date.
It is only issued when you supply requesterVatNumber. Confirmed directly: the same request to FR40303265045 returned requestIdentifier: "" without requester details and WAPIAAAAaC0iRI3o with them. If you are keeping evidence for an audit, fill that field in — it costs nothing and it is the whole point.
The format varies by member state. Most return a sixteen-character token like WAPIAAAAaC0peNOd; Spain, Sweden and Austria return a UUID such as bb948748-c43f-4724-9421-2aee5672709b. Both are equally valid; store whatever comes back.
An outage is not an invalid number
Each national VAT database can go down independently while the rest of VIES stays up. VIES reports this inside an HTTP 200 response, in an envelope that looks nothing like a normal answer:
{"actionSucceed": false, "errorWrappers": [{"error": "MS_UNAVAILABLE"}]}
A validator that parses only the happy path reads no valid: true and writes valid: false. Every customer in that country is then marked as having a bad VAT number, on a day when nothing was wrong with any of them. That is the single most damaging thing this kind of tool can do, and it is why the Actor never sets valid from anything other than an answer that VIES actually gave.
Each failure mode gets its own status and a plain explanation, and valid stays null:
| VIES error | status | Retried |
|---|---|---|
MS_UNAVAILABLE | UNAVAILABLE | yes |
SERVICE_UNAVAILABLE | UNAVAILABLE | yes |
TIMEOUT | TIMEOUT | yes |
MS_MAX_CONCURRENT_REQ | RATE_LIMITED | yes |
GLOBAL_MAX_CONCURRENT_REQ | RATE_LIMITED | yes |
INVALID_INPUT | INVALID_INPUT | no |
INVALID_REQUESTER_INFO | INVALID_REQUESTER | no |
VOW-ERR-* | REJECTED | no |
With checkServiceStatusFirst on, the Actor reads check-status before it starts, records the availability of all 28 databases on the summary row, and does not spend a request on a country already reported down — those rows come back UNAVAILABLE with the country named.
The format and check-digit test, before any network call
Every number is checked against its national format and check digit locally first. A typo is caught for free, and VIES — which is slow and rate-limited — is not asked a question that has only one possible answer.
Two different judgements, kept apart on purpose:
formatValid— is the length and character set right for that country? Afalsehere is certain, so the VIES call is skipped (skipFormatInvalid, on by default).checksumValid— does it satisfy the national check-digit rule? Afalsehere is very probably a typo but not a proof, so by default the number is still sent to VIES. VIES is the authority; a local algorithm is not.
That asymmetry is deliberate. A check-digit rule that is slightly wrong, applied as a hard filter, quietly deletes real customers from your results. You can turn on skipChecksumInvalid if you would rather have the speed.
All 27 member states plus XI have a format and length rule. Check digits are implemented for all 27 member states, and each one was verified against real VAT numbers that VIES itself confirmed valid — never against a published example.
Where a country issues numbers under several different schemes that cannot be told apart from the number alone, the Actor reports checksumChecked: false instead of guessing: Bulgarian and Czech personal identifiers, Latvian natural-person codes, pre-2013 Irish numbers, French keys containing letters, and Northern Irish GD/HA government numbers.
Three rules are allowed to confirm a number but never to reject one, because they could not be verified to the same standard: the Dutch elfproef, the nine-digit Lithuanian branch, and Northern Ireland.
The Dutch case is the instructive one. Sole traders registered since 1 January 2020 carry a randomly generated number that does not satisfy the old elfproef, and they are entirely valid. So a passing Dutch check digit is reported as a pass and a failing one as not checked rather than as a wrong number. Erring the other way would reject every Dutch one-person business in a list.
Across 94 VAT numbers that VIES confirmed valid, in all 27 member states, the local rules produced zero false rejections, while catching 98.4% of randomly injected single-digit typos.
Input formats
Anything readable is accepted. DE811907980, DE 811 907 980, de-811.907.980 and DE811907980 are the same number: spaces, dots and hyphens are stripped and the country code is uppercased.
Greece is the classic trap — the ISO country code is GR but the VAT prefix is EL, and VIES rejects GR outright with INVALID_INPUT. Both are accepted here and sent as EL.
Great Britain is no longer in VIES. A GB number comes back with status: NOT_IN_VIES and a note pointing at HMRC, rather than the bare INVALID_INPUT that VIES itself returns. Northern Ireland is still served, under the prefix XI.
Speed and throughput
VIES enforces a concurrency limit per member state and rejects excess traffic with MS_MAX_CONCURRENT_REQ. This is easy to trigger: during development, six parallel requests were enough.
The Actor therefore uses a semaphore of 2 by default and spaces requests roughly 0.6 seconds apart. Measured on a real run: 28 numbers across 18 countries, 26 VIES calls, 32.0 seconds — about 1.4 seconds per number that reached the network. Expect roughly 2 000 to 2 500 numbers an hour on a clean list, and materially less when one of the national databases is having a slow day. Raising concurrency above 2 or 3 mostly buys retries rather than throughput, because the per-country limit is the binding constraint.
Format-rejected numbers cost nothing and take no time, so a dirty list runs faster than a clean one of the same length.
Who uses this
Finance and accounts-payable teams validating supplier VAT numbers before a payment run. E-commerce and SaaS billing systems deciding whether to zero-rate a B2B sale under the reverse charge. Marketplaces onboarding EU sellers. Auditors and tax advisers who need the consultation number on file. CRM and data teams cleaning a customer list that has accumulated typos and dissolved companies for years.
Scope and limits
VIES answers "registered for intra-EU trade", not "exists". A company can be VAT-registered domestically and still return invalid here, because it is not registered for intra-Community transactions. Germany in particular issues a separate USt-IdNr. for that purpose, which is the number VIES knows.
The name and address are the register's, not the company's letterhead. They are frequently abbreviated, in the local script and occasionally out of date — SE556016068001 returns Telefonaktiebolaget LM Ericsson, not Ericsson. Match on the VAT number, not on the name.
A valid answer is a snapshot. Registrations are withdrawn. The requestDate on each row is the moment the answer was given, and it is what a tax authority will care about.
VIES is a relay, not a database. It forwards each query to the member state that issued the number. Availability, response time and how much detail comes back are decided by that national administration, not by the Commission.
Source and licence
VIES — the VAT Information Exchange System of the European Commission's Directorate-General for Taxation and Customs Union, through ec.europa.eu/taxation_customs/vies/rest-api. Free, keyless, no registration. Queried live on every run; nothing is cached.
Frequently asked
Why is companyName empty for a valid German or Spanish number?
Because those two member states do not release trader details through VIES at all. The row says so in explanation and sets detailsDisclosed: false. For Spain you can still verify the name you hold with the trader match; for Germany you cannot.
Why did all my match flags come back empty?
Either the member state does not run the comparison — most do not, and the row says which — or requesterVatNumber was missing, in which case VIES ignores the trader fields without complaining.
A number I know is good came back invalid. Why?
Most often because the company is registered domestically but not for intra-EU trade, which is a different register. Check requestDate and status: if status is VALID or INVALID the national database genuinely answered, and the answer is the member state's, not the Actor's.
Can I check a UK VAT number?
Not through VIES. Great Britain left the EU VAT area on 31 December 2020. Northern Ireland numbers work under the prefix XI.
How many numbers can I put in one run? As many as you like. The constraint is VIES throughput, not the Actor — budget about half an hour for a thousand.
Does a format-rejected number cost a VIES call? No. It never leaves the machine.