# EU VAT Validator — VIES Check with Official Proof (`sourcerow/eu-vat-validator`) Actor

Bulk-validate EU VAT numbers against the official VIES service. Returns company name and address, an official consultation number as proof, and never confuses "not registered" with "could not check".

- **URL**: https://apify.com/sourcerow/eu-vat-validator.md
- **Developed by:** [SourceRow](https://apify.com/sourcerow) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$6.00 / 1,000 vat checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

Validate EU VAT numbers in bulk against VIES, the European Commission's official
VAT Information Exchange System. Returns the registered trader name and address,
an official consultation number usable as proof, and a distinct answer when VIES
could not be reached.

### What it does

Each number supplied is checked against the [VIES service](https://ec.europa.eu/taxation_customs/vies/)
run by the European Commission. One row per number, 11 fields per row, containing
whether the number is registered, the trader's name and address as held by the
member state, and the date of the check.

The Actor is built around one distinction: **"not registered" and "could not be
checked" are different answers.** VIES is a federation of 27 national databases
and individual countries go offline regularly. A tool that reports an
unreachable country as invalid states that a real customer does not exist, and
acting on that by charging domestic VAT is expensive. Every row is `valid`,
`invalid`, or `unchecked`, and the three are never collapsed.

### What you get

11 fields per row: `input`, `country_code`, `vat_number`, `status`, `source`,
`company_name`, `address`, `request_identifier`, `request_date`, `error`,
`issues`.

`request_identifier` is the official consultation number issued by VIES. It is
the evidence a tax authority accepts that a customer was verified on a given
date, and it is required for reverse-charge invoicing. It is only issued when
your own VAT number is supplied with the request.

### Input

| Field | Meaning |
|---|---|
| `vatNumbers` | Numbers with the country prefix, for example `IT00743110157`. |
| `vatNumbersText` | A pasted list instead, one per line; commas and semicolons also work. |
| `requesterVatNumber` | Your own VAT number. Optional, but without it VIES issues no proof of consultation. |
| `maxNumbers` | Stop after this many. `0` removes the cap. |

```json
{
  "vatNumbersText": "IT00743110157\nBE0417497106\nPL5250005834",
  "requesterVatNumber": "IT00743110157",
  "maxNumbers": 100
}
```

### Sample output

One complete record:

```json
{
  "input": "IT00743110157",
  "country_code": "IT",
  "vat_number": "00743110157",
  "status": "valid",
  "source": "vies",
  "company_name": "MOTOROLA SOLUTIONS ITALIA SRL",
  "address": "LARGO FRANCESCO RICHINI 6 20122 MILANO MI",
  "request_identifier": "WAPIAAAAXXXXXXXX",
  "request_date": "2026-08-25T22:02:59.247Z",
  "error": null,
  "issues": ""
}
```

`source` states how the answer was produced: `vies` when the service replied,
`format` when the number was rejected locally before asking, `cache` when the
same number appeared earlier in the same list.

### Pricing

| Event | Per 1,000 | Notes |
|---|---|---|
| VAT checked | $6.00 | Only numbers VIES actually answered |

Rows marked `unchecked` are not charged: an unreachable member state is a
service failure, not a result. Duplicates within a list are answered from cache
and are not charged either. There is no start fee and no per-row dataset fee.

### What it does not do

**It does not tell you whether a company is solvent, active or trading.** VIES
answers one question: is this VAT number registered for intra-EU trade today.

**Germany and Spain do not return trader names.** Those member states do not
disclose names through VIES. The number is confirmed registered and
`company_name` is empty. This is national policy, not a limitation of this
Actor, and `issues` flags it as `valid_without_name`.

**No proof without your own VAT number.** The consultation number is issued by
VIES to an identified requester. Without `requesterVatNumber` the validation
result is correct but carries no evidence, and `issues` flags
`no_official_proof`.

**Unchecked rows are not retried automatically.** A member state that is down
stays down for the length of a run. Re-run those rows later rather than treating
them as invalid.

### Notes

Supply your own VAT number whenever the check is for invoicing. Without it the
answer is correct but not defensible during an audit.

Filter for `status = unchecked` after a run and schedule those again. They are
unanswered, not negative.

Formatting does not need cleaning. `IT 00743110157` and `it-00743110157` resolve
to the same number and the second is answered from cache.

Schedule monthly rather than validating once at signup. Registrations are
revoked and VIES reflects that within days.

### Support

Open the **Issues** tab, including the specific VAT number and the `status` and
`error` values from the row.

### Licence and attribution

VAT numbers are checked against VIES, the official service of the European
Commission. VIES is a search interface over 27 national databases, not a
downloadable dataset: each check queries the member state's own tax authority in
real time. Nothing is downloaded, stored, or redistributed. The European
Commission does not warrant the accuracy of the national registers behind it.

# Actor input Schema

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

VAT numbers with country prefix, e.g. IT00743110157. Spaces, dots and dashes are ignored. Left untouched, the Actor checks these three real numbers so a first run shows you what the output looks like.

## `vatNumbersText` (type: `string`):

One VAT number per line (commas and semicolons also work). Use this to paste straight from a spreadsheet.

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

Supply your own VAT number to receive an official VIES consultation number for every check. That identifier is the proof you show a tax authority that you verified the customer on that date — required for reverse-charge invoicing. Without it, you get the validation result but no proof.

## `maxNumbers` (type: `integer`):

Stop after this many. **0 removes the cap.**

## Actor input object example

```json
{
  "vatNumbers": [
    "IT00743110157",
    "BE0417497106",
    "PL5250005834"
  ],
  "maxNumbers": 100
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "IT00743110157",
        "BE0417497106",
        "PL5250005834"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sourcerow/eu-vat-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": [
        "IT00743110157",
        "BE0417497106",
        "PL5250005834",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("sourcerow/eu-vat-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": [
    "IT00743110157",
    "BE0417497106",
    "PL5250005834"
  ]
}' |
apify call sourcerow/eu-vat-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sourcerow/eu-vat-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/g9WL3b4ts9MVepa0K/builds/UmWEYu3j8cd8Ro7SI/openapi.json
