EU VAT Number Validator (VIES) - Bulk Check, No Login avatar

EU VAT Number Validator (VIES) - Bulk Check, No Login

Pricing

from $1.60 / 1,000 vat number checkeds

Go to Apify Store
EU VAT Number Validator (VIES) - Bulk Check, No Login

EU VAT Number Validator (VIES) - Bulk Check, No Login

Bulk-validate EU VAT numbers against the official EU VIES service: valid or invalid, company name and address, consultation number. Member-state outages are reported as unavailable, never as invalid.

Pricing

from $1.60 / 1,000 vat number checkeds

Rating

0.0

(0)

Developer

Cliqto Media

Cliqto Media

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 days ago

Last modified

Share

Check a list of EU VAT numbers against the European Commission's VIES service and get one row per number: valid or invalid, the registered company name and address when the country shares them, and an honest status when a country's database is down. No login, no API key.

Paste up to 1,000 VAT numbers with their country prefix (for example IE6388047V) and click Start. A run of 6 numbers takes a few seconds and costs about $0.01.

EU VAT Number Validator: a VAT list goes to VIES and comes back as valid, invalid or format_error per number, with company names

Table of contents

What it does

VIES (VAT Information Exchange System) is the European Commission service that asks each EU country's tax database whether a VAT number is registered for cross-border trade. This Actor sends your numbers to the public VIES REST API one by one and saves the answer for each number in a dataset.

Before a number goes to VIES, the Actor cleans it (spaces, dots and dashes are removed, GR becomes EL) and checks the country's number format. Numbers with a wrong format are reported as format_error and are never sent.

The main difference from a simple VIES call: a VIES "no answer" is not turned into "invalid". When a country is busy or down (VIES codes MS_MAX_CONCURRENT_REQ and MS_UNAVAILABLE), the Actor waits and asks again. If the country still does not answer, the row gets status: "service_unavailable" and valid: null, not valid: false.

Good fit

  • Check customer VAT numbers before you send an invoice without VAT (EU reverse charge).
  • Clean a CRM or lead list: mark invalid numbers and fill in the registered company name.
  • Re-check a supplier list and keep the VIES consultation number as proof of the check.

Not a fit / limits

  • UK (GB) numbers are not checked. They left VIES in 2021, and the UK HMRC API needs registered API credentials. They get status: "unsupported_country". Northern Ireland traders (XI prefix) are checked through VIES.
  • Non-EU numbers (Norway, Switzerland, US and others) get unsupported_country.
  • You cannot search by company name. VIES only checks a number.
  • Some countries (for example Germany and Spain) do not share the name and address. Then name and address are null even when the number is valid.
  • This is a one-time check of a list. There is no monitoring mode and no history.

Quick start

  1. Open the Input tab.
  2. Add your numbers to VAT numbers (vatNumbers), one per line, with the two-letter country prefix. The form is prefilled with 5 public company numbers and one number with a wrong format (DE12).
  3. Optional: add your own EU VAT number in requesterVat to get a consultation number for each valid check.
  4. Click Start.
  5. Open the Output tab. The Results view shows status, valid, name and address for each number.

Expected result for the prefill: 5 rows with status: "valid" (with company names, except the German number: Germany does not share names in VIES), and 1 row with status: "format_error" for DE12.

Input

Input fields

FieldPlain nameTypeRequiredDefault / prefillAllowed valuesEffectExampleRecommendation
vatNumbersVAT numbersarray of stringsyesno default; prefill of 6 numbers1–1,000 items, each with an EU country prefixNumbers to check["IE6388047V", "de 143.454.214"]Keep the country prefix. Spaces, dots and dashes are fine.
requesterVatYour own EU VAT numberstringnoemptyone EU VAT number with prefixVIES returns a consultationNumber for each valid check"IE6388047V"Use it when you need proof that you checked a customer.
retryUnavailableRetry unavailable countriesbooleannotruetrue / falseWhen a country is down, retry it up to 3 more times (waits of 15, 30 and 60 seconds)trueTurn off only if you need the fastest possible answer.

