# EU VAT Number Validator API (VIES): Name, Address, Proof (`actose/eu-vat-vies-validator`) Actor

Bulk-check EU VAT numbers on official VIES: validity, company name, address, request date and consultation number as proof. CSV or Google Sheets input, auto-retry on VIES errors. No API key, no login. MCP-ready for AI agents. Invalid numbers and errors are free. $2 per 1,000 valid numbers.

- **URL**: https://apify.com/actose/eu-vat-vies-validator.md
- **Developed by:** [ABM](https://apify.com/actose) (community)
- **Categories:** Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.70 / 1,000 verified vat numbers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## EU VAT Number Validator API (VIES) — Bulk Check with Company Name, Address and Proof

**$2 per 1,000 verified VAT numbers ($0.002 each). Invalid numbers, format errors and VIES outages are free.**

Validate EU VAT numbers in bulk against the **official VIES service of the European Commission**. For each number you get:
validity, registered **company name and address**, the **VIES request timestamp** (proof of check) and, if you give your own VAT
number, the **official VIES consultation number** you can keep as legal evidence for zero-rated intra-EU invoices.

- Paste a list or point to a **CSV file / Google Sheet** — the VAT column is detected automatically.
- **Automatic retries** on VIES temporary errors (`MS_MAX_CONCURRENT_REQ`, `MS_UNAVAILABLE`, `TIMEOUT`...), with per-country throttling.
- Cleans input: spaces, dots, dashes, lowercase, `GR` → `EL`, duplicates removed.
- All 27 EU member states + Northern Ireland (`XI`).
- No API key, no login, no monthly rental. MCP-ready for Claude, Cursor, ChatGPT and AI agents.
- `onlyNew` and `statusChanged` for scheduled re-verification of your customer or supplier base.
- An audit CSV report is saved in the key-value store (`vat-report.csv`).

### How much does it cost?

Pay per event: **`numero-verifie` = $0.002**, charged only when VIES confirms the number is **valid**.

| You check | Valid numbers | You pay |
|---|---|---|
| 100 numbers | 90 valid, 10 invalid | **$0.18** |
| 1,000 numbers | 1,000 valid | **$2.00** |
| 10,000 numbers | 8,500 valid, 1,500 invalid/unavailable | **$17.00** |

Invalid numbers, bad formats and numbers VIES could not check (national service down) cost **nothing**. Set "Max cost per run"
in Apify to cap your spend: the actor stops cleanly when the limit is reached.

### Input

```json
{
  "vatNumbers": ["FR40303265045", "DE811128135", "IE 6388047 V", "gr094014201"],
  "csvUrl": "https://docs.google.com/spreadsheets/d/<your-sheet-id>/edit#gid=0",
  "requesterVatNumber": "FR12345678901",
  "onlyNew": false,
  "includeInvalid": true,
  "maxConcurrency": 5,
  "maxRetries": 6
}
```

| Field | Description |
|---|---|
| `vatNumbers` | List of VAT numbers with country prefix. |
| `csvUrl` | Public CSV/TXT link or Google Sheet ("anyone with the link"). Combined with the list. |
| `csvColumn` | Column header to use if auto-detection is wrong. |
| `requesterVatNumber` | Your own EU VAT number → VIES returns a consultation number per check. |
| `onlyNew` | Skip numbers already confirmed valid in previous runs. |
| `includeInvalid` | Output invalid / badly formatted numbers too (free). Default `true`. |
| `maxConcurrency` | Parallel checks (max 2 per country). Default 5. |
| `maxRetries` | Retries on VIES temporary errors. Default 6 (`0` = no retry). At most 75 s of retrying per number; national services VIES reports as down get at most 2 retries; numbers left when the run is about to time out are returned as `unavailable` (free). |

### Output

One object per VAT number in the dataset:

```json
{
  "input": "IE 6388047 V",
  "vatNumber": "IE6388047V",
  "countryCode": "IE",
  "vatNumberLocal": "6388047V",
  "isValid": true,
  "status": "valid",
  "companyName": "GOOGLE IRELAND LIMITED",
  "companyAddress": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4",
  "companyAddressLines": ["3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4"],
  "nameAvailable": true,
  "requestDate": "2026-10-20T04:20:33.853Z",
  "checkedAt": "2026-10-20T04:20:34Z",
  "consultationNumber": "WAPIAAAAZ3xxxxxx",
  "requesterVatNumber": "FR12345678901",
  "viesErrorCode": null,
  "message": "VAT number is valid and active in VIES.",
  "proofText": "On 2026-10-20T04:20:33.853Z, the EU VIES service confirmed that VAT number IE6388047V is valid, registered to GOOGLE IRELAND LIMITED, 3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4. Consultation number: WAPIAAAAZ3xxxxxx.",
  "attempts": 1,
  "previousStatus": "valid",
  "statusChanged": false,
  "source": "VIES REST API (European Commission)"
}
```

`status` values: `valid` (charged), `invalid`, `invalid_input` (wrong format), `unavailable` (VIES/national service down after
all retries — run again later), `error`. Only `valid` is charged.

### Use cases

#### 1. Finance team: monthly check of the customer base before zero-rated invoicing

An accounts-receivable manager exports 2,400 B2B EU customers from the ERP into a Google Sheet. The actor runs on the 1st of every
month with their own VAT number to get consultation numbers.

Input:

```json
{"csvUrl": "https://docs.google.com/spreadsheets/d/1AbC.../edit#gid=0", "requesterVatNumber": "FR12345678901"}
```

Output extract:

```json
[{"vatNumber": "NL004495445B01", "status": "valid", "companyName": "OPENJONGERENVERENIGING DE KOORNBEURS", "consultationNumber": "WAPIAAAAZ3..."},
 {"vatNumber": "BE0123456789", "status": "invalid", "previousStatus": "valid", "statusChanged": true}]
```

Next: rows with `statusChanged: true` go to a "VAT revoked" tab; the billing team switches those customers to domestic VAT.
Cost: ~2,300 valid × $0.002 = **$4.60 per month**, with consultation numbers archived for tax audits.

#### 2. E-commerce / SaaS: verify B2B sign-ups every morning

A growth ops engineer stores new business sign-ups in a CSV. A schedule at 7:00 runs with `onlyNew: true`, so only the ~40
new numbers of the day are checked.

Input:

```json
{"csvUrl": "https://example.com/exports/new-b2b-signups.csv", "csvColumn": "vat_id", "onlyNew": true}
```

Output extract:

```json
[{"input": "de 811 128 135", "vatNumber": "DE811128135", "status": "valid", "nameAvailable": false},
 {"input": "IT0074311015", "status": "invalid_input", "message": "VIES rejected the number format (wrong length or characters for this country)."}]
```

Next: valid accounts get reverse-charge invoices automatically; `invalid_input` rows trigger an email asking the customer to fix
their VAT number. Cost: ~$0.08 per day.

#### 3. Procurement / KYB: supplier onboarding with name matching

A procurement analyst checks 300 new suppliers before the first payment and compares `companyName` with the name on the
supplier's invoice.

Input:

```json
{"vatNumbers": ["PL7740001454", "EL094014201", "LU26375245", "IT00743110157"]}
```

Output extract:

```json
[{"vatNumber": "PL7740001454", "companyName": "ORLEN SPÓŁKA AKCYJNA", "companyAddress": "CHEMIKÓW 7, 09-411 PŁOCK"},
 {"vatNumber": "EL094014201", "companyName": "ΤΡΑΠΕΖΑ ΕΘΝΙΚΗ ΤΗΣ ΕΛΛΑΔΟΣ ΑΝΩΝΥΜΗ ΕΤΑΙΡΕΙΑ"}]
```

Next: an LLM compares `companyName` with the invoice name (any alphabet), mismatches go to manual review. Cost: 300 × $0.002 = **$0.60**.

### Call it from the API

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("<username>/eu-vat-vies-validator").call(
    run_input={"vatNumbers": ["FR40303265045", "DE811128135"]}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["vatNumber"], item["status"], item["companyName"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('<username>/eu-vat-vies-validator').call({
    vatNumbers: ['FR40303265045', 'DE811128135'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((i) => `${i.vatNumber} ${i.status} ${i.companyName ?? ''}`));
```

Synchronous HTTP (one call, results in the response):

```
POST https://api.apify.com/v2/acts/<username>~eu-vat-vies-validator/run-sync-get-dataset-items?token=<APIFY_TOKEN>
{"vatNumbers": ["IE6388047V"]}
```

### Integrations (Make, Zapier, n8n, Google Sheets)

- **n8n**: Schedule Trigger (monthly) → *Apify: Run actor* (`csvUrl` = your Google Sheet export) → *Apify: Get dataset items* →
  IF `statusChanged = true` → Google Sheets "Append row" + Slack message to the finance channel.
- **Make**: Watch new rows in Google Sheets → Apify "Run an actor" with `{"vatNumbers": ["{{VAT}}"]}` → write `status`,
  `companyName` and `consultationNumber` back into the row.
- **Zapier**: New customer in your CRM → Apify "Run actor" → update the CRM field "VAT verified".
- **Google Sheets**: export the dataset as CSV/XLSX, or use the `vat-report.csv` audit file from the key-value store.

### Use with AI agents (MCP)

The actor works as a tool in the Apify MCP server (`https://mcp.apify.com`) for Claude, Cursor, ChatGPT and other agents.
Ask "Check whether these EU VAT numbers are valid and give me the company names: …" — the agent calls the actor and gets
structured JSON plus a ready-to-quote `proofText` sentence for each number.

### FAQ

**Is this the official VIES data?** Yes. Every number is checked live against the European Commission VIES REST API. Nothing is cached or guessed.

**Why is the company name empty for some countries?** Some member states (e.g. Germany, Spain) don't disclose name and address
through VIES. The validity check still works; `nameAvailable` is `false`.

**What is a consultation number?** An identifier VIES issues when you give your own VAT number as requester. Tax authorities
accept it as proof that you checked your customer's VAT number on a given date.

**What happens when VIES is down?** The actor retries with exponential backoff (per-country throttling). If a national service stays
down, the number is returned with `status: "unavailable"` and is **not charged** — run it again later.

**Can I validate UK (GB) numbers?** No: VIES covers EU member states and Northern Ireland (`XI`) only.

**Does "invalid" mean the company doesn't exist?** It means the number is not active for intra-EU transactions in VIES
(not registered, deregistered, or not activated for cross-border trade).

### Limits

- VIES limits concurrent requests per member state; large countries (FR, DE, IT) can be busy during office hours, which slows
  big batches. Expect roughly 1,000–3,000 numbers per 10 minutes depending on VIES load.
- Name/address availability depends on the member state.
- Consultation numbers require a valid EU VAT number of your own.
- CSV files are limited to 20 MB per run; `onlyNew` memory holds ~150,000 numbers.

# Actor input Schema

## `vatNumbers` (type: `array`):

EU VAT numbers with their 2-letter country prefix (FR, DE, IT, EL for Greece, XI for Northern Ireland...). Spaces, dots and dashes are ignored; GR is converted to EL. Duplicates are checked only once.

## `csvUrl` (type: `string`):

Public link to a CSV/TXT file or a Google Sheet shared as 'anyone with the link'. The VAT column is detected automatically (vat, vat_number, tva, ust-idnr, btw, iva, nif...). Combined with the list above.

## `csvColumn` (type: `string`):

Exact header of the column holding the VAT numbers, if the automatic detection picks the wrong one.

## `requesterVatNumber` (type: `string`):

If set, VIES returns an official consultation number for each valid check — the legal proof that you verified your customer's VAT number (useful for zero-rated intra-EU invoices).

## `onlyNew` (type: `boolean`):

For scheduled runs: skip numbers already confirmed valid in previous runs (remembered in the named key-value store 'eu-vat-vies-validator-state'). Leave off to re-verify everything.

## `includeInvalid` (type: `boolean`):

Also output invalid and badly formatted numbers (free, never charged). VIES outages are always output with status 'unavailable'.

## `maxConcurrency` (type: `integer`):

Number of VAT numbers checked at the same time (max 2 per country to respect VIES limits).

## `maxRetries` (type: `integer`):

How many times a number is retried when VIES or a national service is busy (MS_MAX_CONCURRENT_REQ, MS_UNAVAILABLE, TIMEOUT...). Exponential backoff up to 20 s.

## Actor input object example

```json
{
  "vatNumbers": [
    "FR40303265045",
    "DE811128135",
    "IE6388047V"
  ],
  "onlyNew": false,
  "includeInvalid": true,
  "maxConcurrency": 5,
  "maxRetries": 6
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `report` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "vatNumbers": [
        "FR40303265045",
        "DE811128135",
        "IE6388047V"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("actose/eu-vat-vies-validator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "vatNumbers": [
        "FR40303265045",
        "DE811128135",
        "IE6388047V",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("actose/eu-vat-vies-validator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "vatNumbers": [
    "FR40303265045",
    "DE811128135",
    "IE6388047V"
  ]
}' |
apify call actose/eu-vat-vies-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,actose/eu-vat-vies-validator"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/841PHvn6FPzRrv0Uh/builds/w0LGJ5rHw1XC4YOaU/openapi.json
