# EU VAT Number Validation (VIES) (`fabriken2026/eu-vat-validation`) Actor

Validate EU VAT numbers in real time against the European Commission's VIES: valid, invalid or source-down - with official audit receipts.

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

## Pricing

from $10.00 / 1,000 completed vat validations

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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 Validation (VIES) - Three Honest Answers

**Verified official source - never hallucinated.** This Actor validates
EU VAT numbers in real time against **VIES**, the European Commission's
VAT Information Exchange System - not with an AI model's guess and not
with a scraped snapshot of somebody's website. And unlike most
validators, it tells the truth when the source is down.

> Validation is performed in real time against the European
> Commission's VIES on the customer's behalf. A valid response is one
> piece of evidence, not a guarantee - see the
> [VIES disclaimer](https://ec.europa.eu/taxation_customs/vies/#/disclaimer)
> and the
> [VIES Data Protection Notice](https://ec.europa.eu/dpo-register/detail/DPO-3816-1).
> No company or personal data is stored by the service.

### Why this Actor?

VIES is free at the source - but notoriously flaky. Member state
registries drop out independently and unannounced, Germany never
returns names, Greece is coded `EL` (not `GR`), and hidden per-country
concurrency limits throw errors that most wrappers silently translate
into "invalid". That silent lie is dangerous: it blocks good suppliers
and stops correct reverse-charge invoices.

This Actor is the boring, reliable shell around a shaky source:

- **Three-state answers:** `valid`, `invalid` or
  `unknown_source_unavailable`. A registry outage is **never** reported
  as invalid - and never charged.
- **Format check before the call.** Every number is validated against
  its country's official VAT pattern first, so typos never reach the
  API and never cost you anything.
- **Country-code traps handled:** `GR` is auto-corrected to `EL`
  (Greece's VIES code), Northern Ireland works as `XI`, and `GB` is
  rejected with a clear Brexit explanation instead of a confusing error.
- **Retry with backoff** (3s/6s/9s) on VIES concurrency errors -
  Germany's infamous `MS_MAX_CONCURRENT_REQ` is absorbed, not exposed.
- **Per-country queues in batch runs:** one country being down never
  blocks validation of the others, and a down country is not hammered
  with further calls.
- **Official audit receipt:** provide your own EU VAT number and each
  valid lookup returns the EU's **consultation number** - the
  Commission's own proof for VAT audits that you checked the number
  that day. Receipts are always fetched fresh, never from cache.
- **No AI in the loop.** Pure, predictable code. Same input, same
  output, every time.

### Use cases

- **Reverse-charge invoicing:** confirm your customer's VAT number
  before zero-rating an intra-EU B2B invoice, and store the
  consultation number as audit evidence.
- **AI agents that must not hallucinate:** a grounded, three-state VAT
  check instead of a guess - the `unknown_source_unavailable` state
  lets the agent retry later rather than draw a false conclusion.
- **Supplier and customer onboarding (KYB):** verify counterparties
  across all 27 EU member states plus Northern Ireland in one call.
- **ERP and CRM hygiene:** batch-validate up to 50 stored VAT numbers
  per run, with per-row source and timestamp for your compliance trail.

### Input

```json
{
    "vatNumbers": ["SE556042722001", "DE129273398", "EL123456789"],
    "requesterVatNumber": "SE556999999901",
    "confirmLegitimateUse": true
}
````

`confirmLegitimateUse` is **required**: you attest that every lookup
supports your own VAT compliance as a legitimate user of VIES (the
exemption the VIES disclaimer grants), and that you will not use the
Actor to build registers, republish data or look up individuals. Runs
without the attestation are rejected before any call is made.

### Output (dataset items)

```json
{
    "input": "SE556042722001",
    "ok": true,
    "status": "valid",
    "vatNumber": "SE556042722001",
    "countryCode": "SE",
    "name": "H & M Hennes & Mauritz AB",
    "address": "MASTER SAMUELSGATAN 46 A, 106 38 STOCKHOLM",
    "checkedAt": "2026-07-12T10:00:00.000Z",
    "consultationNumber": "WAPIAAAAY6mrqctG",
    "fromCache": false,
    "chargeable": true,
    "evidenceNote": "A valid VIES response is one piece of evidence...",
    "disclaimerLinks": { "vies_disclaimer": "...", "vies_data_protection": "..." },
    "source": "VIES, European Commission (ec.europa.eu/taxation_customs/vies)"
}
```

When a country withholds names (Germany always does), the item says so
honestly in `notes` - the validity verdict still stands. When a
registry is down, `status` is `unknown_source_unavailable` with the
exact VIES error code in `sourceError`, so you can retry later.

### Pricing (pay-per-event)

| Event | Price | When |
|---|---|---|
| `actor-start` | $0.005 | Per run |
| `vat-validation` | $0.01 | Per **completed** validation only (a valid or invalid verdict) |
| Source down | $0.00 | `unknown_source_unavailable` answers are free |
| Cache hit / format reject | $0.00 | Repeated numbers within 24h and typos are free |

**We do not charge for answers we could not give.** The nearest
competitor charges $0.04 per validation regardless; here an EU outage
costs you nothing.

### FAQ

**Is there a free API for EU VAT validation?**
Yes - VIES itself, and this Actor never hides that. You pay for the
shell: format checks, the `EL`/`XI` traps, retry and backoff against
hidden concurrency limits, three-state honesty, per-country batch
queues and the consultation receipt - $0.01 per completed check.

**What is the consultation number and why do I want it?**
If you supply your own EU VAT number, VIES issues a unique consultation
number per valid check - the EU's own evidence in a VAT audit that you
verified your counterparty on that date. Receipt requests always go
fresh to the EU, never to the cache.

**Why did I get "unknown" instead of valid/invalid?**
Because the member state's registry (or all of VIES) did not answer.
Spain, Germany and France drop out most often, and VIES has a Monday
night maintenance window (UTC). The honest answer is "unknown, retry
later" - never "invalid" - and it is free.

**Does it return company names and addresses?**
When the member state provides them, yes. Some countries (notably
Germany) only confirm validity - the item then carries an explicit
note instead of silently empty fields.

**Can my AI agent use this?**
Yes - that is the primary design goal. Call it via the Apify API or
MCP. The three-state output is small, flat JSON that maps cleanly onto
agent decision logic: proceed, reject, or retry later.

**How fresh is the data?**
Every verdict comes from VIES at lookup time (repeated numbers within
the same 24h may be answered from a status-only cache, marked with the
original check time and never charged; receipts always bypass the
cache).

### GDPR & privacy by design

A VAT number can be personal data (a Swedish sole trader's VAT number
contains their personal identity number - this applies to your own
requester number too). Therefore:

- **No database is built.** Names and addresses are passed through to
  you and never stored or cached.
- The 24h cache stores **only** a validity status against a **SHA-256
  hash** of the number, marked with the original check time.
- **Logs never contain plain-text VAT numbers** - only hashes and
  country codes.
- **There is no search function**: numbers in, never "find people or
  companies".

### Permissions & security

This Actor runs with Apify's **limited permissions** model: it reads
its own input, writes to its own default dataset and calls the
Commission's official API over HTTPS - nothing else. No API key or
login is needed anywhere in the chain.

### Data source & license

Data comes from **VIES**, operated by the European Commission with data
from the 27 member state registries plus Northern Ireland. The VIES
disclaimer permits retrieval and use of the data as needed to support
the activity of a legitimate user - which is exactly, and only, what
this Actor does: real-time pass-through on your behalf, no storage, no
republication (the standard industry reading of the license terms; see
the disclaimer linked above). This Actor is independent and not
affiliated with or endorsed by the European Commission.

### Terms of use

- **Business use only.** This Actor is intended exclusively for use in
  the course of business (B2B). By using it you confirm you are acting
  as a business, not a consumer, and that the legitimate-use
  attestation you give in the input is true.
- **As is.** The service and all data are provided "as is", without
  warranties of any kind - no guarantee of accuracy, completeness,
  timeliness or availability.
- **Liability cap.** Total aggregate liability for all claims in any
  12-month period is limited to the amount you paid for the service in
  that period. No liability for indirect or consequential damages, lost
  profits, lost data or tax assessments resulting from registry errors
  or outages. Nothing in these terms limits liability that cannot
  lawfully be limited.
- **Fair use.** No bulk harvesting, no register building, no
  circumventing rate limits (the Commission actively blocks bulk
  traffic), no use that conflicts with the VIES disclaimer.

### Versioning & support

Versions are locked - the Actor never silently changes behaviour under
you. Changes are released as new versions with a changelog entry.

Part of the **Nordic Data Tools** family: Swedish, Norwegian and
Finnish company lookup, company financials, new registrations,
procurement search, statistics and EU contract awards - all built on
official European data sources.

#### Changelog

- **0.1** - initial release: three-state validation for all 27 EU
  member states plus Northern Ireland (XI), per-country format checks,
  `EL`/`XI` trap handling, retry with backoff, per-country batch
  queues, consultation-number receipts (always fresh, never cached)
  and honest handling of countries that withhold names.

# Actor input Schema

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

EU VAT numbers WITH country prefix, e.g. <code>SE556042722001</code> or <code>DE129273398</code>. Spaces, dots and hyphens are cleaned automatically; <code>GR</code> is interpreted as <code>EL</code> (Greece's VIES code) and Northern Ireland uses <code>XI</code>. Max 50 per run. Each number is format-checked per country BEFORE any call - typos never reach the API and are never charged.

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

Optional. If you provide your own EU VAT number, VIES returns a unique <b>consultation number</b> for each valid lookup - the EU's own proof for VAT audits that the check was made. Receipts are ALWAYS fetched fresh from the EU, never served from cache.

## `confirmLegitimateUse` (type: `boolean`):

REQUIRED. You attest that every lookup supports your own VAT compliance as a legitimate user of VIES (e.g. checking a counterparty before reverse-charge invoicing), in line with the exemption in the VIES disclaimer - and that you will not use this Actor to build registers, republish data or look up individuals. Runs without this confirmation are rejected.

## Actor input object example

```json
{
  "vatNumbers": [
    "SE556042722001",
    "DE129273398"
  ],
  "confirmLegitimateUse": false
}
```

# 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": [
        "SE556042722001",
        "DE129273398"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabriken2026/eu-vat-validation").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": [
        "SE556042722001",
        "DE129273398",
    ] }

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "SE556042722001",
    "DE129273398"
  ]
}' |
apify call fabriken2026/eu-vat-validation --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fabriken2026/eu-vat-validation",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "EU VAT Number Validation (VIES)",
        "description": "Validate EU VAT numbers in real time against the European Commission's VIES: valid, invalid or source-down - with official audit receipts.",
        "version": "0.1",
        "x-build-id": "ze04KNMGwYhIzjdJG"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fabriken2026~eu-vat-validation/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fabriken2026-eu-vat-validation",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fabriken2026~eu-vat-validation/runs": {
            "post": {
                "operationId": "runs-sync-fabriken2026-eu-vat-validation",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fabriken2026~eu-vat-validation/run-sync": {
            "post": {
                "operationId": "run-sync-fabriken2026-eu-vat-validation",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "vatNumbers",
                    "confirmLegitimateUse"
                ],
                "properties": {
                    "vatNumbers": {
                        "title": "EU VAT numbers",
                        "type": "array",
                        "description": "EU VAT numbers WITH country prefix, e.g. <code>SE556042722001</code> or <code>DE129273398</code>. Spaces, dots and hyphens are cleaned automatically; <code>GR</code> is interpreted as <code>EL</code> (Greece's VIES code) and Northern Ireland uses <code>XI</code>. Max 50 per run. Each number is format-checked per country BEFORE any call - typos never reach the API and are never charged.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "requesterVatNumber": {
                        "title": "Your own EU VAT number (for the official receipt)",
                        "type": "string",
                        "description": "Optional. If you provide your own EU VAT number, VIES returns a unique <b>consultation number</b> for each valid lookup - the EU's own proof for VAT audits that the check was made. Receipts are ALWAYS fetched fresh from the EU, never served from cache."
                    },
                    "confirmLegitimateUse": {
                        "title": "I confirm legitimate use (required)",
                        "type": "boolean",
                        "description": "REQUIRED. You attest that every lookup supports your own VAT compliance as a legitimate user of VIES (e.g. checking a counterparty before reverse-charge invoicing), in line with the exemption in the VIES disclaimer - and that you will not use this Actor to build registers, republish data or look up individuals. Runs without this confirmation are rejected.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
