# EORI Number Validator: Bulk EU & UK Customs Check (`swillz/eori-validator`) Actor

Bulk-validate EORI customs numbers against the official EU EOS service and UK HMRC: valid/invalid, trader name and address where published, and a name match. Bad formats and outages are free. From $1.50 per 1k.

- **URL**: https://apify.com/swillz/eori-validator.md
- **Developed by:** [William Jin](https://apify.com/swillz) (community)
- **Categories:** Business, 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 eori 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

## EORI Number Validator: Bulk EU & UK Customs Check

Check thousands of **EORI** (Economic Operators Registration and Identification) numbers against the official sources: the European Commission's **EOS** validation service for EU and Northern Ireland (`XI`) numbers, and **HMRC** for UK (`GB`) numbers. For each number you get valid or invalid, the trader's name and address where the trader has agreed to publish them, and an optional **name match** against your own records.

Built for customs brokers, freight forwarders, e-commerce sellers shipping cross-border, and compliance teams onboarding importers or exporters.

### What can EORI Number Validator do?

- **EU and UK in one run.** GB numbers are routed to HMRC automatically; EU member-state and XI numbers to the EU EOS service. Both are queried in batches of 10, the maximum each service allows.
- **Forgiving input.** `gb 117 223 643 000`, `EORI No: DE1234567`, `EL…` (converted to `GR`) and numbers without a prefix (with `defaultCountry`) all work.
- **Free local format check.** Numbers that can't be valid (for example a GB number that isn't 12 digits) are returned as free `invalid_format` rows. Non-EORI countries such as CH or US return free `unsupported_country` rows.
- **Handles outages.** Retries with backoff, then returns free `service_unavailable` rows instead of failing the run.
- **Name match.** Add ` | Expected name` to a number, or set `nameField` for a dataset, to get `exact`, `close`, `partial` or `mismatch`.

### What data does it return?

| Field | Example |
|---|---|
| `eori`, `status`, `valid` | `GB117223643000`, `valid`, `true` |
| `name`, `address` | `APPLE DISTRIBUTION INTERNATIONAL LIMITED`, `HM REVENUE AND CUSTOMS, AB10 1ZP, ABERDEEN, GB` |
| `street`, `postalCode`, `city` | split address fields when published |
| `countryCode`, `countryName` | `GB`, `United Kingdom` |
| `expectedName`, `nameMatch`, `namePublished` | `Apple Distribution International`, `exact`, `true` |
| `source`, `requestDate`, `checkedAt` | `HMRC (UK)`, … |

**Statuses:**

- Charged: `valid`, and `invalid` (not registered, or expired).
- Free: `invalid_format`, `unsupported_country`, `service_unavailable`, `invalid_input`, `error` and `skipped_charge_limit`.

Most traders do not consent to publishing their name and address. In that case `name` is `null`, `namePublished` is `false` and `nameMatch` is `not_available`, but `valid` is still authoritative.

### How much does it cost?

You pay only for numbers the official service actually answered (`valid` or `invalid`):

| Plan | Per 1,000 numbers |
|---|---|
| Free | $3.00 |
| Bronze | $2.50 |
| Silver | $2.00 |
| Gold | $1.50 |

Format errors, unsupported countries and outages are **free**. There is also a tiny Apify start fee of $0.00005 per run.

### Input example

```json
{
  "eoriNumbers": ["GB117223643000 | Apple Distribution International", "BE0403448140", "XI220430231000"]
}
```

### Output example

```json
{"eori": "GB117223643000", "status": "valid", "valid": true, "name": "APPLE DISTRIBUTION INTERNATIONAL LIMITED",
 "address": "HM REVENUE AND CUSTOMS, AB10 1ZP, ABERDEEN, GB", "countryCode": "GB", "expectedName": "Apple Distribution International",
 "nameMatch": "exact", "namePublished": true, "source": "HMRC (UK)"}
```

```json
{"eori": "GB123", "status": "invalid_format", "valid": false, "error": "GB EORI numbers are GB + 12 digits (usually the 9-digit VAT number + 000). Not sent."}
```

### Use cases

- **Customs declarations:** confirm the importer's or exporter's EORI before filing.
- **Freight and logistics onboarding:** validate a shipper or consignee list and flag name mismatches.
- **Marketplaces and e-commerce:** check B2B buyers' and sellers' EORI numbers in bulk.
- **Periodic re-checks:** schedule the Actor monthly to catch EORIs that have been revoked.

### Use with AI agents (MCP, ChatGPT, Claude, Cursor, n8n)

