# EU VAT Number Validator (VIES) & LEI Lookup: Bulk Company Check (`latamdatatools/eu-vat-lei-validator`) Actor

Validate EU VAT numbers in bulk with the official VIES service and look up LEIs in the official GLEIF database: valid or not, registered company name and address, LEI status, renewal date and parent companies. Unavailable answers are retried and never charged.

- **URL**: https://apify.com/latamdatatools/eu-vat-lei-validator.md
- **Developed by:** [Julian Genuario](https://apify.com/latamdatatools) (community)
- **Categories:** Business, Developer tools, E-commerce
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 vat or lei 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) & LEI Lookup: Bulk Company Check

Check thousands of **EU VAT numbers** against the official **VIES** service of the European Commission and look up **LEIs** (Legal Entity Identifiers) in the official **GLEIF** database, in one run:

- **VAT numbers**: valid or not, **registered company name and address** (when the member state publishes them), the VIES answer code and, if you add your own VAT number, a **VIES consultation number** you can keep as proof of the check
- **LEIs**: legal name, other names, legal and headquarters address, jurisdiction, legal form, business-register ID, entity status (ACTIVE / INACTIVE), **LEI registration status (ISSUED / LAPSED / RETIRED...)**, next renewal date, managing LOU, BIC codes, and the **direct and ultimate parent company**
- Optional: find the **LEI of a VAT-registered company** (exact legal-name match in the same country)
- VAT numbers and LEIs can be mixed in the same list: each value is recognised automatically (country prefix, format rules per country, LEI check digits)

Only official, public APIs are used (VIES REST API and GLEIF API). No scraping, no API keys.

### What does EU VAT Number Validator do?

EU VAT Number Validator checks VAT numbers in bulk against the European Commission's official VIES service and looks up Legal Entity Identifiers (LEI) in the official GLEIF database: valid or not, registered company name and address, LEI status, renewal date and parent companies. Use it for KYB, invoicing and B2B checkout VAT checks.

### How to use EU VAT Number Validator

1. Click **Try for free** on this page (a free Apify account is enough to start).
2. Fill in the input (see the examples below) or keep the prefilled example.
3. Click **Start** and wait for the run to finish.
4. Download the results from the **Output** tab as JSON, CSV, Excel or HTML, or read them with the Apify API.
5. Optional: create a **Schedule** to run it daily or weekly, and connect a webhook or an integration (Make, Zapier, n8n, Slack).

### Use cases

- **Invoicing and e-commerce**: validate the VAT number of B2B customers before applying the EU reverse charge (0 % VAT), and keep the VIES consultation number as evidence
- **KYB / onboarding / compliance**: confirm a supplier or customer exists, get its registered name and address, its LEI status and who owns it
- **Data cleaning**: fix and normalise VAT columns in an ERP or CRM export (spaces, dots, GR instead of EL, Austrian numbers without the U)
- **Finance and reporting**: check that LEIs of counterparties are still ISSUED (not LAPSED) before regulatory reporting (EMIR, MiFIR, SFTR)

### Input

```json
{
  "identifiers": ["IE6388047V", "FR 40 303 265 045", "DE811569869", "506700GE1G29325QX363"],
  "includeParents": true,
  "findLeiForVat": false,
  "requesterVatNumber": ""
}
```

You can also read the values from an **Apify dataset** (e.g. the output of another Actor) or a **CSV file / Google Sheet** by URL: set **Field** to the column that holds the VAT number or LEI, and **Fields to keep** to copy columns such as a customer ID into the output.

### Output (one row per VAT number or LEI)

```json
{
  "input": "IE6388047V",
  "type": "vat",
  "status": "valid",
  "isValid": true,
  "countryCode": "IE",
  "vatNumber": "IE6388047V",
  "lei": null,
  "name": "GOOGLE IRELAND LIMITED",
  "address": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4",
  "viesCode": "VALID",
  "consultationNumber": null,
  "requestDate": "2026-10-26T22:00:07.665Z",
  "matchedLei": null,
  "error": null
}
```

