# EU Company Data Extractor – domain to company + VIES (`etse/eu-company-data-extractor`) Actor

Turn any European company website into a structured record: legal name, legal form, address, registration number (HRB, SIREN, KvK, Companies House, P.IVA, CIF, CVR…), VAT ID validated via EU VIES, representatives, contacts and social links. EU, UK, CH. One record per domain.

- **URL**: https://apify.com/etse/eu-company-data-extractor.md
- **Developed by:** [Este Lab](https://apify.com/etse) (community)
- **Categories:** Lead generation, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$6.00 / 1,000 company records

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 Company Data Extractor – domain to company record (+ VIES VAT check)

**Run it on Apify: https://apify.com/etse/eu-company-data-extractor** · Source: MIT, https://github.com/Estefanolabudda/eu-company-data-extractor

Give it a list of company websites from anywhere in the **EU, UK or Switzerland** and get back **one clean, structured company record per domain**: legal name, legal form, address, company registration number, VAT ID validated live against EU VIES, representatives, contact data, share capital, hosting provider and the company's social profiles.

It reads the page every European business has to publish anyway: the *Impressum* (DE/AT/CH), *Mentions légales* (FR/BE/LU), *Colofon* (NL), *Legal notice / Company information* (UK/IE), *Note legali* (IT), *Aviso legal* (ES), plus terms and privacy pages as a fallback, and turns the free text into fields for your CRM, KYB workflow or AI agent.

### Countries and identifiers

| Country | Registration number | VAT ID |
|---|---|---|
| Germany | HRB / HRA + Registergericht | DE… |
| Austria | FN (Firmenbuch) | ATU… |
| Switzerland | CH-… UID register | CHE-… MWST (not in VIES) |
| France | SIREN / SIRET, RCS city | FR… |
| Netherlands | KvK number | NL…B01 |
| Belgium | KBO/BCE enterprise number | BE0… |
| Luxembourg | RCS Luxembourg B… | LU… |
| United Kingdom | Companies House number | GB… (not in VIES) |
| Ireland | CRO number | IE… |
| Italy | Partita IVA, REA | IT… |
| Spain | CIF / NIF, Registro Mercantil | ES… |
| Portugal | NIPC / NIF | PT… |
| Denmark | CVR | DK… |
| Sweden / Norway | Organisationsnummer | SE… |
| Poland | KRS, NIP | PL… |
| Czechia, Hungary, Finland | IČO, Cégjegyzékszám, Y-tunnus | CZ…, HU…, FI… |
| Other EU | generic "registration number" + any EU VAT format | all EU formats |

### What you get

| Field | Example |
|---|---|
| `companyName`, `legalForm` | `Lumière Digitale SAS`, `SAS` |
| `street`, `postalCode`, `city`, `country` | `12 rue de la Paix`, `75002`, `Paris`, `FR` |
| `registerType`, `registerNumber`, `registerCourt` | `SIRET`, `81234567800012`, `RCS Paris` |
| `vatId` + `vies` | `FR12812345678` → `{ valid: true, name: "...", address: "..." }` |
| `representatives[]`, `responsiblePerson` | `["Marie Dupont"]` |
| `email`, `phone`, `fax`, `supervisoryAuthority` | |
| `shareCapital`, `hostingProvider` | `50 000 euros`, `OVH SAS` |
| `websiteTitle`, `websiteDescription` | homepage meta |
| `linkedinUrl`, `facebookUrl`, `instagramUrl`, `twitterUrl`, `youtubeUrl`, `xingUrl` | social profiles linked from the homepage |
| `impressumUrl`, `fetchedVia`, `confidence`, `fieldsFound[]`, `errors[]` | provenance and quality |

`confidence` (0–1) counts how many of the four core blocks were found: name, postal address, an official identifier (registration number / VAT ID), and a contact channel. Filter on `confidence >= 0.75` for CRM-grade data.

### Why this Actor

- **Legal-page aware in 10+ languages.** Finds Impressum, Mentions légales, Aviso legal, Note legali, Colofon, Legal notice, Company information; follows index pages with several sub-pages; falls back to terms and privacy pages where UK/NL companies hide their entity.
- **Handles JavaScript sites.** Pages rendered client-side are re-fetched with a headless browser automatically (cookie banners are accepted so the legal text is in the DOM).
- **Country-specific formats built in.** UK one-line registered offices (`10 Downing Street, London SW1A 2AA`), Dutch `1015 CJ` postcodes, French number-first streets, Belgian `0123.456.789` enterprise numbers, Italian P.IVA = VAT, obfuscated e-mails.
- **VIES validation included.** Every EU VAT ID is checked against the official service, with registered name and address where available.
- **Enrichment in the same run.** Website title and description plus LinkedIn, Facebook, Instagram, X, YouTube and Xing links from the homepage, so a domain list becomes a CRM-ready company list in one step.
- **Agent-ready.** Works through the Apify MCP server, so an AI agent can look up the legal entity behind a website before writing an offer, a contract or a due-diligence note.

### Typical uses (domain to company, company enrichment, KYB)

- Enrich a lead list of domains with legal entity, registration number, VAT ID and LinkedIn page before importing into HubSpot, Pipedrive or Salesforce.
- Supplier / customer onboarding (KYB): confirm that the entity on the website matches the entity on the invoice, VIES status included.
- Build a European company dataset from a list of websites.
- Agencies: check legal-page completeness across client sites.

### Input

```json
{
  "startUrls": [{ "url": "https://www.ovhcloud.com" }, { "url": "mollie.com" }, { "url": "https://www.ocado.com" }],
  "validateVatId": true,
  "maxCandidatesPerSite": 3,
  "tryCommonPaths": true,
  "useBrowserFallback": true
}
```

### Output example

```json
{
  "domain": "sevdesk.de",
  "impressumUrl": "https://sevdesk.de/impressum/",
  "companyName": "sevDesk GmbH",
  "legalForm": "GmbH",
  "street": "Im Unteren Angel 1",
  "postalCode": "77652",
  "city": "Offenburg",
  "country": "DE",
  "registerCourt": "Amtsgericht Freiburg",
  "registerType": "HRB",
  "registerNumber": "710506",
  "vatId": "DE291779897",
  "vies": { "checked": true, "valid": true },
  "representatives": ["Rico Andersen"],
  "email": "support@sevdesk.com",
  "phone": "+49-781-125508-10",
  "linkedinUrl": "https://www.linkedin.com/company/sevdesk",
  "confidence": 1
}
```

### Pricing

Pay per event: you are charged **only for records with `confidence >= 0.25`**, i.e. domains where company data was actually found. Unreachable or blocked sites and sites without a legal page cost nothing.

### Accuracy and limits

- Legal pages are free text; extraction is heuristic. Keep `impressumUrl` and `confidence` next to the data and spot-check records below 0.75.
- Live benchmark (October 2026, `BENCHMARK.md`): on a deliberately hard set of 22 large consumer/tech sites across 12 countries, 10 returned CRM-grade records (confidence ≥ 0.75) and 16 a country; the misses were sites with bot protection (bol.com, allegro.pl, doctolib.fr, cabify.com) or whose legal entity only appears deep inside terms pages. On the simpler DACH benchmark of the sibling Actor, 18 of 20 sites succeed. Typical SME websites with a normal legal page are the easy case.
- Sites with aggressive bot protection may return `errors`; use Apify Proxy (residential) via `proxyConfiguration` if you need those.
- UK and Swiss VAT numbers are not in VIES; `vies.checked = false` with a reason is returned.
- Companies that publish only a trading name and no identifiers get a low confidence by design.

### Data protection

The Actor only reads information that the website operator is legally obliged to publish or has chosen to publish about the company. Under the Apify Store terms you (the user) are the controller of the data you collect and responsible for a lawful basis for the intended use (e.g. B2B contact, KYB). Do not use the output for unsolicited marketing where local law requires consent.

### Changelog

- 0.1 – initial release: 15+ country profiles, legal-page discovery in 10 languages, browser fallback, VIES validation, social-profile enrichment, pay-per-event pricing.

# Actor input Schema

## `startUrls` (type: `array`):

Homepages (or any page) of the companies you want to look up, anywhere in the EU, UK or Switzerland. One record per domain is returned.

## `validateVatId` (type: `boolean`):

Checks every found EU VAT ID against the official EU VIES service and adds the registered name/address when the member state returns it. UK and Swiss numbers are not in VIES.

## `maxCandidatesPerSite` (type: `integer`):

How many candidate pages (Impressum, Legal notice, Mentions légales, Aviso legal, Colofon, Contact, Terms, Privacy) to fetch per site.

## `tryCommonPaths` (type: `boolean`):

If the homepage has no recognizable legal-page link, probe /impressum, /legal-notice, /mentions-legales, /aviso-legal, /note-legali, /colofon, /about, /contact, /terms, /privacy.

## `useBrowserFallback` (type: `boolean`):

If a legal page comes back empty over plain HTTP (single-page apps, consent walls), re-fetch it with a headless browser. Costs more compute per page but rescues most large e-commerce sites.

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

Parallel requests.

## `proxyConfiguration` (type: `object`):

Apify Proxy (datacenter) is used by default so that sites blocking cloud IPs still answer. Switch to residential proxies (optionally with a country) for sites with strong bot protection or strict geo-routing.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.sevdesk.de"
    },
    {
      "url": "https://www.ovhcloud.com"
    },
    {
      "url": "https://www.mollie.com"
    },
    {
      "url": "https://www.ocado.com"
    }
  ],
  "validateVatId": true,
  "maxCandidatesPerSite": 3,
  "tryCommonPaths": true,
  "useBrowserFallback": true,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `companyRecords` (type: `string`):

Dataset with one item per domain: company name, legal form, address, register data, VAT ID with VIES result, representatives, contact data, confidence and provenance.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.sevdesk.de"
        },
        {
            "url": "https://www.ovhcloud.com"
        },
        {
            "url": "https://www.mollie.com"
        },
        {
            "url": "https://www.ocado.com"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("etse/eu-company-data-extractor").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 = {
    "startUrls": [
        { "url": "https://www.sevdesk.de" },
        { "url": "https://www.ovhcloud.com" },
        { "url": "https://www.mollie.com" },
        { "url": "https://www.ocado.com" },
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("etse/eu-company-data-extractor").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 '{
  "startUrls": [
    {
      "url": "https://www.sevdesk.de"
    },
    {
      "url": "https://www.ovhcloud.com"
    },
    {
      "url": "https://www.mollie.com"
    },
    {
      "url": "https://www.ocado.com"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call etse/eu-company-data-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,etse/eu-company-data-extractor"
        }
    }
}
```

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/oCDxUabFveBP5ipz9/builds/o6DibhgDP8g2qo078/openapi.json