AI agents can run this Actor through the [Apify MCP server](https://mcp.apify.com):

```json
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=swillz/eori-validator"}}}
```

Or run it locally with `npx -y @apify/actors-mcp-server --tools swillz/eori-validator` and `APIFY_TOKEN` set.

Example prompts:

- "Is GB117223643000 a valid EORI number, and who is it registered to?"
- "Validate the EORI numbers in this consignee list."

Minimal input: `{"eoriNumbers": ["GB117223643000"]}`. To cap the cost, pass `maxTotalChargeUsd`. Numbers left unchecked come back as free `skipped_charge_limit` rows.

### Integrations and API

Run it from the Apify API, the clients, Make, Zapier or n8n. To chain it, pass `{"datasetId": "...", "eoriField": "eori"}`. The OUTPUT record holds a run summary (`byStatus`, `zeroResultsReason`, `nextSteps`).

### FAQ

**Is this the official source?** Yes. Every answer comes live from the European Commission's EOS validation service or HMRC's public EORI API. Nothing is cached.

**Why is there no name for a valid number?** The trader has not consented to publication. The validity result is still official.

**Is an EORI the same as a VAT number?** No, but in many countries it is derived from it (for example GB + VAT number + 000). To check VAT numbers, use the EU VAT Number Validator below.

### Related tools

More tools from the same developer, built to work together:

- [Career Site Jobs Scraper](https://apify.com/swillz/career-site-jobs-scraper): jobs from Greenhouse, Lever, Ashby, Workable and Recruitee boards, with salary fields, as a jobs API or CSV.
- [Workday Jobs Scraper](https://apify.com/swillz/workday-jobs-scraper): every job from any myworkdayjobs.com career site, past the 2,000-result cap.
- [Company Website Enrichment](https://apify.com/swillz/company-website-enrichment): turn a list of domains into company name, emails, phones, social links and tech stack.
- [AI Extract](https://apify.com/swillz/ai-extract): structured JSON from any web page with a plain-English prompt or a JSON schema. AI included.
- [Google Sheets Import & Export](https://apify.com/swillz/google-sheets-import-export): send any Apify dataset to a Google Sheet (append, replace or dedupe) or read a sheet as JSON.
- [XML Sitemap URL Extractor & Sitemap to CSV](https://apify.com/swillz/sitemap-url-extractor): every URL from a website's sitemap, with lastmod, HTTP status and new-page monitoring.
- [AI Brand Visibility Tracker](https://apify.com/swillz/ai-brand-visibility-tracker): track whether ChatGPT mentions, ranks and cites your brand vs competitors (GEO).
- [Email Provider Detector](https://apify.com/swillz/email-provider-detector): bulk check whether domains use Google Workspace, Microsoft 365, Proofpoint or Mimecast, plus SPF, DMARC and DKIM.
- [Hiring Signals by Company Domain](https://apify.com/swillz/hiring-signals-by-domain): from a list of company domains, find which ATS each uses and how many open roles, by department and location.
- [EU VAT Number Validator (VIES)](https://apify.com/swillz/eu-vat-validator): bulk check EU VAT numbers against official VIES, with company name and address.
- [LEI Lookup (GLEIF)](https://apify.com/swillz/lei-lookup): find a company's Legal Entity Identifier, legal name, address, status and parent from official GLEIF data.
- [Sanctions Screener](https://apify.com/swillz/sanctions-screener): screen company and person names against official OFAC, UN, EU and UK sanctions lists with fuzzy matching.

**Popular workflows**

- **B2B customer onboarding (KYB):** validate the VAT number with [EU VAT Number Validator (VIES)](https://apify.com/swillz/eu-vat-validator) and the EORI with this Actor, confirm the legal entity with [LEI Lookup (GLEIF)](https://apify.com/swillz/lei-lookup), and screen the name with [Sanctions Screener](https://apify.com/swillz/sanctions-screener).

Source code: https://github.com/williamjin02/apify-actors/tree/main/actors/eori-validator

# Actor input Schema

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

Required unless datasetId is set. Strings with the country prefix, e.g. \["GB117223643000","BE0403448140","XI220430231000"]. Spaces and dashes are fine. Add " | Expected name" to compare names, e.g. "GB117223643000 | Apple Distribution International". GB goes to HMRC; EU and XI to the EU EOS service.

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

Optional 2-letter code (e.g. "DE" or "GB") used for numbers without a country prefix.

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

Check at most this many unique numbers per run (default 5000). Aliases: maxItems, limit, maxResults.

## `datasetId` (type: `string`):

Optional. Read EORI numbers from another run's dataset, e.g. a supplier export. In an integration the triggering run's dataset is used automatically.

## `eoriField` (type: `string`):

Field holding the EORI (dot paths work). Leave empty to auto-detect: eori, eoriNumber, EORI, eori_number, eoriNo, customsId.

## `nameField` (type: `string`):

Optional field compared with the official trader name (nameMatch). Leave empty to auto-detect: companyName, name, company, legalName, traderName.

## `datasetMaxItems` (type: `integer`):

Read at most this many values from the dataset (default 1000).

## `maxRetries` (type: `integer`):

Retries per batch of 10 when a service is busy or offline (0-6, default 3).

## `requestTimeoutSecs` (type: `integer`):

Timeout per request (5-90, default 30).

## Actor input object example

```json
{
  "eoriNumbers": [
    "GB117223643000 | Apple Distribution International",
    "BE0403448140",
    "IT00743110157",
    "XI220430231000"
  ],
  "defaultCountry": "",
  "maxNumbers": 5000,
  "datasetMaxItems": 1000,
  "maxRetries": 3,
  "requestTimeoutSecs": 30
}
```

# Actor output Schema

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

One row per number. Example: {"eori":"GB117223643000","status":"valid","valid":true,"name":"APPLE DISTRIBUTION INTERNATIONAL LIMITED"}. Failed: {"eori":"GB123","status":"invalid_format","error":"..."}.

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

JSON: numbersRequested, uniqueChecked, valid, invalid, byStatus, chargeLimitReached, zeroResultsReason, nextSteps.

# 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 = {
    "eoriNumbers": [
        "GB117223643000 | Apple Distribution International",
        "BE0403448140",
        "IT00743110157",
        "XI220430231000"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("swillz/eori-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 = { "eoriNumbers": [
        "GB117223643000 | Apple Distribution International",
        "BE0403448140",
        "IT00743110157",
        "XI220430231000",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("swillz/eori-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 '{
  "eoriNumbers": [
    "GB117223643000 | Apple Distribution International",
    "BE0403448140",
    "IT00743110157",
    "XI220430231000"
  ]
}' |
apify call swillz/eori-validator --silent --output-dataset

```

## MCP server setup

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