```json
{
  "input": "YYPPRNO5HB304LHFVG31",
  "type": "lei",
  "status": "found",
  "isValid": true,
  "countryCode": "IE",
  "lei": "YYPPRNO5HB304LHFVG31",
  "name": "GOOGLE IRELAND LIMITED",
  "address": "GORDON HOUSE, BARROW STREET, D04 E5W5 DUBLIN 4, IE",
  "jurisdiction": "IE",
  "entityStatus": "ACTIVE",
  "registrationStatus": "ISSUED",
  "nextRenewalDate": "2027-...",
  "directParent": { "lei": "549300Y7W34DK0WBPY51", "name": "GOOGLE INTERNATIONAL LLC", "country": "US" },
  "ultimateParent": { "lei": "5493006MHB84DD0ZWV18", "name": "ALPHABET INC.", "country": "US" }
}
```

Every row has the same keys (fields that do not apply are `null`). **Status** values:

| status | meaning | charged |
|---|---|---|
| `valid` / `invalid` | VIES answered: the VAT number is (not) active for intra-EU trade | yes |
| `found` / `not_found` | the LEI exists (or not) in GLEIF; for found LEIs `isValid` = registration ISSUED | yes |
| `invalid_format` | wrong format or wrong LEI check digits (no lookup needed) | no |
| `unsupported_country` | not in VIES (UK since 2021 except XI, Switzerland, Norway) | no |
| `service_unavailable` | the country's VAT system or GLEIF did not answer after retries | no |

A `RUN_SUMMARY` record in the key-value store has counts per status and per country.

### Pricing

Pay per event: **USD 0.002 per check** (USD 2 per 1,000) with a definitive answer (valid, invalid, found, not found). Format errors, unsupported countries, duplicates and unavailable services are **free**. Your "max charge per run" is respected: the Actor never checks more than you are willing to pay for.

### Reliability: how VIES outages are handled

VIES is a gateway to 27 national systems that are sometimes down or overloaded (Germany often answers `MS_UNAVAILABLE` for some minutes). The Actor:

1. reads the VIES status page at the start and tells you which countries are down;
2. checks numbers of the same country **one at a time, at least 1 second apart** (VIES rejects bursts with `MS_MAX_CONCURRENT_REQ`);
3. retries "try later" answers with growing waits (5, 15, 30, 60 s);
4. retries what is still unavailable once more at the end of the run;
5. returns anything still unanswered as `service_unavailable`, **not charged**, so you can re-run just those.

GLEIF is queried with batches of up to 200 LEIs per call and stays under its limit of 60 calls per minute.

### Notes and limits

- Some member states do not publish the name or address of a valid VAT number (e.g. Germany and Spain): the number is still validated, `name`/`address` stay `null`.
- VIES confirms that a VAT number is registered for intra-EU transactions; it is not a full company report. Sole traders registered for VAT appear with the name the tax authority publishes.
- UK (GB) numbers are not in VIES since Brexit; Northern Ireland businesses use the XI prefix and are supported.
- Data: VIES (European Commission) and GLEIF (Global LEI data, CC0). This Actor is not affiliated with the European Commission or GLEIF.

### Cost examples

Prices at the current pay-per-event rate: USD 2.00 per 1,000 VAT numbers or LEIs with a definitive answer (bad formats, unsupported countries, duplicates and VIES outages are free). You can set a maximum charge per run in the run options.

| Job | Approximate cost |
|---|---|
| Test run: the 3 example identifiers (measured: 8 s) | about $0.006 |
| 500 supplier VAT numbers before an invoice run | about $1.00 |
| 10,000 customer records (VAT and LEI mixed) | about $20.00 |

