# Europe Company Officers & Directors — Official Registry Data (`foxlabs/europe-company-officers`) Actor

Officers and directors of French, Norwegian and Czech companies from the official registries, one row per person: full name, role, body, appointment and departure date, birth year, residence country, company number and registry link. Search by company name or registration number. No API key.

- **URL**: https://apify.com/foxlabs/europe-company-officers.md
- **Developed by:** [Berkan Kaplan](https://apify.com/foxlabs) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 officer rows

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

## Europe Company Officers & Directors — Official Registry Data

Get the **people behind a company**, not just the company. One row per officer: full name, role, which body
they sit on, when they were appointed and when they left, birth year, country of residence, and the company's
registration number with a link to its official registry page.

Three official registries, one schema: **France** (Répertoire National des Entreprises), **Norway**
(Enhetsregisteret, Brønnøysundregistrene) and **Czechia** (Veřejný rejstřík / ARES). Search by company name or
look up an exact registration number. No API key, no account at any registry, no browser.

### 🔍 What is this Actor — and when should you use it?

Company databases give you the company. Sales, KYC and research work needs the **decision maker**: who signs,
who chairs the board, who just joined.

Use it when you want to:

- put a **name and a role** next to a company you already have (SIREN, organisasjonsnummer or IČO in, officers out);
- build a list of **managing directors or board chairs** for companies matching a name or a trade;
- see **who left and who arrived** — Czechia publishes appointment and departure dates for every member, so a
  second run tells you what changed;
- check a company's **governance** for compliance: the statutory body, the supervisory board, the proxies, with
  a link to the registry page as evidence.

Do **not** use it to find private individuals: it reads company registers, and every person in it is there
because they hold a public role in a company.

### 🤖 Use with AI agents

**Already on the Apify MCP server?** Ask for this Actor by name: `foxlabs/europe-company-officers`.

**Your agent can pay for its own runs.** This Actor is pay-per-event with agentic payments, so an agent can
discover it, run it and settle the bill over **x402 (USDC on Base)** or **Skyfire** — no Apify account or API
token of its own. Billing is the same either way: per delivered officer row, never for errors.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```
I want the officers and directors of European companies using the Apify Actor
`foxlabs/europe-company-officers`.

Input: `companyNames` is a list of company names to search for; prefix one with a country to pin it
("FR:Michelin", "NO:Equinor", "CZ:Škoda Auto"), or leave it bare to search all three registries.
`companyIds` takes exact registration numbers instead: SIREN (FR, 9 digits), organisasjonsnummer
(NO, 9 digits), IČO (CZ, 8 digits). Filters: `countries` (fr, no, cz), `onlyActive` (current roles
only, default true), `includeEntityOfficers` (roles held by a company, default false),
`appointedAfter` ("2026-09-01" — Czechia only, the other two publish no appointment dates),
`organs` (board, supervisory_board, management, proxy, audit, owner),
`maxCompaniesPerQuery` (default 5), `maxOfficers` (default 500).
Each row has officerFullName, officerRole, officerRoleOriginal, officerOrgan, isActive,
appointedAt, resignedAt, birthYear, residenceCountry, companyName, companyId and companyRegistryUrl.

Start with:
{ "companyIds": ["CZ:00177041"], "onlyActive": true }

Ask me which companies or which country I care about, run the Actor, then give me the officers as a table.
```

Things you can ask your agent for:

- "Who is the managing director of each of these 40 French companies?"
- "Every current board member of Škoda Auto, with the date they were appointed."
- "Which people joined the board of these Czech companies after 1 September 2026?"
- "Show me every role this person holds across the companies in my list."

The machine-readable API, MCP config and OpenAPI definition live at
`apify.com/foxlabs/europe-company-officers.md`.

### 📋 Overview

| | |
|---|---|
| **Countries** | France, Norway, Czechia |
| **Sources** | `recherche-entreprises.api.gouv.fr` · `data.brreg.no` · `ares.gov.cz` — official government APIs |
| **Granularity** | one row per officer per role term |
| **Fields** | 32 |
| **Start from** | a company name, or an exact registration number |
| **Appointment dates** | Czechia yes; France and Norway do not publish them |
| **Keys / accounts** | none |
| **Modes** | batch run; the same code also answers as a Standby HTTP API |

Pool size, measured 2026-10-20: the Norwegian register alone holds **1,178,742 entities**, and a company
carries several roles (Equinor: 15; Škoda Auto: 165 including past terms).

### ✨ Features

- **One row per person, not a `directors` blob.** Filter, sort and dedupe officers like any other table.
- **The registry's own wording kept.** `officerRoleOriginal` holds "Gérant", "Daglig leder" or
  "člen představenstva"; `officerRole` adds a normalised English name and `officerOrgan` says which body it is.
- **Role terms with dates (Czechia).** `appointedAt` and `resignedAt` per member, so past boards are available
  and new appointments are visible.
- **Current or historical.** `onlyActive` on by default; turn it off for everyone who ever held the role.
- **People, or companies too.** Corporate officers (a parent company, an auditing firm) are off by default and
  come with `officerEntityName` / `officerEntityId` when you ask for them.
- **Evidence in every row.** `companyRegistryUrl` opens the official page; `sourceUrl` is the exact API call.
- **A date-of-birth decision made on purpose.** The registries publish full dates of birth; this Actor delivers
  only **`birthYear`** — enough to tell two people with the same name apart, without shipping a full
  identity record.
- **Nothing silently empty.** A target that delivers no row leaves a free status row saying why, and
  `SOURCE_REPORT` holds the per-target detail.

### 🎬 Quick Start

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~europe-company-officers/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companyIds": ["CZ:00177041"], "onlyActive": true}'
```

### 🚀 Getting Started (3 steps)

1. **Name or number.** Put company names in `companyNames` (prefix with `FR:`, `NO:` or `CZ:` to pin a
   country) or exact registration numbers in `companyIds`.
2. **Narrow it if you want.** `onlyActive`, `organs`, `appointedAfter`, `includeEntityOfficers`.
3. **Run it.** Officer rows land in the dataset; the run log and `SOURCE_REPORT` say what each target did.

### 📥 Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `companyNames` | array | — | Names to search for. `"Michelin"` searches every chosen country; `"FR:Michelin"` searches only France. |
| `companyIds` | array | — | Exact numbers: SIREN (FR, 9 digits), organisasjonsnummer (NO, 9 digits), IČO (CZ, 8 digits). `"CZ:00177041"` pins the registry. |
| `countries` | array | `fr, no, cz` | Which registries to ask. |
| `maxCompaniesPerQuery` | integer | 5 | How many matching companies one **name** search reads officers for. A number always reads exactly one company. |
| `maxOfficers` | integer | 500 | Stops the run at this many delivered rows. |
| `onlyActive` | boolean | `true` | Current roles only. Off also returns past terms — in practice that means Czechia, the only one of the three that publishes them. |
| `includeEntityOfficers` | boolean | `false` | Include roles held by a company instead of a person. |
| `appointedAfter` | string | — | Keep only roles appointed on or after this date (`YYYY-MM-DD`). **Czechia only**; France and Norway publish no appointment date, so their rows are left out when this is set, and the run note says so. |
| `organs` | array | all | `board`, `supervisory_board`, `management`, `proxy`, `audit`, `owner`. |
| `removeDuplicates` | boolean | `true` | The same person, company, role and term is delivered once across your targets. |

One of `companyNames` or `companyIds` is required; the Actor refuses to guess and says so instead of running.

### 📤 Output

One row per officer per role term. 32 fields:

**The person** — `officerFullName`, `officerFirstName`, `officerLastName`, `officerKind`
(`person` / `entity`), `birthYear`, `residenceCountry`, `isDeceased` (Norway only), `officerEntityName`,
`officerEntityId`.

**The role** — `officerRole` (normalised), `officerRoleOriginal` (the registry's wording), `officerOrgan`,
`officerOrganName` (the body's own name, Czechia), `isActive`, `appointedAt`, `resignedAt`,
`roleGroupChangedAt` (Norway: when this role group last changed).

**The company** — `companyName`, `companyId`, `companyIdType`, `companyLegalForm`, `companyStatus`,
`companyIncorporatedAt`, `companyActivityCode`, `companyCity`, `companyPostalCode`, `companyCountry`,
`country`, `registry`, `companyRegistryUrl`, `sourceUrl`.

**The row** — `type` (`officer` / `status`), `query`, `scrapedAt`, `error`.

#### Sample row (Czechia)

```json
{
  "type": "officer",
  "country": "CZ",
  "registry": "Veřejný rejstřík / ARES, Ministerstvo financí ČR (ares.gov.cz)",
  "companyId": "00177041",
  "companyIdType": "IČO",
  "companyName": "Škoda Auto a.s.",
  "companyCity": "Mladá Boleslav",
  "companyRegistryUrl": "https://or.justice.cz/ias/ui/rejstrik-$firma?ico=00177041",
  "officerKind": "person",
  "officerFullName": "Klaus-Dieter Schürmann",
  "officerRole": "board_member",
  "officerRoleOriginal": "člen představenstva",
  "officerOrgan": "board",
  "officerOrganName": "Statutární orgán - představenstvo",
  "isActive": false,
  "appointedAt": "2016-08-01",
  "resignedAt": "2021-09-30",
  "birthYear": 1963,
  "residenceCountry": "DE"
}
```

#### How full each field is (measured)

303 officer rows from 29 companies across the three registries, 2026-10-20, past roles and corporate officers
included so that every field could be seen:

| Field | All | FR | NO | CZ |
|---|---|---|---|---|
| `officerFullName`, `officerRoleOriginal`, `isActive`, `companyId`, `companyName`, `companyRegistryUrl` | 100% | 100% | 100% | 100% |
| `officerRole` (normalised) | 96% | 97% | 100% | 94% |
| `officerOrgan` | 99% | 97% | 99% | 100% |
| `officerLastName` | 95% | 69% | 94% | 100% |
| `birthYear` | 75% | 69% | 94% | 69% |
| `appointedAt` | 62% | 0% | 0% | 100% |
| `resignedAt` | 56% | 0% | 0% | 90% |
| `residenceCountry`, `officerOrganName` | 62% | 0% | 0% | 100% |
| `roleGroupChangedAt` | 26% | 0% | 100% | 0% |
| `companyActivityCode` | 38% | 100% | 100% | 0% |

The French figures for `officerFirstName` / `officerLastName` / `birthYear` are held down by corporate
officers, which have no personal name — with the default `includeEntityOfficers: false` they are not delivered
at all. France leaves `qualite` empty on a small number of records, which is why `officerRoleOriginal` is 97%
and not 100% there.

Roles in that sample: board member 105, supervisory board member 75, board chair 29, managing director 27,
supervisory board chair 15, deputy board member 14, auditor 10, president 6, proxy holder 6, partner 3.

### 💼 Use cases

- **Sales.** Turn a list of companies into named decision makers with their role, ready for a CRM.
- **KYC and onboarding.** The statutory body, the supervisory board and the proxies, with a registry link per row.
- **Change monitoring.** Run the same company list weekly and compare `appointedAt` — a new board member is a
  trigger worth a call.
- **Research and due diligence.** Past terms in Czechia show how a board has turned over.
- **Entity resolution.** `birthYear` plus the name separates two people who share a name across companies.

### 🔗 Integration

**JavaScript / Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/europe-company-officers').call({
  companyIds: ['CZ:00177041'], onlyActive: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/europe-company-officers').call(
    run_input={'companyIds': ['CZ:00177041'], 'onlyActive': True}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

Written for `apify-client` 3 for Python, where `call()` returns a run object; with version 1 or 2 it returns a
dict — write `run['defaultDatasetId']` there.

**Automation (n8n / Zapier / Make):** schedule → HTTP request to the Actor API with your company list → handle
the JSON dataset → push to a sheet, CRM or dashboard.

### 📊 Pricing

Pay-per-event: **$0.002 per delivered officer row**, plus the per-run start event. Status rows are free, and a
role left out by your filters (not current, held by a company, appointed before your date, on a body you did
not ask for) is never delivered and never charged. The same person found through two of your searches is
charged once. [View current pricing.](https://apify.com/foxlabs/europe-company-officers)

### ❓ FAQ

**Which countries?** France, Norway and Czechia. They were chosen because all three publish officers through an
official API with no key and allow a search by company name, which is what lets you start from a name you know.

**Why is Poland not here?** Its register answers only for a KRS number you already have, and its search is
behind a bot wall (measured HTTP 403 on 2026-10-20). Starting from a company name is not possible, so it was
left out rather than shipped as a half feature.

**Do I get a date of birth?** No — only `birthYear`. The registries do publish full dates; this Actor delivers
the year, which is enough to tell people apart.

**Why does `appointedAfter` return nothing for France and Norway?** Those registries do not publish an
appointment date. Rather than invent one, the Actor leaves those rows out and the run note says exactly that.
For a Norwegian company, `roleGroupChangedAt` is the nearest thing: when the registry last changed that group
of roles.

**Why did a company return no officers?** Some companies in the Czech business register have no public-register
file (a sole trader, for instance) — measured on 2026-10-20, 2 of 10 companies found by name. The status row
says so, and it is not charged.

**How many companies does one name search read?** `maxCompaniesPerQuery`, 5 by default. A name search finds
matches in the registry's own order; a registration number is exact.

**Is the data live?** Every run reads the registries directly — there is no snapshot in between.

### 🐛 Troubleshooting

- **"Give at least one company"** — `companyNames` or `companyIds` has to hold something.
- **"… is not a IČO"** — the number does not match the country's format (SIREN and organisasjonsnummer are 9
  digits, IČO is 8). Nothing is requested and nothing is charged.
- **Empty result with a status row** — the registry has nothing matching, or your filters removed everything.
  The row's `error` field names the reason and the counts are in `SOURCE_REPORT`.
- **Fewer rows than expected** — check `onlyActive` (past terms are off by default) and
  `includeEntityOfficers` (corporate roles are off by default).
- **A target says "did not answer"** — the registry did not reply in time. The request is tried again once
  automatically; a target that still fails is reported, and the rest of the run goes on.

### ⚠️ Trademark

France, Norway and Czechia and their registry operators (DILA / data.gouv.fr, Brønnøysundregistrene,
Ministerstvo financí ČR) are not affiliated with this Actor and do not endorse it. Names are used only to say
which public source the data comes from.

### ⚖️ Is it legal to scrape this data?

The three sources are **official open-data APIs**, published for reuse including commercial reuse. This Actor
sends plain requests to them, no key and no sign-in, and does nothing a registry's own website does not do.

These records name real people in their professional role as a company officer. Treat the output as personal
data: in the EU and the EEA you need a lawful basis to process it, you have to tell people whose data you hold,
and the data subject keeps their rights. This Actor deliberately delivers only the **year** of birth rather
than the full date the registries publish. What you do with the rows is your responsibility, not the registry's
and not ours.

### 🤝 Support & contact

Found a registry field we should carry, or a country worth adding? Open an issue on the Actor page. Denmark,
Estonia and Latvia were looked at for this release and left for the next one; Poland is explained in the FAQ.

### Changelog

#### 0.1 — 2026-10-20

- First release. France, Norway and Czechia; one row per officer per role term; 32 fields.
- Batch runs and a Standby HTTP API from the same code.
- `birthYear` instead of the full date of birth the registries publish.
- Czechia: appointment and departure dates, the supervisory body, the member's country of residence, and the
  company's **current** name (its public-register file lists every name it ever had).

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/europe-company-officers/changelog.md

# Actor input Schema

## `companyNames` (type: `array`):

Company names to search for. A plain name is looked for in every country you chose; prefix one with a country to pin it — "FR:Michelin", "NO:Equinor", "CZ:Škoda Auto".

## `companyIds` (type: `array`):

Exact registration numbers: SIREN (FR, 9 digits), organisasjonsnummer (NO, 9 digits) or IČO (CZ, 8 digits). Prefix with a country when the same number could belong to two registries — "CZ:00177041".

## `countries` (type: `array`):

Which registries to ask. Leave empty for all three.

## `maxCompaniesPerQuery` (type: `integer`):

How many matching companies one name search reads officers for. A registration number always reads exactly one.

## `maxOfficers` (type: `integer`):

Stops the run once this many officer rows are delivered.

## `onlyActive` (type: `boolean`):

On: only people currently in the role. Off: past roles too — Czechia publishes the full history with its departure dates, so this is where the past comes from.

## `includeEntityOfficers` (type: `boolean`):

Some roles are held by another company rather than a person (a corporate director, a parent company, an auditing firm). Off by default so every row is a person.

## `appointedAfter` (type: `string`):

Keep only roles whose appointment date is on or after this date (YYYY-MM-DD) — the way to list new appointments. Only Czechia publishes appointment dates; rows from France and Norway have none and are left out when this is set.

## `organs` (type: `array`):

Keep only roles on these bodies. Leave empty for all.

## `removeDuplicates` (type: `boolean`):

The same person in the same company and role is delivered once, even when two of your searches find the company.

## Actor input object example

```json
{
  "companyNames": [
    "FR:Michelin",
    "NO:Equinor",
    "CZ:Škoda Auto"
  ],
  "countries": [
    "fr",
    "no",
    "cz"
  ],
  "maxCompaniesPerQuery": 5,
  "maxOfficers": 500,
  "onlyActive": true,
  "includeEntityOfficers": false,
  "removeDuplicates": true
}
```

# Actor output Schema

## `dataset` (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 = {
    "companyNames": [
        "FR:Michelin",
        "NO:Equinor",
        "CZ:Škoda Auto"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/europe-company-officers").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 = { "companyNames": [
        "FR:Michelin",
        "NO:Equinor",
        "CZ:Škoda Auto",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/europe-company-officers").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 '{
  "companyNames": [
    "FR:Michelin",
    "NO:Equinor",
    "CZ:Škoda Auto"
  ]
}' |
apify call foxlabs/europe-company-officers --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,foxlabs/europe-company-officers"
        }
    }
}
```

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/orZMbgwFRv7BYselo/builds/3t1O6k9cWqTdRVexe/openapi.json
