# VAT Number Checker & EORI Checker: VIES, HMRC, EOS (`yourevenings/eu-uk-vat-eori-checker`) Actor

Check trading partners' EU VAT numbers with VIES and GB, EU and XI EORI numbers with HMRC and EOS. Local format checks first, one row per number, no API key.

- **URL**: https://apify.com/yourevenings/eu-uk-vat-eori-checker.md
- **Developed by:** [Your Evenings](https://apify.com/yourevenings) (community)
- **Categories:** E-commerce, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 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?

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

## VAT Number Checker & EORI Checker: VIES, HMRC, EOS

![VAT Number Checker and EORI Checker: VIES, HMRC and EOS](https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/3aJAAcuntBUjxtHMh-actor-kQQVFF7kktTdvMl3z-LvCGXDX0xK-vat-eori-checker-512.png)

**VAT Number Checker & EORI Checker** checks lists of VAT and EORI numbers you supply against the official public services and returns one clear JSON row per number, with **no API key needed**:

- **EU VAT numbers** (all 27 member states, plus Northern Ireland `XI`): checked with **VIES**, the European Commission's VAT Information Exchange System.
- **GB EORI numbers**: checked with **HMRC's Check an EORI number API**.
- **EU and XI EORI numbers**: checked with the European Commission's **EORI validation service (EOS)**.

Each row says `valid`, `invalid` or why the number wasn't checked, with the official check date, the source, and (if you ask for them) the trader name and address where the service publishes them. Turn on **monitor mode** and schedule it to hear when a trading partner's number becomes invalid.

Use it as a **VAT number checker** and **EU VAT validator** for your own customers and suppliers: a **VIES VAT checker** for **bulk VAT checks** of up to 500 numbers per run, and an **EORI number checker** that uses **HMRC EORI** checks for GB numbers and EOS for EU and XI numbers. Export rows as CSV, JSON or Excel.

**For checking your own trading partners' VAT and EORI numbers.** Don't republish or resell the results as a database.

> **Not affiliated with the European Commission or HMRC.** This Actor is independent and is not affiliated with, endorsed by or sponsored by either of them. It calls their public checking services one number at a time and passes on their answers. Each row carries the source's terms and attribution (see *Data sources, terms and attribution*).

**GB VAT numbers are not checked online.** HMRC's VAT number checking API needs an HMRC developer account and application, so this Actor doesn't use it. GB VAT numbers get a free `not_supported` row with a local check-digit result only.

### Why use this VAT number checker?

- **An outage is never reported as invalid.** When VIES or a national VAT database is down or busy, the number gets a free `source_unavailable` row that says to try again later. Busy answers are retried twice, after 5 and 15 seconds.
- **Bad numbers never reach the official service.** Format and check digits are checked locally first for every EU country and for GB and XI VAT numbers (format only for a few formats that can be personal identity numbers; tested against an independent open-source implementation on 84,000 numbers). A number that fails gets a free `invalid_format` row with the reason.
- **Kind to VIES, so it keeps answering.** Each VAT number is checked with VIES at most once a day (later runs that day get the cached answer, free), duplicates are removed, VIES is called one number at a time at most once a second, and a VIES refusal stops VIES for the rest of the run.
- **Proof of the check.** Every answer has the official `checkDate`. Add your own EU VAT number as `requesterVatNumber` and VIES answers also carry a `consultationNumber` you can keep as evidence.
- **Monitor mode.** A scheduled run flags numbers that `became_invalid` or `became_valid` since the last run. Outages are marked `not_checked` and don't overwrite the last real answer.
- **You pay only for real answers.** Only a fresh `valid` or `invalid` answer from the official service is charged. Local failures, cached answers, outages and unsupported numbers are free.

### Use it to check your own trading partners

VIES exists so businesses can confirm the VAT numbers of the customers and suppliers they trade with. Its terms forbid extracting, retransmitting or copying its content beyond that. Use this Actor to check numbers of businesses you trade with or are about to trade with, and don't republish or resell the answers. It takes up to 500 numbers per run, checks only numbers you supply, and has no search, listing or number-generation mode.

### How do I check VAT and EORI numbers? Quick start

Press **Start** with the prefilled input, or paste this into the **JSON** view of the Input tab:

```json
{
  "vatNumbers": ["IE6388047V", "ATU13585627"],
  "eoriNumbers": ["GB220430231000"]
}
```

In our test run on 30 October 2026 it returned `IE6388047V` valid and `ATU13585627` invalid (VIES), and `GB220430231000` valid (HMRC), in about 4 seconds.

With trader names where published:

```json
{
  "vatNumbers": ["IE6388047V"],
  "includeTraderDetails": true
}
```

Add `"requesterVatNumber"` with **your own** EU VAT number to get a VIES consultation number with each answer.

Weekly monitor of your customers' VAT and EORI numbers:

```json
{
  "vatNumbers": ["IE6388047V", "DE129273398"],
  "eoriNumbers": ["GB220430231000", "XI220430231000"],
  "monitorMode": true,
  "stateStoreName": "customer-numbers"
}
```

### Who it's for

- **Finance, accounts and tax teams** checking the EU VAT numbers of their own customers and suppliers, with the official check date (and a VIES consultation number when you add your own VAT number) as a record of the check.
- **Customs, shipping and logistics teams** confirming the GB, XI or EU EORI numbers of the businesses they trade with.
- **Online shops and B2B platforms** checking the VAT and EORI numbers their own business customers give them, from code or on a schedule.

### Input: which numbers can I check?

Add at least one number to `vatNumbers` or `eoriNumbers`, always with its country prefix.

#### VAT numbers (`vatNumbers`)

EU VAT numbers with their country prefix (`DE…`, `FR…`, `EL…` or `GR…` for Greece, `XI…` for Northern Ireland). GB VAT numbers get a local check only. Spaces, dots and dashes are removed.

#### EORI numbers (`eoriNumbers`)

EORI numbers: `GB…` (HMRC), `XI…` and EU (EOS).

#### Your own VAT number (optional) (`requesterVatNumber`)

Your own EU VAT number. VIES then returns a consultation number with each fresh answer. If VIES rejects it, numbers are still checked without one and a free `requester_rejected` row says so.

#### Include trader name and address (`includeTraderDetails`)

Default `false`. Return the trader name and address where the official service publishes them, unless the name looks like a private person.

#### Cache EORI checks for the day (`useDailyCache`)

Default `true`. Answers EORI numbers already checked today from the cache. VAT numbers are always answered from the cache when already checked today.

#### Monitor mode (`monitorMode`)

Compare each answer with the last run. See *How do I hear when a VAT or EORI number changes?* below.

#### State store name (`stateStoreName`)

Named key-value store for the daily cache and monitor history. Use a different name per list you monitor. See *How do I hear when a VAT or EORI number changes?* below.

#### Maximum numbers per run (`maxNumbers`)

Up to 500 numbers per run (default 500). Extra numbers get a free `too_many_numbers` row.

### Output: what does each row say?

Every row has `rowType`. A **result** row (`result`) has `checkType` (`vat` or `eori`), `input`, `number` (cleaned), `countryCode`, `localCheck` (`pass`, `fail`, `format_only` or `not_checked`), `localCheckNote`, `status`, `valid`, `message`, `checkDate`, `consultationNumber`, `requesterVatNumber`, `traderName`, `traderAddress`, `traderDetailsStatus`, `fromCache`, `source`, `sourceName`, `licence`, `licenceUrl`, `attribution`, `changeType`, `previousStatus` and `checkedAt`. Values shortened:

```json
{
  "rowType": "result",
  "checkType": "vat",
  "input": "IE6388047V",
  "number": "IE6388047V",
  "countryCode": "IE",
  "localCheck": "pass",
  "status": "valid",
  "valid": true,
  "checkDate": "2026-10-30T15:02:39.392Z",
  "consultationNumber": null,
  "traderName": null,
  "traderDetailsStatus": "not_requested",
  "fromCache": false,
  "source": "VIES",
  "licence": "VIES terms of use: for confirming VAT numbers of trading partners …"
}
```

| `status` | Meaning | Charged |
|---|---|---|
| `valid` | The official service says the number is valid on `checkDate` | yes (fresh answers only) |
| `invalid` | The official service says it isn't valid | yes (fresh answers only) |
| `invalid_format` | Wrong format or check digits (local check or VIES); not sent to any service by this Actor if the local check failed | no |
| `not_supported` | GB VAT number (local check-digit result in `message`) or an unsupported country prefix | no |
| `source_unavailable` | The service or the national database didn't answer; says nothing about the number | no |
| `blocked` | VIES won't check this number (`VAT_BLOCKED`) | no |
| `not_checked_budget` | Not checked because the run reached your maximum cost | no |

`localCheck` is `format_only` for some formats that can be personal identity numbers (for example Romanian 13-digit and Latvian personal codes), where only the format is checked locally and VIES gives the answer.

`traderDetailsStatus` is `not_requested`, `not_published` (the service gave no name), `withheld_person_like` (the name doesn't look like a company, so it is not returned) or `included`.

**Status** rows (`status`, free): `duplicates_removed`, `too_many_numbers`, `requester_rejected`, `source_unavailable`, `no_changes` or `budget_reached`, each with a plain-English `message`.

The **SUMMARY** record in the default key-value store lists the input, statuses, request counts, what isn't covered and each source's terms and attribution. The dataset has views for Overview, Monitor: changes, and Status rows.

### How do I hear when a VAT or EORI number changes?

Set `monitorMode` to `true` and schedule a saved task with your list. The Actor remembers each number's last answer in the named key-value store `stateStoreName` (for 400 days). On later runs, `changeType` is `first_check`, `unchanged`, `became_valid`, `became_invalid` or `not_checked` (outage, budget or unsupported number), with `previousStatus`. A run with no change gets a free `no_changes` row. Use the **Monitor: changes** view, or a webhook, to act on changes. Because each VAT number is checked once a day, schedule monitors daily or less often.

### How much does it cost to check a VAT or EORI number?

Pay per event:

| Event | Price |
|---|---|
| Number checked (a fresh valid or invalid answer from the official service) | $0.002 |
| Alert run with changes (monitor mode only, once per run where at least one number changed) | $0.01 |
| Actor start | $0.00005 |

Higher Apify plans get lower prices (shown on the Pricing tab). Local format failures, cached answers, outages, unsupported numbers, status rows and the SUMMARY record are free. Set **Maximum cost per run** in the run options: the Actor stops before going over it, marks unchecked numbers `not_checked_budget` and adds a free `budget_reached` row.

### Data sources, terms and attribution

Every result row from an official service carries its `licence`, `licenceUrl` and `attribution`. Answers are passed on with field names and dates normalised.

| Source | Service | Terms or licence | Attribution (in every row's `attribution`) |
|---|---|---|---|
| VIES | [VIES REST API](https://ec.europa.eu/taxation_customs/vies/) (`check-vat-number`, `check-status`) | [VIES disclaimer](https://ec.europa.eu/taxation_customs/vies/#/disclaimer) and [FAQ](https://ec.europa.eu/taxation_customs/vies/#/faq): for confirming VAT numbers of trading partners (Art. 31, Regulation (EU) No 904/2010); extraction, retransmission and copying of VIES content are forbidden | Source: VIES, European Commission. Answers come from the national VAT databases of the EU member states and Northern Ireland (XI). |
| HMRC EORI | [Check an EORI number API](https://developer.service.hmrc.gov.uk/api-documentation/docs/api/service/check-eori-number-api/1.0) (open access) | [HMRC Developer Hub terms of use](https://developer.service.hmrc.gov.uk/api-documentation/docs/terms-of-use); HMRC states no separate data licence for this API | Source: HMRC Check EORI number API. Trader name and address are shown only when the trader has agreed to HMRC publishing them. |
| EU EOS | [EORI number validation](https://ec.europa.eu/taxation_customs/dds2/eos/eori_validation.jsp) (SOAP service) | [European Commission legal notice](https://commission.europa.eu/legal-notice_en): reuse under CC BY 4.0 unless otherwise indicated (Decision 2011/833/EU) | Source: EORI number validation (EOS), European Commission. Trader name and address are shown only when the trader has agreed to publication. |

Not used: HMRC's Check a UK VAT number API (needs an HMRC developer account).

### Company data, not personal data

Sole traders also have VAT and EORI numbers, and some VAT number formats are personal identity numbers. So:

- Trader names and addresses are off by default (`includeTraderDetails: false`).
- When on, a name is returned only if it contains a company form or organisation word (for example Ltd, GmbH, S.A., Α.Ε., ЕООД). Other names get `withheld_person_like` and are not returned or stored. A partnership named after its partners can still be returned.
- The daily cache and monitor history live in your own key-value store and hold only what the Actor is allowed to return.
- Your input numbers are echoed back in `input` and `number`.

### What are the limits?

- **Coverage:** EU VAT (27 member states and XI) via VIES; GB EORI via HMRC; EU and XI EORI via EOS. GB VAT: local check only. Other countries: `not_supported`.
- **Speed:** VIES is called one number at a time, at most once a second, so allow about 1 second per VAT number (more when VIES is busy and retries). HMRC takes 10 EORI numbers per request at most once a second, EOS 10 per request at most once every 2 seconds.
- **Once a day:** each VAT number is checked with VIES at most once a day per `stateStoreName`; a consultation number is only returned on that day's first check.
- **Up to 500 numbers per run.** Only numbers you supply are checked: no search, listing or number generation.
- **Your own trading partners only:** use it to check the VAT and EORI numbers of businesses you trade with or are about to trade with. Don't republish or resell the results as a database.
- **If VIES blocks requests:** when VIES refuses further requests from a run (`IP_BLOCKED`), the Actor stops calling VIES for the rest of that run; the remaining VAT numbers get a free `source_unavailable` row and a status row says so. Try again later.
- **What valid means:** VIES says whether a number is valid for cross-border trade within the EU on the check date; a domestic-only VAT registration can show as invalid. EORI services say whether the number is a valid EORI number.

### Use the VAT number checker from code, spreadsheets or an AI agent

Run it with the Apify API or client libraries, schedule it, or connect it to Make, Zapier, Google Sheets or webhooks through Apify integrations. AI agents can call it through Apify's MCP server.

The examples below check two VAT numbers and set a maximum cost of $0.05 for the run, so trying them costs a few cents at most. Read your API token from an environment variable (`APIFY_TOKEN`) rather than pasting it into code.

#### JavaScript (Node.js)

```js
// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yourevenings/eu-uk-vat-eori-checker').call(
  {
    "vatNumbers": [
      "IE6388047V",
      "ATU13585627"
    ]
  },
  { maxTotalChargeUsd: 0.05 },
);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
## pip install "apify-client>=3"
import os
from decimal import Decimal
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yourevenings/eu-uk-vat-eori-checker").call(
    run_input={
        "vatNumbers": [
            "IE6388047V",
            "ATU13585627"
        ]
    },
    max_total_charge_usd=Decimal("0.05"),
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

#### HTTP API (cURL)

```bash
curl -X POST "https://api.apify.com/v2/acts/yourevenings~eu-uk-vat-eori-checker/run-sync-get-dataset-items?maxTotalChargeUsd=0.05" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"vatNumbers": ["IE6388047V", "ATU13585627"]}'
```

#### AI agents (MCP)

Add Apify's MCP server with just this Actor as a tool. On first connection your browser opens so you can sign in to Apify and approve access.

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=yourevenings/eu-uk-vat-eori-checker"
    }
  }
}
```

### FAQ

**Why is a number `source_unavailable` and not `invalid`?** The service, or that country's national VAT database, didn't answer or was busy. That says nothing about the number. You're not charged; run it again later.

**Why didn't a second run today ask VIES again?** VIES asks that the same number isn't checked several times a day, so each VAT number is checked once a day and later runs that day get the cached answer, free, with `fromCache: true`.

**Why are GB VAT numbers not checked?** HMRC's VAT number API needs an HMRC developer account, which this Actor doesn't use. You get the local check-digit result.

**Why is the trader name empty?** Either you didn't turn on `includeTraderDetails`, the service didn't publish one (many countries and traders don't), or the name looked like a private person's (`withheld_person_like`).

**Can I check EORI numbers only?** Yes. Leave `vatNumbers` empty and list GB, XI or EU EORI numbers in `eoriNumbers`.

**How do I get a consultation number?** Put your own EU VAT number in `requesterVatNumber`. VIES returns a consultation number on the first check of a number each day.

### Feedback

Found a problem or need a feature? Open an issue on the Issues tab.

# Changelog

This Actor's version history is a separate document: https://apify.com/yourevenings/eu-uk-vat-eori-checker/changelog.md

# Actor input Schema

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

EU and Northern Ireland (XI) VAT numbers of your customers or suppliers, with the country prefix (for example IE6388047V, DE123456789, XI123456789). Greek numbers may start EL or GR. GB numbers get a local check-digit result only. Up to 500 numbers per run, VAT and EORI together.

## `eoriNumbers` (type: `array`):

GB EORI numbers (checked with HMRC) and EU or XI EORI numbers (checked with the European Commission's EOS service), with the country prefix.

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

Your EU or XI VAT number. When set, VIES returns a consultation number for each valid answer: your proof that you checked the number on that date.

## `includeTraderDetails` (type: `boolean`):

Off by default. When on, the official name and address are returned only when the name is clearly an organisation (it contains a legal form such as Ltd, GmbH or SA). Names that may belong to a private person are withheld.

## `useDailyCache` (type: `boolean`):

EORI numbers already checked today are answered from the cache (free, marked fromCache). VAT numbers are always answered from the cache when checked today, whatever this setting, because VIES asks that a number is not checked several times a day.

## `monitorMode` (type: `boolean`):

Compare each answer with the last run and mark it first_check, unchanged, became_valid or became_invalid. Outages never count as a change.

## `stateStoreName` (type: `string`):

Named key-value store for the daily cache and monitor history. Use a different name per list you monitor.

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

Numbers after this are skipped (a free status row says so). VIES answers about one number a second, so raise the run timeout for long lists.

## Actor input object example

```json
{
  "vatNumbers": [
    "IE6388047V",
    "ATU13585627"
  ],
  "eoriNumbers": [
    "GB220430231000"
  ],
  "includeTraderDetails": false,
  "useDailyCache": true,
  "monitorMode": false,
  "stateStoreName": "vat-eori-checker-state",
  "maxNumbers": 500
}
```

# Actor output Schema

## `overview` (type: `string`):

Overview view of the dataset.

## `changes` (type: `string`):

Monitor: changes view of the dataset.

## `status` (type: `string`):

Status rows (free) view of the dataset.

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

SUMMARY record: input, counts per status, charged checks, request counts and timings, and each source's terms and attribution.

# 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": [
        "IE6388047V",
        "ATU13585627"
    ],
    "eoriNumbers": [
        "GB220430231000"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("yourevenings/eu-uk-vat-eori-checker").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": [
        "IE6388047V",
        "ATU13585627",
    ],
    "eoriNumbers": ["GB220430231000"],
}

# Run the Actor and wait for it to finish
run = client.actor("yourevenings/eu-uk-vat-eori-checker").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": [
    "IE6388047V",
    "ATU13585627"
  ],
  "eoriNumbers": [
    "GB220430231000"
  ]
}' |
apify call yourevenings/eu-uk-vat-eori-checker --silent --output-dataset

```

## MCP server setup

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

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/kQQVFF7kktTdvMl3z/builds/Gv8tuSfm8JO0j7yl7/openapi.json