How the input is read:

  • Each number is cleaned: upper case, spaces, dots, dashes and similar marks removed, full-width digits changed to normal digits. GR is changed to EL (the VIES code for Greece).
  • Duplicates (after cleaning) are checked once. The result row shows how many extra copies there were in duplicateInputs.
  • Empty input or more than 1,000 numbers: the run fails at once with a clear message and nothing is charged except the start fee.
  • An invalid requesterVat format fails the run with a clear message. If VIES rejects a well-formed requesterVat, the Actor logs a warning and checks your numbers without it.

Interacting settings

WhenInput AInput BEffective behaviorCost/result effect
A country is downvatNumbersretryUnavailable: trueNumbers of that country are retried in up to 3 rounds (about 2 minutes extra)Longer run; service_unavailable rows have no check fee
A country is downvatNumbersretryUnavailable: falseNo retry rounds: numbers of that country are reported as service_unavailable right away (short busy retries of 2 and 5 seconds still happen)Faster run
You need proofvatNumbersrequesterVatEach valid row gets a consultationNumber from VIESSame price

Input example

{
"vatNumbers": ["IE6388047V", "LU20260743", "NL810433941B01", "DE143454214", "ATU33803701", "DE12"],
"retryUnavailable": true
}

Expected behavior: 5 numbers are sent to VIES, DE12 is stopped by the format check. Expected output: 6 rows; 5 valid with names where the country shares them, 1 format_error. Cost: about $0.0103 (5 checks + 6 rows + start fee, see Pricing).

Output

Each unique input number gives one dataset row. A run summary is saved in the key-value store as RUN_SUMMARY.

Output example

One valid row and one format_error row from a real run:

[
{
"input": "IE6388047V",
"countryCode": "IE",
"vatNumber": "6388047V",
"fullVatNumber": "IE6388047V",
"status": "valid",
"valid": true,
"name": "GOOGLE IRELAND LIMITED",
"address": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4",
"requestDate": "2026-10-13T16:13:43.268Z",
"consultationNumber": null,
"errorCode": null,
"errorMessage": null,
"attempts": 1,
"duplicateInputs": 0,
"source": "EU VIES (European Commission)",
"sourceUrl": "https://ec.europa.eu/taxation_customs/vies/",
"checkedAt": "2026-10-13T16:13:43.314Z"
},
{
"input": "DE12",
"countryCode": "DE",
"vatNumber": "12",
"fullVatNumber": "DE12",
"status": "format_error",
"valid": null,
"name": null,
"address": null,
"requestDate": null,
"consultationNumber": null,
"errorCode": "FORMAT_ERROR",
"errorMessage": "Does not match the DE VAT number format.",
"attempts": 0,
"duplicateInputs": 0,
"source": "EU VIES (European Commission)",
"sourceUrl": "https://ec.europa.eu/taxation_customs/vies/",
"checkedAt": "2026-10-13T16:13:42.494Z"
}
]

consultationNumber is null here because the run had no requesterVat.

Output fields

FieldMeaningTypeCan be empty?Example / enum
inputThe number exactly as you typed itstringnode 143.454.214
countryCodeVIES country code (EL = Greece, XI = Northern Ireland)stringnull when no prefix was foundDE
vatNumberNumber without prefix and separatorsstringnull when no prefix was found143454214
fullVatNumberCleaned number with prefixstringnull when no prefix was foundDE143454214
statusResult of the checkstringnovalid, invalid, service_unavailable, format_error, unsupported_country, not_checked, error
validVIES verdictbooleannull when VIES gave no verdicttrue
nameRegistered trader namestringnull when the country does not share itGOOGLE IRELAND LIMITED
addressRegistered address on one linestringnull when not shared3RD FLOOR, GORDON HOUSE, …
requestDateTime of the VIES answerstring (ISO 8601)null when VIES was not asked or did not answer2026-10-13T16:13:43.268Z
consultationNumberOfficial VIES consultation numberstringnull without requesterVatWAPI…
errorCodeWhy there is no verdictstringnull for valid / invalidMS_UNAVAILABLE, FORMAT_ERROR, UNSUPPORTED_COUNTRY, CHARGE_LIMIT
errorMessageThe same in plain wordsstringnull for valid / invalidDoes not match the DE VAT number format.
attemptsRequests sent to VIES for this numberintegerno1
duplicateInputsExtra copies of this number in your inputintegerno0
source / sourceUrlWhere the answer came fromstringnoEU VIES (European Commission)
checkedAtWhen this row was madestring (ISO 8601)no2026-10-13T16:13:43.314Z

