# Bulk EU VAT Number Checker — Official VIES (`comall-agency/eu-vat-checker`) Actor

Confirm an EU VAT number against the European Commission's own VIES service, after a per-country format check. Returns the registered name and address when the member state publishes them. Never charged when VIES is unreachable: that verdict means try again later, not invalid.

- **URL**: https://apify.com/comall-agency/eu-vat-checker.md
- **Developed by:** [Comall Agency](https://apify.com/comall-agency) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 vat 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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Checker — Official VIES Lookup

Confirm that an EU VAT number is really registered, against the European
Commission's own [VIES](https://ec.europa.eu/taxation_customs/vies/)
service — the official public endpoint that tax authorities themselves
rely on. No scraping, no login, no third-party API key, no account to
create.

### Duplicates are checked once and charged once

The same VAT number repeated in a batch is sent to VIES **once**. Every
submitted line still gets its own output row, in your original order and
**spelled the way you wrote it**, so the result joins straight back onto your
list — the repeat carries `is_duplicate: true` and **is not charged**.

Matching is done on the number, not on the formatting: `FR 552 032 534`,
`fr552032534` and `FR-552-032-534` are one number and are charged once.

This is not only about the invoice. VIES is a shared public service that
starts refusing requests under load; asking it twice for an answer already in
hand makes that worse for everyone — including for the next number in your
own list.

**A number whose VIES check did not go through is not cached.** If the
registry was unreachable, a repeat gets a genuine retry instead of inheriting
our outage — and, as always, an unanswered check is not charged.

### What it does

Each number goes through two stages:

1. **Local format check** — the two-letter country code is recognised and
   the rest of the number matches the length and character class that
   member state uses. This stage is deliberately permissive: it rejects
   only what clearly cannot belong to any supported country, because VIES
   is the only real source of truth.
2. **Official VIES lookup** — a direct call to the Commission's REST
   endpoint, which answers whether the number is currently registered for
   intra-EU trade, and returns the trader's name and address when that
   member state chooses to publish them.

### Use cases

- **Invoicing and reverse charge** — before you issue a zero-rated
  intra-EU invoice, confirm your customer's VAT number is genuinely
  registered. Getting this wrong is your liability, not theirs.
- **Customer onboarding** — validate the VAT number a B2B customer typed
  into a signup form, instead of discovering the problem at audit time.
- **Periodic re-checks of a customer base** — VAT registrations get
  cancelled. Re-run your list and see which numbers stopped being valid.
- **ERP and CRM data cleanup** — bulk-check a column of VAT numbers
  exported from an existing system.

### Input

```json
{ "vatNumbers": ["DE811569869", "FR32350477372", "FR00000000000"] }
```

Each number starts with its two-letter country code. Greece uses `EL`
(not `GR`) and Northern Ireland uses `XI` — that is VIES's own
convention, not ours. Spaces, dots and hyphens are ignored.

### Output (one row per VAT number)

```json
{
  "vat_id": "DE811569869",
  "country_code": "DE",
  "checked_at": "2026-08-28T17:00:00.000Z",
  "verdict": "valid",
  "valid": true,
  "registered_name": null,
  "registered_address": null
}
```

`registered_name` and `registered_address` are populated only when VIES
returns them for that country. Several member states never return trader
details even for a perfectly valid number — VIES marks those fields
`"---"`, which is surfaced here as `null` rather than as a fake empty
string.

### Pricing, and when you are not charged

Pay-per-event: **$0.004 per VAT number checked**, charged once a number
receives a definitive answer — `valid`, `invalid`, `invalid_format` or
`invalid_country_code`.

**You are never charged for `verification_unavailable`.** When VIES times
out or is down for a member state, that is our problem to absorb, not a
result you asked for. This is enforced in the code, not just promised
here: the charge call is skipped on that branch.

### Limitations — read this before you buy

- Coverage is the 27 EU member states plus Northern Ireland (`XI`) —
  exactly the countries VIES itself supports. Non-EU VAT and GST numbers
  are out of scope.
- VIES regularly takes an individual member state's service offline for
  maintenance. A `verification_unavailable` verdict means **try again
  later**, not that the number is invalid. Treating it as invalid would
  be the single most damaging mistake a VAT checker can make, so it is
  reported as its own distinct verdict.
- This confirms VAT registration validity only. It says nothing about the
  company's trading status, solvency or creditworthiness.
- The local format stage is not a checksum. It will not reject a
  well-shaped number that was never issued — VIES will.

### FAQ

**Why did a number that works on the VIES website come back invalid here?**
Check the country prefix first: `EL` for Greece, `XI` for Northern
Ireland. Those two trip up most integrations.

**Is there a rate limit?**
VIES applies its own concurrency limits and can return a busy signal
under load. That surfaces here as `verification_unavailable` — unbilled —
rather than as a wrong answer.

### Related Actors

Part of the same family of small, single-purpose checkers on this account —
each does one thing, priced per item checked:

- [IBAN Validator & Formatter](https://apify.com/comall-agency/iban-validator-formatter) — ISO 13616 length + mod-97 checksum, fully offline.
- [Card Number Validator (Luhn)](https://apify.com/comall-agency/card-number-validator) — Luhn checksum and card-network detection, output is masked.
- [Barcode Check-Digit Validator](https://apify.com/comall-agency/barcode-checkdigit-validator) — EAN-13, EAN-8 and UPC-A check digits.
- [Email Address Validator](https://apify.com/comall-agency/email-address-validator) — syntax, domain and MX checks.
- [Password Strength Checker](https://apify.com/comall-agency/password-strength-checker) — entropy scoring, never returns the password.
- [Cron Expression Validator](https://apify.com/comall-agency/cron-expression-tool) — plain-English description and next run times.
- [French E-Invoice Partner Resolver](https://apify.com/comall-agency/fr-einvoice-partner-resolver) — SIRET / SIREN / VAT resolution.

# Actor input Schema

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

VAT numbers to check, each starting with the 2-letter country code (e.g. DE811569869, FR32350477372). Spaces, dots and hyphens are ignored.

## Actor input object example

```json
{
  "vatNumbers": [
    "DE811569869",
    "FR00000000000",
    "DE 811 569 869"
  ]
}
```

# Actor output Schema

## `results` (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 = {
    "vatNumbers": [
        "DE811569869",
        "FR00000000000",
        "DE 811 569 869"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("comall-agency/eu-vat-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": [
        "DE811569869",
        "FR00000000000",
        "DE 811 569 869",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("comall-agency/eu-vat-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": [
    "DE811569869",
    "FR00000000000",
    "DE 811 569 869"
  ]
}' |
apify call comall-agency/eu-vat-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,comall-agency/eu-vat-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/5OzWKmG1FJqHD1fSR/builds/xH1iV4p2Qq1I2zb6N/openapi.json
