# EU VAT Number Validator (VIES) (`miacx/eu-vat-validator`) Actor

Check EU VAT numbers in batches against the official VIES service. Get validity plus the registered name and address where the member state provides them.

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

## Pricing

from $0.90 / 1,000 vat number checks

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?

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 (VIES)

Check a list of EU VAT numbers in one run instead of typing them into the VIES web form one at a time.
The Actor checks each number against the European Commission's VIES service. You get one row per number with its validity, plus the registered name and address when the member state shares them.
UK VAT numbers and other non-EU IDs come back as `UNSUPPORTED_COUNTRY` rows at no charge.
Each answered VAT number costs $0.0009, plus $0.00005 per run start at default memory.

### Try it

```json
{ "ids": ["IE6388047V", "DE811907980"] }
```

An empty input `{}` checks these same two numbers. An empty `ids` list fails the run.
VIES needs no API key or account.

### Use from an agent

Add `https://mcp.apify.com?tools=miacx/eu-vat-validator` to your MCP client and sign in to Apify.
Call the dedicated Actor tool with the input above, then read its completed dataset with `get-dataset-items`.
Or set `APIFY_TOKEN` to your Apify API token and request JSON rows:

```sh
curl --fail-with-body 'https://api.apify.com/v2/actors/miacx~eu-vat-validator/run-sync-get-dataset-items' \
  -H "Authorization: Bearer $APIFY_TOKEN" -H 'Content-Type: application/json' \
  -d '{"ids":["IE6388047V","DE811907980"]}'
```

### What you get

Read `status` first. On `ok`, inspect `valid`. An invalid answer is still a completed, billable check.
There is one row per processed input, in input order, including duplicates.
Every row has every key. Missing details are null.

This row comes from the recorded Irish VIES fixture, processed with the fixed test clock.

```json
{
  "input": "IE6388047V",
  "ok": true,
  "status": "ok",
  "id": "IE6388047V",
  "country": "IE",
  "registry": "vies",
  "valid": true,
  "name": "GOOGLE IRELAND LIMITED",
  "address": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4",
  "reference": null,
  "source": "https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number",
  "fetchedAt": "2026-10-31T00:00:00.000Z",
  "cached": false,
  "error": null,
  "errorMessage": null
}
```

`id` is normalized; `input` keeps the text you sent. `country` uses VIES codes, so Greece is EL and Northern Ireland is XI.
`valid` is null on failure. Some member states, Germany among them, withhold names and addresses. Those fields stay null.
`reference` holds the VIES request identifier when you supply your own VAT number as `viesRequester`.
`source` is the VIES endpoint, without the queried number. `fetchedAt` records when the last VIES request finished, including failures.
Both are null when no request went to VIES. Cached answers keep their original timestamp and reference.

### Input

| Field           | Default                        | Accepted input                                                                                                       |
| --------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `ids`           | `["IE6388047V","DE811907980"]` | 1–10,000 VAT numbers with prefixes for the 27 member states or XI.                                                   |
| `viesRequester` | `""`                           | Your own EU VAT number with its prefix, to request a VIES reference.                                                 |
| `useCache`      | `true`                         | Reuse recent VIES answers. False skips cross-run reads and writes; duplicates still share one lookup within the run. |

Numbers ignore case, spaces, dots, dashes and slashes, and GR becomes EL.
A number without a two-letter prefix, or with fewer than 2 or more than 12 characters after it, returns `INVALID_FORMAT` before any VIES request.
An empty or null `viesRequester` means no requester. A malformed or rejected requester returns `INVALID_REQUESTER` instead of an answer.

### Pricing

A VAT number check (`tax-id-check`) costs $0.0009 per unique normalized number VIES answers within one run.
Valid, invalid and cached answers count. Errors, unsupported prefixes and repeated numbers incur no result events.
Duplicates keep their own dataset rows, so the row count can exceed the number of charged checks.

1,000 answered numbers cost $0.90005, including the $0.00005 run start at default 256 MB memory.
The start charge applies even with no billable checks. Apify counts one start event per GB, with a minimum of one.
The Actor stops at the first input needing a new lookup beyond your spending limit. Later inputs get no rows.

### Limits and data freshness

- At most 10,000 numbers per run, four VIES lookups in flight, a ten-second request timeout and 256 KiB per VIES response.
- Network failures, timeouts, HTTP 429 and 5xx responses and VIES concurrency limits get up to two retries.
- A `Retry-After` longer than ten seconds fails the row at once instead of waiting.
- When VIES reports a member state down, other numbers from that state fail for 30 seconds. Other states continue.
- Valid answers are reused for 24 hours and invalid answers for one hour. Errors never enter the cross-run cache.

The named store `taxid-check-cache` in the running account keeps up to 10,000 unexpired answers when saved.
Expiry limits reuse; the last saved record stays until overwritten or deleted.
Set `useCache: false` for fresh lookups. It does not delete earlier cache records.
`cached` marks a cross-run cache hit. Duplicate rows reuse the first answer's cache flag.

The synchronous API waits up to 300 seconds. Use [asynchronous runs](https://docs.apify.com/api/v2/actor-runs-post) for longer batches.

### If a row fails

| Status                                                     | Next step                                                                           |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `INVALID_FORMAT`                                           | Check the prefix and number. VIES also returns this for numbers it cannot parse.    |
| `UNSUPPORTED_COUNTRY`                                      | Use an EU member state or XI prefix. VIES does not cover UK VAT or other countries. |
| `INVALID_REQUESTER`                                        | Correct `viesRequester` or leave it empty.                                          |
| `RATE_LIMITED`, `REGISTRY_UNAVAILABLE`, `UPSTREAM_TIMEOUT` | Retry later, or run fewer batches at once.                                          |
| `AUTH_FAILED`                                              | VIES blocked the request. Retry later.                                              |
| `UPSTREAM_ERROR`                                           | Read `errorMessage` for a network or response-format failure.                       |

A failed row has `ok: false`, `valid: null` and matching `status` and `error` codes.
It does not mean the VAT number is invalid.

# Actor input Schema

## `ids` (type: `array`):

1-10,000 EU VAT numbers with country prefixes, such as IE6388047V or DE811907980. Covers the 27 member states and XI (Northern Ireland). Spaces, dots, dashes and slashes are ignored; GR becomes EL. Other prefixes return UNSUPPORTED_COUNTRY rows at no charge. Omitted checks IE6388047V and DE811907980; \[] fails the run. Each unique normalized number VIES answers incurs one event per run, including invalid and cached answers.

## `viesRequester` (type: `string`):

Your own EU VAT number with its country prefix, sent to VIES to request a consultation reference. Omitted, empty or null means no requester. A malformed or rejected requester returns INVALID_REQUESTER instead of an answer. Answers with a requester are cached apart from answers without one; cached references keep the original check time.

## `useCache` (type: `boolean`):

Reuse VIES answers from taxid-check-cache in your Apify account: valid answers for 24 hours, invalid answers for one hour. Defaults to true. False bypasses cross-run cache reads and writes; within-run deduplication remains. Cached answers are billable and keep their original fetchedAt. Stored records remain until rewritten or deleted.

## Actor input object example

```json
{
  "ids": [
    "IE6388047V",
    "DE811907980"
  ],
  "viesRequester": "",
  "useCache": true
}
```

# Actor output Schema

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

VAT validation results in the default dataset.

# 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 = {
    "ids": [
        "IE6388047V",
        "DE811907980"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("miacx/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 = { "ids": [
        "IE6388047V",
        "DE811907980",
    ] }

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

```

## MCP server setup

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