What each status means:

statusvalidMeaningWhat to do
validtrueVIES says the number is active for cross-border tradeUse it
invalidfalseVIES says the number is not registered or not activeAsk the customer to check the number
service_unavailablenullThe country's database did not answer, even after retries. This is not invalid.Run these numbers again later
format_errornullThe number does not match the country's format; it was not sent to VIESFix the number
unsupported_countrynullPrefix is not an EU VIES country (for example GB, NO, CH)Check it with that country's own service
not_checkednullThe run stopped before this number (time limit, your charge limit, or VIES stopped answering)Run these numbers again
errornullVIES returned an unexpected error for this numberRun it again later

Output views and run summary

SituationWhere to lookWhat you see
Normal runDataset view ResultsAll rows with status, name, address, consultation number
Status and error codesDataset view Status and errors (all rows; sort or filter by status when exporting)Input, status, error code, note, attempts
Every input has a wrong formatDatasetOnly format_error rows; run is SUCCEEDED
A country was downDataset + RUN_SUMMARYservice_unavailable rows; unavailableCountries lists the countries; run is SUCCEEDED
Run stopped earlyRUN_SUMMARYstatus: "PARTIAL" with reason: CHARGE_LIMIT or DEADLINE_REACHED (remaining rows are not_checked), VIES_NOT_RESPONDING (VIES gave no verdict for 2 minutes; remaining rows are service_unavailable or not_checked), MEMBER_STATE_UNAVAILABLE (some rows are service_unavailable)
Bad input or VIES fails many times in a rowRun status + RUN_SUMMARYRun FAILED with a clear message; rows saved before the stop stay in the dataset

RUN_SUMMARY contains status, reason, message, counts per status, charged, duplicatesMerged, unavailableCountries, request statistics and timing.

Pricing and limits

Pricing unit

This Actor uses pay-per-event pricing. You pay for:

EventWhenPrice
Actor startOnce per run (at the default 256 MB memory)$0.0007
VAT checkEach number that gets a VIES verdict (valid or invalid)$0.0019 (Free plan), $0.0018 (Bronze), $0.0017 (Silver), $0.0016 (Gold and higher)
Result rowEach row saved to the dataset, for any status$0.00002

Numbers with service_unavailable, format_error, unsupported_country, not_checked or error have no VAT check fee. They only cost the $0.00002 row fee. Duplicates are checked and charged once.

Platform usage (compute, storage) is included in the event prices.

Cost examples (Free plan prices)

ScenarioInputEventsTotal
Prefill6 numbers, 5 verdicts1 start + 5 checks + 6 rows$0.0103
Small10 numbers, all with verdicts1 start + 10 checks + 10 rows$0.0199
Normal100 numbers, all with verdicts1 start + 100 checks + 100 rows$0.1927
Maximum1,000 numbers, all with verdicts1 start + 1,000 checks + 1,000 rows$1.9207
Only wrong formats1,000 numbers, all format_error1 start + 1,000 rows$0.0207

Your maximum total charge for a run (set in the run options) is respected. When the next check would go over it, the Actor stops sending numbers, marks the rest as not_checked (no check fee) and ends the run as SUCCEEDED with reason: "CHARGE_LIMIT".

Limits and speed

  • Up to 1,000 numbers per run. Split bigger lists into several runs.
  • Speed: about 100 numbers per minute when the list has many countries (1,000 numbers from 12 countries took about 4.5 minutes in our test). The Actor sends only one request at a time to each country, because VIES limits parallel requests per country. So a list from one country is slower: 194 German numbers took about 1.5 minutes in our test. A very long list from one slow country may not finish within the 900-second timeout; the rest is then marked not_checked (no check fee) — split such lists or raise the timeout.
  • Default run options: 256 MB memory, 900-second timeout. More memory does not make the run faster.
  • If the run time limit is close, the Actor stops sending numbers 20 seconds before it and marks the rest as not_checked.
  • If VIES gives no verdict at all for 2 minutes (only "busy" or "unavailable" answers), the Actor stops early with reason: "VIES_NOT_RESPONDING" instead of waiting until the timeout. Run the list again later.