### Use it from your code, an integration or an AI agent

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("latamdatatools/eu-vat-lei-validator").call(run_input={
  "identifiers": [
    "IE6388047V",
    "506700GE1G29325QX363",
    "NL123456789B01"
  ],
  "includeParents": True
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["input"], item["status"], item["name"])
```

**JavaScript / Node.js** (`npm install apify-client`):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('latamdatatools/eu-vat-lei-validator').call({
  identifiers: [
    'IE6388047V',
    '506700GE1G29325QX363',
    'NL123456789B01'
  ],
  includeParents: true
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((i) => [i.input, i.status, i.name]));
```

**No code:**

- **Schedules:** save your input as a Task and run it daily or weekly from Apify Console (Schedules).
- **Integrations:** send the results to Google Sheets, Slack, email, Make, Zapier, n8n or Airbyte from the Integrations tab, or call your own webhook when a run finishes.
- **AI agents:** add it as a tool in Claude, Cursor, VS Code and other MCP clients through the Apify MCP server (`https://mcp.apify.com`), so the agent can check a VAT number or LEI while it works on an order or a supplier.

### FAQ

**Can I call it from my own code or from an AI agent?** Yes. Start runs and fetch results with the Apify API or the JavaScript / Python clients, or use it as a tool from Claude, Cursor and other MCP clients through the Apify MCP server (`mcp.apify.com`).

**Can I run it automatically?** Yes. Create a Schedule in Apify Console (for example every morning) and add a webhook or an integration to get the results where you need them.

**Which export formats are available?** JSON, JSONL, CSV, Excel (XLSX), XML, RSS and HTML table, from the Output tab or the API.

**What does it cost?** See the Pricing section above. You only pay for the events listed there.

# Actor input Schema

## `identifiers` (type: `array`):

One per line. EU VAT numbers with their country prefix (DE811569869, FR 40 303 265 045, ATU12345678, EL/GR, XI for Northern Ireland) and 20-character LEIs (506700GE1G29325QX363) can be mixed: each value is detected automatically. Spaces, dots and dashes are ignored.

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

Optional two-letter VIES code (DE, FR, ES, IT, NL, EL...) used when a VAT number has no country prefix.

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

Optional: check the VAT numbers / LEIs stored in an Apify dataset. Use "Field" to say which field holds them.

## `csvUrl` (type: `string`):

Optional: a public URL of a CSV file with a header row (comma, semicolon, tab or | separated, up to 50 MB). Google Sheets links work if shared as "Anyone with the link".

## `identifierField` (type: `string`):

Field / CSV column that holds the VAT number or LEI, e.g. vat, vatNumber, lei, company.vat (dot notation for nested fields).

## `keepFields` (type: `array`):

Optional: copy these fields of each dataset record / CSV row into the output (under "source"), e.g. customerId, name.

## `includeParents` (type: `boolean`):

For each LEI, read the direct and ultimate parent company reported to GLEIF (2 extra calls per LEI; GLEIF allows 60 calls per minute, so about 25 LEIs per minute with parents).

## `findLeiForVat` (type: `boolean`):

For valid VAT numbers whose name VIES returns, look for an active LEI with exactly the same legal name in the same country ("matchedLei"). Left empty when there is no exact, single match.

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

Optional: your company's VAT number. VIES then returns a consultation number ("consultationNumber") for each valid check, which you can keep as proof that you verified your customer's VAT number on that date.

## `maxConcurrency` (type: `integer`):

Numbers of different countries are checked in parallel; numbers of the same country always go one at a time, at least 1 second apart, as VIES expects.

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

VIES depends on each country's own system, which is sometimes down or busy (MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ). The Actor waits 5, 15, 30, 60 s between retries.

## `retryUnavailableAtEnd` (type: `boolean`):

Numbers that are still unavailable are retried one last time after the rest of the list (30 s later). Still unavailable = "service_unavailable", not charged.

## `maxItems` (type: `integer`):

Upper limit of VAT numbers + LEIs checked in one run. 0 = no limit (up to 50,000). Your max charge per run is respected too.

## Actor input object example

```json
{
  "identifiers": [
    "IE6388047V",
    "506700GE1G29325QX363",
    "NL123456789B01"
  ],
  "identifierField": "vat",
  "includeParents": true,
  "findLeiForVat": false,
  "maxConcurrency": 3,
  "maxRetries": 3,
  "retryUnavailableAtEnd": true,
  "maxItems": 0
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "identifiers": [
        "IE6388047V",
        "506700GE1G29325QX363",
        "NL123456789B01"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("latamdatatools/eu-vat-lei-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 = { "identifiers": [
        "IE6388047V",
        "506700GE1G29325QX363",
        "NL123456789B01",
    ] }

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

```

## MCP server setup

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