VIES VAT Validator – Bulk EU VAT Number Check
Pricing
from $4.00 / 1,000 vat number validateds
VIES VAT Validator – Bulk EU VAT Number Check
Bulk VAT number validation through VIES for invoicing software, accountants and B2B webshops. Tells valid, invalid and "member state down" apart (never a false invalid), returns the registered name and the consultation number for reverse charge, and finds VAT numbers by company name.
Pricing
from $4.00 / 1,000 vat number validateds
Rating
0.0
(0)
Developer
Leyten Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
What does VIES VAT Validator do?
Bulk VAT number validation through VIES for invoicing software, accountants and B2B webshops: per EU VAT number (btw-nummer) it tells you whether the number is valid, invalid, or could not be checked because the member state's service did not answer. It returns the registered name and address where the member state discloses them, the VIES consultation number you need as evidence for reverse charge, and it can find the VAT number of a company by name.
The problem: "invalid" and "the service was down" look the same
VIES is not one database. It relays every check to the tax administration of the member state, and those services fail independently:
- Germany takes its VIES service offline every night (measured in August 2026: roughly 21:40 to 01:00 UTC, every night, weekends included).
- Ireland was unavailable every Monday night, and Latvia degrades during the day.
- Member states answer
MS_MAX_CONCURRENT_REQwhen they are busy. On 15 September 2026 France answered it to every check for minutes, while the VIES status endpoint listed France as "Available". - The endpoint most tools copy from the VIES website returns
"isValid": falsetogether with an error code when the check did not happen at all.
A validator that turns any of these into "invalid" breaks the accounting integration behind it: a customer with a perfectly valid VAT number is suddenly charged VAT, blocked at checkout, or flagged in your ICP/EC Sales List review. This Actor treats that distinction as the product.
How outages are handled
Per member state, the Actor keeps a gate with its own concurrency (at most 3 checks at a time), backoff and failure clock. It only gives up on a member state after it kept failing for Wait for an unavailable member state (default 5 minutes); from then on its remaining numbers in the run are reported as unavailable immediately. When VIES itself reports the member state as unavailable, it checks once a minute instead of hammering a service that is down.
| VIES error | Meaning | What the Actor does |
|---|---|---|
MS_UNAVAILABLE | The member state's service is not replying | Retried with growing waits (5 s up to 1 min, calmer while VIES reports the state as down) until the maximum wait, then unavailable |
TIMEOUT | The member state did not reply in time | Retried with growing waits (5 s up to 1 min, calmer while VIES reports the state as down) until the maximum wait, then unavailable |
MS_MAX_CONCURRENT_REQ | Too many requests to this member state right now | One request at a time for that member state, retried from 1 s up to 20 s, then unavailable |
MS_MAX_CONCURRENT_REQ_TIME | Too many requests to this member state in a period | One request at a time for that member state, retried from 1 s up to 20 s, then unavailable |
GLOBAL_MAX_CONCURRENT_REQ | Too many requests to VIES right now | All checks pause and retry from 2 s up to 30 s, then unavailable |
GLOBAL_MAX_CONCURRENT_REQ_TIME | Too many requests to VIES in a period | All checks pause and retry from 2 s up to 30 s, then unavailable |
SERVICE_UNAVAILABLE | VIES itself (network or application) is failing | All checks pause and retry from 5 s up to 1 min, then unavailable |
VAT_BLOCKED | VIES temporarily refuses checks of this number | unavailable for this number; retried in the next run |
IP_BLOCKED | VIES refuses requests from this IP address | All remaining numbers unavailable; retried in the next run |
INVALID_REQUESTER_INFO | Your own VAT number was rejected | The run stops before anything is charged |
INVALID_INPUT | Country code or number format rejected | invalid-format, not charged |
Unknown error codes are treated as an outage, never as an answer. A run in which VIES only answers in an unexpected way (for example after an API change) fails with a clear message instead of reporting every number as unavailable.
Next runs. In a saved task (or a run with a State key), unavailable numbers and company names are checked again in the following runs for up to Keep retrying for days (default 7) after the first failed check, and delivered as changed with carriedOver: true once VIES answers. A number that is still unavailable, or that the run's check limit, your spending limit or the run's memory left unchecked, does not produce a new record and keeps waiting.
Find a VAT number by company name
VIES cannot search by name. For names in Company names ("Coolblue; NL"), the Actor finds candidates and lets VIES decide:
- Candidates come from the Peppol Directory in every country (company identifiers such as a Belgian enterprise number, French SIREN, Danish CVR or a VAT number determine the VAT number), and for France also from the French government's company register (recherche-entreprises).
- Similarity. Names are compared without legal forms, punctuation, case or accents (
Coolblue B.V.equalsCOOLBLUE BV: one record, and another of these spellings in a later run is no change), tolerating typos. The best candidates are validated in VIES; Spain also compares the name inside VIES. - Result. The best valid candidate above Minimum name similarity becomes the result, with
match.score,match.sourceand up to fivematch.alternatives. When two valid VAT numbers match equally well (Coolblue B.V.andCoolblue GmbHfor "Coolblue"),match.ambiguousistrueand the reason names both.
Coverage is honest, not complete: for France it covers all active companies; elsewhere it covers companies registered on Peppol, which includes most Belgian businesses since Belgium made Peppol e-invoicing mandatory in January 2026, but only a minority of Dutch or German ones. French sole traders are skipped in the name search (see the GDPR question below); validate their VAT number directly.
Features
- Bulk EU VAT number check against VIES, thousands of numbers per run, with one record per distinct number
invalidonly when VIES answered. Every error, time-out and throttle becomesunavailable, with the VIES error code, the attempts made and, for known maintenance windows, when to retry- Retries per member state. A German outage does not slow down Dutch numbers; each member state gets its own concurrency, backoff and maximum wait
- Unavailable numbers come back. In a saved task, numbers VIES could not check are checked again in the next runs until VIES answers (for up to a week by default), even if your next batch no longer contains them
- A second opinion. An "invalid" answer from a member state that failed during the same run is checked once more before it is reported
- VIES consultation number per check when you provide your own VAT number: proof for reverse charge invoices
- VAT number lookup by company name through the Peppol Directory and the French company register, confirmed in VIES
- Never charged for downtime. Only definite answers cost money
- Change detection per number across runs (
added,unchanged,changed) with a webhook, so a customer who is no longer valid shows up the day it happens - Runs through the Apify API, on a schedule, or from Make, Zapier and n8n
Use cases
ERP and invoicing software: validate customer VAT numbers in bulk
Call the Actor from your backend when customers are created or imported, or nightly for the whole customer file. Branch on status, not on valid alone, and never store a record with fromEarlierRun: true as a new check:
// npm install apify-clientimport { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });// customers: [{ id: 'C-1001', vatNumber: 'NL810433941B01' }, ...]// One run checks as many numbers as its memory holds (15,000 with the default 1 GB, 35,000 with 2 GB, 50,000 with 4 GB).// A larger file at 1 GB leaves the same customers unchecked every night, so pick the memory by the size of the file.const memory = customers.length <= 15_000 ? 1024 : customers.length <= 35_000 ? 2048 : 4096;const run = await client.actor('lwsdjfls/vies-vat-validator').call({vatNumbers: customers.map((customer) => customer.vatNumber),requesterVatNumber: 'NL123456789B01', // your own VAT number: VIES returns consultation numbersmaxWaitMinutes: 10,maxChecksPerRun: customers.length, // the default of 10,000 would stop a larger file},{ memory },);// Runs without a task or state key share one state and must not overlap: a run started while another is still// working fails before it checks or charges anything. Queue the calls, or start the run again later.if (run.status !== 'SUCCEEDED') throw new Error(`VAT check run ${run.id} ended with status ${run.status}`);// A run that its check limit, your spending limit or its memory stopped still succeeds: its RUN_SUMMARY says "partial",// and its log says what was left out and what makes room. Watch for it, or the customers left out wait every night.const summary = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('RUN_SUMMARY');if (summary?.value.outcome === 'partial') console.warn(`VAT check run ${run.id} did not check every number; see its log`);const { items } = await client.dataset(run.defaultDatasetId).listItems({ clean: true });// One record per distinct number: spellings of one number ("NL 8104.33.941.B01", "nl810433941b01") are checked// once, so look records up by the number as the Actor normalizes it.const normalize = (vatNumber) => vatNumber.replace(/[\s.\-/,_:]/g, '').toUpperCase().replace(/^GR/, 'EL').replace(/^BE(\d{9})$/, 'BE0$1');const byNumber = new Map(items.map(({ payload }) => [payload.vatNumber ?? normalize(payload.input), payload]));for (const customer of customers) {const result = byNumber.get(normalize(customer.vatNumber));// Not checked in this run (your spending limit was reached, or the run's memory was full): keep the evidence you// have and check again later. A record with fromEarlierRun repeats an earlier result; it is not a new check.if (!result || result.status === 'skipped' || result.fromEarlierRun) {await scheduleRecheck(customer.id, null);continue;}switch (result.status) {case 'valid': // reverse charge allowed; keep the evidence with the customerawait saveVatCheck(customer.id, { reverseCharge: true, name: result.name, consultationNumber: result.consultationNumber, checkedAt: result.checkedAt });break;case 'invalid':case 'invalid-format': // charge VAT and ask the customer for a correct numberawait saveVatCheck(customer.id, { reverseCharge: false, reason: result.statusReason });break;case 'unavailable': // no answer: keep the last known status and check again laterawait scheduleRecheck(customer.id, result.unavailable.retryAfter);break;default: // outside-vies (GB, CH, ...): handle outside the EU flowawait flagForReview(customer.id, result.statusReason);}}
1,000 customers cost $4.00 when VIES answers all of them; numbers VIES could not check cost nothing.
Accountants: monthly check of intra-EU customers before the ICP/EC Sales List
Save a task with the customer VAT numbers of your client, schedule it monthly (or before each filing), and add your client's VAT number for consultation numbers. Each run lists every number; the changeType column shows which customers changed since last month, and a webhook can alert you when a customer is no longer valid. A record with fromEarlierRun: true was not checked again because the check limit or your spending limit was reached: its unchanged says nothing about this month.
E-commerce with EU B2B sales
Validate the VAT numbers entered at checkout in batches (for example every hour) instead of in the checkout itself, so a German night-time outage never blocks an order: accept the order, and invoice with reverse charge once the number is valid.
Tax teams: reverse charge validation with proof
For an intra-EU B2B sale you apply the 0% rate or reverse charge (verlegde btw, Steuerschuldnerschaft des Leistungsempfängers, autoliquidation) only for a customer with a valid VAT number:
- Goods. Since the 2020 Quick Fixes, the customer's VAT number being valid in VIES is a substantive condition for the exemption of an intra-Community supply (Article 138 of the VAT Directive), and the number must appear in your recapitulative statement.
- Services. You may treat the customer as a taxable person when it gave you its VAT number and you verified it (Article 18 of Implementing Regulation 282/2011).
Checking is half of it; being able to show you checked is the other half. Put your own VAT number in Your VAT number and VIES issues a consultation number for every check: a reference, stored by VIES, that you verified that customer's number on that date. The Actor returns it with the check timestamp, so you can store it with the invoice or customer record.
How to use it
- Paste your VAT numbers into VAT numbers, one per line, and press Start. A country prefix is all that is needed; spaces, dots and dashes are ignored, and a number without a prefix uses Default country. Every number comes back as its own record.
- Fill in Your VAT number if you need evidence for reverse charge. VIES then issues a consultation number for each check and it lands in the record next to the answer, which is what an auditor asks for.
- Save the run as a task once the input is right, then call that task from your invoicing system. A task keeps its own state, so later runs report only what changed, and numbers VIES could not reach are checked again for you over the following week.
Three dataset views tell you where to look. validation holds the answer per number, unavailable lists the numbers a member state never answered for, and companyMatches shows which VAT number a company name resolved to and how confident that match is. Every run ends with a status message counting all three, so a quiet day never looks like a broken integration. Read one record in the Output tab before you wire anything up.
Two things this Actor deliberately does not do. It never turns an outage into invalid, so a number you get back as invalid really was rejected by the member state. And it does not check that a name belongs to a number: VIES returns the registered name where the member state discloses it, and comparing that with your own customer record stays your decision.
curl "https://api.apify.com/v2/acts/lwsdjfls~vies-vat-validator/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H 'Content-Type: application/json' \-d '{"vatNumbers":["NL810433941B01","BE0403170701"],"requesterVatNumber":"NL123456789B01"}'
Input
| Field | What it does | Example |
|---|---|---|
vatNumbers | VAT numbers, one per line, with country prefix. Spaces, dots and dashes are fine; GR is read as EL. Numbers without a prefix use the default country. | ["NL810433941B01", "BE 0403.170.701"] |
companyNames | Names as "Company name; country code". Candidates come from the Peppol Directory and, for France, the French company register; each is confirmed in VIES. | ["Coolblue; NL", "Danone; FR"] |
defaultCountry | Country for VAT numbers without prefix and names without country code. | NL |
requesterVatNumber | Your own EU VAT number. VIES then issues a consultation number per check as proof of verification. | NL123456789B01 |
maxWaitMinutes | How long a member state may keep failing before its remaining numbers are reported as unavailable. Waiting is free. | 5 |
retryUnavailableInLaterRuns | In saved tasks: numbers VIES could not check are checked again in the following runs and delivered once VIES answers. | true |
retryForDays | How many days an unavailable number is retried after the first failed check. | 7 |
minMatchScore | How similar a registered name must be to the name you gave (legal forms, punctuation and case ignored; 100 = identical). | 80 |
maxCandidatesPerCompany | How many similar companies are validated in VIES per name. | 3 |
maxChecksPerRun | Caps the charged validations and matches in one run. Inputs above it are not checked: a number with an earlier result keeps it (with fromEarlierRun: true), others are listed as skipped. | 10000 |
maxConcurrency | Checks running at the same time (at most 3 per member state). | 6 |
useTestService | Free rehearsal against the official VIES test service (see below). | false |
webhookUrl | Receives a POST with the new and changed results after each run; stored encrypted. | https://hooks.example.com/vat-checks |
stateKey | Keeps results and retries separate for runs outside a saved task. Runs without a task or state key share one state. | customer-file-2026 |
proxyConfiguration | Not needed normally; only when VIES answers IP_BLOCKED. | { "useApifyProxy": false } |
{"vatNumbers": ["NL810433941B01", "BE 0403.170.701", "DE143454214", "FR27552032534"],"companyNames": ["Coolblue; NL", "Danone; FR"],"requesterVatNumber": "NL123456789B01","maxWaitMinutes": 5,"webhookUrl": "https://hooks.example.com/vat-checks"}
Batch size and memory. One run checks up to 15,000 numbers and company names with the default 1 GB of memory, 35,000 with 2 GB and 55,000 (the input maximum) with 4 GB; 5,000 with 512 MB. Results kept from earlier runs of the same task or state key take memory too: every 4 that are not in the run take the place of one number. What does not fit is not checked, not charged and not delivered: the run ends as partial in its run summary, the log says what was left out and what would make room for it, and numbers VIES could not check in earlier runs wait for a later run. A run in which nothing fits checks and charges nothing. When results whose number was last checked more than 35 days ago take the room, it deletes them and ends without records, so that the next run has room (numbers and company names of its input among them then arrive as added again, not compared with their deleted results); otherwise it fails, and its message says what makes room and from when runs make room again on their own.
A state that keeps getting new numbers fills up. A result stays until a run of its task or state key starts more than 35 days after the number was last checked. A task, or the one state of all runs without a task or state key, that checks new numbers all the time (hourly checkout batches, an API call for every new customer) therefore holds about 60,000 distinct numbers per 35 days with 1 GB of memory, 20,000 with 512 MB, 140,000 with 2 GB and 270,000 with 4 GB. The fuller the state, the fewer new numbers a run checks; once it is full, runs fail, and a failed run deletes nothing, so runs keep failing until you act or until enough results are more than 35 days old (the failure message gives the date): start these runs with more memory, give them a state key that you change regularly (checkout-2026-09, then checkout-2026-10), or delete the results of the full state as the GDPR question below describes. A new state key starts over: every number arrives as added again, numbers VIES could not check are retried only under their old key, and the results of the old key stay until you delete them. Delete the records of the old key (keys starting with checkout-2026-09.) once you no longer need them.
Runs that overlap. Every task and every state key has its own state, and all runs without a task or state key share one. Two runs with the same state must not work at the same time: a run that starts while another one with its state is still working fails at once, before it checks or charges anything. Queue calls that can overlap, start a failed run again later, or give each integration its own state key (its unavailable numbers are then retried in its later runs).
Testing your integration. Set Use the VIES test service to rehearse every situation for free with the official VIES test numbers: 100 valid, 200 invalid, 300 SERVICE_UNAVAILABLE, 301 MS_UNAVAILABLE, 302 TIMEOUT, 400 VAT_BLOCKED, 600 MS_MAX_CONCURRENT_REQ (with a default country).
Supported member states
All 27 EU member states and Northern Ireland (XI, for trade in goods):
| Prefix | Member state | Example |
|---|---|---|
AT | Austria | ATU12345678 |
BE | Belgium | BE0403170701 |
BG | Bulgaria | BG123456789 |
CY | Cyprus | CY12345678X |
CZ | Czechia | CZ12345678 |
DE | Germany | DE123456789 |
DK | Denmark | DK12345678 |
EE | Estonia | EE123456789 |
EL | Greece | EL123456789 |
ES | Spain | ESB12345678 |
FI | Finland | FI12345678 |
FR | France | FR27552032534 |
HR | Croatia | HR12345678901 |
HU | Hungary | HU12345678 |
IE | Ireland | IE9700053D |
IT | Italy | IT12345678901 |
LT | Lithuania | LT123456789 |
LU | Luxembourg | LU12345678 |
LV | Latvia | LV12345678901 |
MT | Malta | MT12345678 |
NL | Netherlands | NL810433941B01 |
PL | Poland | PL1234567890 |
PT | Portugal | PT123456789 |
RO | Romania | RO12345678 |
SE | Sweden | SE123456789001 |
SI | Slovenia | SI12345678 |
SK | Slovakia | SK1234567890 |
XI | Northern Ireland | XI123456789 |
Formats are checked structurally (length and characters). Check digits are deliberately left to VIES: a local check-digit rule that is wrong for one class of numbers would report real customers as invalid (Dutch VAT numbers issued to sole traders since 2020 no longer pass the old check-digit test, for example).
Numbers from these countries are reported as outside-vies:
GB: Great Britain left VIES in 2021 (HMRC checks GB numbers; businesses in Northern Ireland trading goods use XI).CH: Switzerland is not in VIES (the Swiss UID register checks CHE numbers).NO: Norway is not in VIES (the Brønnøysund register checks Norwegian numbers).IS: Iceland is not in VIES.LI: Liechtenstein is not in VIES.
Output
One record per distinct VAT number or company name that fits in the run's memory (see Batch size and memory under Input):
status:valid,invalid,invalid-format,outside-vies,unavailable,no-match(company names) orskipped(run limit reached)valid:trueorfalseonly when there is an answer;nullwhen the number was not checked and has no earlier answerfromEarlierRun:truewhen the check limit or your spending limit stopped this run's check of a number with an earlier result.status,valid,name,address,consultationNumberandcheckedAtare then that earlier result, not a new verification. A number that was onlyskippedbefore has no earlier result: it isskippedagain, withfromEarlierRun: falsevatNumber(normalized, with prefix),vatNumberWithoutPrefix,countryCode(VIES code, so Greece isEL),countryNamename,address,addressLines: as registered, where the member state discloses them;detailsWithheld: truewhen a valid number comes without them (Germany, for example)consultationNumber,requesterVatNumber,checkedAt: your evidence that the number was valid on that datestatusReason: one sentence explaining the result, for your usersunavailable:code(VIES error),viesStatus,attempts,waitedSeconds,retryAfterpendingSince,carriedOver,doubleCheckedchangeTypeper record:added(first check),unchanged(also for a record withfromEarlierRun: true, which was not checked again), orchangedwith a summary such asNL123456789B01 (ACME B.V.): no longer valid (valid on 2026-09-01)
| Status | Meaning | Charged |
|---|---|---|
valid | VIES confirms the number is valid for intra-EU transactions | Yes |
invalid | VIES answered: not valid (not registered, no longer active, or not enabled for cross-border trade) | Yes |
invalid-format | Cannot be a VAT number of that member state (wrong length or characters); VIES is not asked | No |
outside-vies | A country VIES does not cover, such as GB, CH or NO | No |
unavailable | VIES or the member state did not answer within the maximum wait. Not an answer about the number | No |
no-match | No company with a similar name and a valid VAT number was found. match.alternatives lists the similar companies without their VIES result (not-checked): VIES results come with a charged match | No |
skipped | Not checked because the run's check limit or your spending limit was reached. A number with an earlier result other than skipped keeps that result instead (unchanged, with fromEarlierRun: true and a statusReason saying it was not checked in this run) | No |
A German number checked during an outage: not checked, not charged, and checked again in the next run of the task.
{"envelopeVersion": 1,"id": "vat:DE143454214","scope": "vat:DE143454214","changeType": "added","sourceUrl": "https://ec.europa.eu/taxation_customs/vies/","scrapedAt": "2026-09-15T16:25:00.000Z","firstSeenAt": "2026-09-15T16:25:00.000Z","hash": "7257a435b5f7582eed8bafd9f6162e9acb0168d22dd42f19da6885189f491109","previousHash": null,"changes": [],"summary": "Added: DE143454214","diffText": null,"payload": {"input": "DE143454214","inputType": "vat-number","status": "unavailable","valid": null,"statusReason": "Germany's VAT service did not answer VIES (MS_UNAVAILABLE) (tried 5× over 1 min). This says nothing about the number: it was not checked. It is checked again in the next run of this task.","countryCode": "DE","countryName": "Germany","vatNumber": "DE143454214","vatNumberWithoutPrefix": "143454214","name": null,"address": null,"addressLines": [],"detailsWithheld": null,"consultationNumber": null,"requesterVatNumber": null,"checkedAt": null,"fromEarlierRun": false,"unavailable": {"code": "MS_UNAVAILABLE","reason": "Germany's VAT service did not answer VIES (MS_UNAVAILABLE) (tried 5× over 1 min). This says nothing about the number: it was not checked. It is checked again in the next run of this task.","viesStatus": "Available","attempts": 5,"waitedSeconds": 75,"retryAfter": null},"pendingSince": "2026-09-15T16:25:00.000Z","carriedOver": false,"doubleChecked": false,"match": null}}
Pricing
Pay only for answers.
| Event | Name | What it means | Price |
|---|---|---|---|
apify-actor-start | Actor start | Charged by Apify when a run starts: once for a run of up to 1 GB of memory, and once more for every extra GB. It covers the first five seconds of compute. | $0.00005 per run up to 1 GB of memory ($0.05 per 1,000) |
vat-number-validated (primary) | VAT number validated | VIES gave a definite answer for one VAT number: valid or invalid, with the consultation number when you provide your own VAT number. Never charged when VIES or the member state did not answer. | $0.004 per VAT number ($4.00 per 1,000) |
company-matched | Company matched | A company name was matched to a VAT number that VIES confirmed as valid, including the validation itself. No charge without a confirmed match. | $0.02 per matched company ($20.00 per 1,000) |
Unavailable numbers, impossible formats, countries outside VIES, company names without a confirmed match (their records list the similar companies found, without VIES results) and test-service checks cost nothing. The time spent waiting for a member state is on us. 1,000 numbers with answers cost $4.00; a company name that is confirmed costs a match on top.
FAQ
What exactly does invalid mean?
VIES answered that the number is not valid for intra-Community transactions. That can mean it does not exist, is no longer active, or exists nationally but is not enabled for cross-border trade (some member states register that separately). In all cases, reverse charge is not supported by that answer.
Why are name and address empty for a valid German number?
Germany (and some other member states) does not disclose them through VIES. detailsWithheld is then true. If you give a company name, the Actor can still compare it through the name sources above.
How long does a run take?
Normally a few seconds per hundred numbers. During an outage, numbers from the affected member state wait up to the maximum wait you set; numbers from other member states are not delayed.
Is bulk VAT number validation through VIES allowed, and is it GDPR-compliant?
VIES may be used to verify the VAT numbers of your business partners, for example to draw up your own invoices; building or reselling a database from it is not allowed. This Actor fits that purpose: every check is live, for the numbers you provide, and results go only to your own Apify account. There is no shared cache between users.
VAT numbers of sole traders are personal data under the GDPR, and VIES returns their registered name and address. This Actor therefore returns name and address only as VIES provides them, for the numbers you ask about; keeps the last result per number (for change detection and retries) only in the key-value store vies-vat-validator-state of your own Apify account; skips French sole traders (entrepreneurs individuels, whose company name is the owner's name) and companies that opted out of publication in the name search; and reads only names, countries and identifiers from Peppol business cards, which businesses publish themselves for e-invoicing (never contacts, addresses or free text).
Results are kept per task or state key, and runs without either share one set. A result is deleted by the first run with the same task or state key that starts more than 35 days after the last run that checked the number; a run that reached the number after its check limit or your spending limit was used up counts as checking it, a run that left it out because its memory was full does not, and a run that fails deletes nothing. A run in which nothing fits in memory fails, unless deleting results that are due for deletion makes room: then it deletes them and checks nothing. Results of a task or state key that does not run again stay until you delete them: delete the store in Apify Console (Storage, Key-value stores), or only the records whose key starts with the task ID or state key and a dot (default. for runs without either), while no run with that state is working.
What are the limitations?
- VIES publishes no rate limits; the Actor paces itself per member state and reacts to throttling, but a member state that throttles for longer than the maximum wait still yields
unavailablenumbers. - Consultation numbers require your own valid EU VAT number; VIES rejects the whole request otherwise, and the run stops before charging.
- Company name matching depends on the coverage of the Peppol Directory outside France.
- One run checks what its memory holds (15,000 numbers and company names with the default 1 GB, 55,000 with 4 GB), fewer when its task or state key keeps many results from earlier runs, and none once a state that keeps getting new numbers is full; see Batch size and memory under Input.
- This Actor is not affiliated with the European Commission. It uses the public VIES REST API and, for company names, the public Peppol Directory and French company register.
Related Actors
- EU Company ID Resolver: turn a VAT number into KvK, KBO, SIREN and LEI, with the registered name, legal form and status from the national registers.
- Peppol Participant Lookup: can this customer receive an e-invoice? A valid VAT number says the customer is a VAT-registered business; Peppol reachability is a different question, answered from the same kind of list.
- IBAN Validator & Bank Enricher for supplier and customer bank accounts: the same kind of bulk check for IBANs, fully offline.
Support
Missing something your accounting integration needs? Open an issue on the Actor page.