Use cases

Buyer jobInputKey fieldsNext step
Check a customer before a reverse-charge invoicevatNumbers + requesterVatstatus, valid, consultationNumber, requestDateSave the consultation number with the invoice
Clean a CRM or lead listvatNumbers (export from CRM)status, name, addressExport CSV and update the CRM
Re-check suppliers every monthvatNumbers in a saved taskstatus, errorCodeSchedule the task; follow up on invalid rows

API, export and integrations

  • API: start a run with POST https://api.apify.com/v2/acts/cliqtomedia~vat-number-validator/runs and the input JSON above. Read rows from the run's default dataset.
  • Export: download the dataset as JSON, CSV, Excel or XML from the Output tab or the dataset API.
  • Scheduling: save your input as a task and add an Apify schedule to re-check the same list.
  • Webhooks / no-code: use an Apify integration (Make, Zapier, webhooks) to send the rows on when the run finishes. Filter on status in the next step.

Use with AI agents (MCP)

  • MCP server URL with only this Actor: https://mcp.apify.com?tools=cliqtomedia/vat-number-validator
  • Smallest useful input: {"vatNumbers": ["IE6388047V"]}
  • Key output fields: fullVatNumber (cleaned number), status (see the status table), valid (true / false / null), name and address (null when the country does not share them).
  • The 6-number prefill finished in 2–8 seconds in our tests and costs about $0.01; 100 numbers take about 1 minute and cost about $0.19. Maximum 1,000 numbers per run.
  • valid: null never means invalid. Read status and errorMessage for the reason.

Troubleshooting

Many numbers show service_unavailable

Symptom: rows from one country have status: "service_unavailable" and errorCode: "MS_UNAVAILABLE" or "MS_MAX_CONCURRENT_REQ". Likely reason: that country's tax database was down or busy. This happens on the VIES side, often for a short time. Check: RUN_SUMMARY → unavailableCountries. The VIES website shows which countries are available now. Action: run only these numbers again later. Keep retryUnavailable: true.

A number I know is real shows format_error

Symptom: errorMessage says the number does not match the country's format. Likely reason: a missing or wrong country prefix, a missing digit, or extra text in the cell (for example a company name or HTML). Check: compare input with the country's VAT format; the prefix must be the VIES code (EL or GR for Greece, XI for Northern Ireland). Action: fix the number and run it again.

A valid number has no name or address

Symptom: status: "valid" but name and address are null. Likely reason: some countries (for example Germany and Spain) do not share these details through VIES. Action: nothing is wrong. The verdict is still valid.

The run ended with some not_checked rows

Symptom: RUN_SUMMARY.status is PARTIAL and some rows are not_checked. Likely reason: your maximum total charge or the run timeout was reached. Action: raise the maximum charge or the timeout, or run the not_checked numbers in a new run.

The run failed at once

Symptom: run status FAILED with "Invalid input". Likely reason: vatNumbers is empty, has more than 1,000 items, or requesterVat has a wrong format. Action: fix the input as the message says.

FAQ

Do I need a login or an API key?

No. VIES is a public service of the European Commission. You only need an Apify account to run the Actor.

Can I check UK VAT numbers?

Not GB numbers: they left VIES in 2021, and the UK HMRC check needs registered API credentials. Northern Ireland numbers with the XI prefix are checked through VIES.

Is a service_unavailable number invalid?

No. It means the country did not answer. Run it again later. You do not pay the check fee for it.

How fresh is the data?

Each check is a live VIES request at run time. requestDate shows the time of the VIES answer. The Actor does not cache results.

When you add your own VAT number in requesterVat, VIES returns a consultation number. It is the VIES record that you checked this number on that date. Whether it is enough proof for your tax office is a question for your tax adviser.

Support

For bugs, questions or feature requests, open an issue in the Issues tab of this Actor. Include the run ID and the numbers that gave an unexpected result. Do not send API tokens or private customer data.