# EU VAT Number Checker (VIES) (`deriverge/eu-vat-check`) Actor

\[$1.50 / 1K] Bulk EU VAT number validation against the official VIES service for all member states and Northern Ireland. Returns validity, the registered name and address, the check date and, with your own VAT number, the consultation number tax offices accept as proof. Typos are free.

- **URL**: https://apify.com/deriverge/eu-vat-check.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 vat number checkeds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## EU VAT Number Checker

### What does EU VAT Number Checker do?

**EU VAT Number Checker** validates lists of EU VAT numbers through VIES, the European Commission's official VAT Information Exchange System. Paste a list of numbers from any member state (Northern Ireland included) and for each one you get back whether it is valid for intra-EU trade, the name and address the member state has on file, the exact date of the check, and, if you supply your own VAT number, the **consultation number** that tax authorities accept as proof that you verified your customer.

### Why the consultation number matters

Zero-rating an intra-EU supply requires a valid customer VAT number, and when the number later turns out to be invalid, the burden of proof is on you. A screenshot of the VIES website is weak evidence. A consultation number is the official one: VIES stores the check under that identifier, with the date, your VAT number and the customer's, and any tax office in the EU can look it up. This actor requests one for every row when `requesterVatNumber` is set.

### Honest about outages

VIES is a gateway to 28 national databases, and on a given day one or two of them are down. Other tools return `valid: false` in that case and let you draw the wrong conclusion. This actor asks VIES for the member-state status before it starts, reports rows from an unavailable state as `member_state_unavailable`, and does not charge for them. The same applies to numbers that fail their country's format: they are reported as typos, never sent to VIES, and never charged.

| Status | Meaning | Charged |
|---|---|---|
| `valid` | The member state confirms the number | yes |
| `invalid` | The member state does not know the number, or it is not active | yes |
| `format_error` | The number does not match the country format; nothing was sent | no |
| `member_state_unavailable` | The national database was down; run again later | no |
| `error` | VIES returned an unexpected answer; details in `note` | no |

### Input

```json
{
  "vatNumbers": [
    "DE811907980",
    "CZ 452 746 49",
    { "vatNumber": "FR89380129866", "reference": "customer-1187" }
  ],
  "requesterVatNumber": "CZ19456361",
  "defaultCountry": "",
  "watchKey": "customers"
}
```

Strings and objects can be mixed freely. Spaces, dots and dashes are ignored. Greece can be written as GR or EL.

### Output

```json
{
  "input": "DE811907980",
  "vatNumber": "DE811907980",
  "countryCode": "DE",
  "checked": true,
  "valid": true,
  "name": null,
  "address": null,
  "requestDate": "2026-09-02+02:00",
  "consultationNumber": "WAPIAAAAZbMPDlCP",
  "status": "valid",
  "note": null
}
```

Germany, like a few other member states, confirms validity without returning the name and address. That is the member state's rule, and the row says exactly what VIES said, no more.

### Watch a list for changes

Customer VAT numbers get cancelled quietly, and the invoice you issue after that is the one the auditor picks. Give the run a watch name (or save it as a task and schedule it) and every later run compares its results with the previous one: a number that turned invalid, a changed registered name. The differences are stored in the `CHANGES` record of the run. The comparison itself is free.

### Pricing

| Event | Price |
|---|---|
| VAT number checked (valid or invalid answer from VIES) | $0.003 |
| Format error, member state unavailable, or VIES error | **free** |

No start fee. A run that verifies nothing costs nothing.

### Frequently asked questions

**Is the consultation number really proof?** Yes. It is issued by VIES itself when the check is made with the requester's VAT number, and it is the mechanism the European Commission provides for exactly this purpose. Keep it with the invoice.

**Why does VIES say my customer is invalid when they are clearly trading?** VIES only confirms numbers registered for intra-EU transactions. Some member states, Spain and Italy among them, require a separate registration for that. The customer may need to register before you can zero-rate a supply to them.

**How fast is it?** VIES limits concurrent requests per member state, so numbers are checked one after another with a short gap. A thousand numbers take roughly ten minutes.

**Where does the data come from?** The European Commission VIES REST service, nothing else. Every row carries the URL, the timestamp and the exact answer.

This checker shares its engine with our country company checkers for the Czech Republic and Slovakia, Poland, France, Romania, Estonia, Lithuania, Latvia and Bulgaria, which combine VIES with the national business, tax and insolvency registers.

# Actor input Schema

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

One entry per number, with the country prefix (DE811907980, CZ45274649, FR89380129866), or an object with vatNumber and an optional reference returned unchanged. Spaces, dots and dashes are ignored. Greece can be written as GR or EL. Numbers that fail the country format are reported as typos and never sent to VIES.

## `defaultCountry` (type: `string`):

Two-letter code applied to numbers that come without a country prefix, for example CZ when your list holds bare Czech numbers. Leave empty if every number already has its prefix.

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

When you provide your own valid EU VAT number, VIES issues a consultation number for every check. Tax authorities accept it as proof that you verified the customer on that date. Without it the check still runs, but without the proof.

## `watchKey` (type: `string`):

Give the run a name such as "customers" and schedule it. Every later run with the same name compares its results with the previous one and stores the differences (a number that became invalid, a changed name) in the CHANGES record. Comparison is free. Runs from a saved task are compared automatically even without a name.

## Actor input object example

```json
{
  "vatNumbers": [
    "DE811907980",
    "CZ45274649",
    {
      "vatNumber": "FR89380129866",
      "reference": "supplier-42"
    }
  ]
}
```

# Actor output Schema

## `vatNumbers` (type: `string`):

One row per submitted number: validity, registered name and address, consultation number and status.

## `summary` (type: `string`):

Counts of valid, invalid, malformed and unverifiable numbers, and how many were charged.

# 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": [
        "DE811907980",
        "CZ45274649",
        {
            "vatNumber": "FR89380129866",
            "reference": "supplier-42"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/eu-vat-check").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": [
        "DE811907980",
        "CZ45274649",
        {
            "vatNumber": "FR89380129866",
            "reference": "supplier-42",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("deriverge/eu-vat-check").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": [
    "DE811907980",
    "CZ45274649",
    {
      "vatNumber": "FR89380129866",
      "reference": "supplier-42"
    }
  ]
}' |
apify call deriverge/eu-vat-check --silent --output-dataset

```

## MCP server setup

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

```

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/kOoLgP8xyeBWhdXxB/builds/teGwPdYSVsHjDBhsh/openapi.json
