# Pappers French Company & Officer Scraper (`automation-lab/pappers-french-company-officer-scraper`) Actor

Export public Pappers French company profiles by SIREN or URL with legal status, officers, establishments, financial rows, accounts, and filing metadata.

- **URL**: https://apify.com/automation-lab/pappers-french-company-officer-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#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

## Pappers French Company & Officer Scraper

Export public French company dossiers from Pappers by SIREN or company URL.
This Actor provides a practical **Pappers API** workflow for KYB checks, CRM enrichment,
officer research, filing review, and scheduled company monitoring without requiring a
Pappers account or API key.

One dataset item represents one company and can include:

- registration and legal status;
- declared activity and NAF/APE classification;
- current and former officers;
- head office and secondary establishments;
- financial table rows;
- legal-document metadata;
- annual-account filing metadata.

### What does this Pappers API Actor do?

The Actor accepts nine-digit SIREN identifiers and public `pappers.fr/entreprise/...`
URLs. It retrieves the server-rendered public profile and converts its sections into a
typed JSON dossier.

It follows canonical redirects, removes duplicate SIRENs, validates that the returned
profile matches the requested company, and saves one item only after successful parsing.

The Actor does not download PDFs or spreadsheets. It exports the public metadata that
identifies available legal documents and annual-account files.

### Who is it for?

Use this Actor if you are:

- a compliance analyst checking French counterparties;
- a sales operations team enriching company records;
- a data engineer building a registry dataset;
- a researcher mapping officers and establishments;
- a procurement team reviewing supplier status;
- an automation builder monitoring selected SIRENs on a schedule.

It is designed for known-company lookups. It does not implement free-text company search.

### Why use this Actor?

The output combines several public profile sections in one stable dataset record.
Nested limits let you keep large officer, establishment, and filing lists manageable.
The direct HTTP implementation avoids browser overhead and uses bounded retries only for
transient network and upstream errors.

Useful safeguards include:

- strict SIREN and Pappers URL validation;
- deduplication before requests are sent;
- a maximum of 100 companies per run;
- challenge and unexpected-page detection;
- no charge for invalid, duplicate, missing, or failed company records;
- no proxy configuration or login required.

### What Pappers company data can I extract?

| Field | Meaning |
| --- | --- |
| `siren` | Nine-digit French company identifier |
| `companyName` | Name displayed on the Pappers profile |
| `status` | Public profile status, such as active |
| `canonicalUrl` | Final canonical Pappers company URL |
| `legal` | Registration, legal form, VAT, RCS/RNE, and capital fields when shown |
| `activity` | Declared activity, NAF/APE code, domain, and related classification fields |
| `officers` | Names, roles, officer type, appointment text, and public profile links |
| `establishments` | SIRET, type, status, address, creation date, and trading name |
| `financialRows` | Financial metrics and displayed yearly values |
| `legalDocuments` | Document type, date, and filename metadata |
| `annualAccounts` | Account label, filing date, and available formats |
| `scrapedAt` | UTC extraction timestamp |

Fields depend on what Pappers publicly displays for the requested company. Arrays can be
empty, and optional nested values can be `null`.

### How to get started

1. Open the Actor in Apify Console.
2. Enter one or more SIRENs, or paste public Pappers company profile URLs.
3. Keep `maxItems` small for your first run.
4. Adjust the nested officer, establishment, document, and account limits if needed.
5. Click **Start**.
6. Open the **Company dossiers** dataset view.
7. Export JSON, CSV, Excel, XML, or RSS through Apify dataset integrations.

A minimal input is:

```json
{
  "sirens": ["552120222"],
  "maxItems": 1
}
```

### Input parameters

#### `sirens`

An array of nine-digit SIRENs. Spaces are accepted. Repeated values are fetched once.

#### `startUrls`

An array of public Pappers company profile URLs. URLs must use a `pappers.fr` hostname,
start with `/entreprise/`, and end in a nine-digit SIREN.

#### `maxItems`

Maximum unique company dossiers saved. Range: 1–100. Default: 10.

#### `maxOfficers`

Maximum officer records included per company. Range: 0–500. Default: 100.

#### `maxEstablishments`

Maximum establishment records included per company. Range: 0–500. Default: 100.

#### `maxDocuments`

Maximum legal-document metadata entries per company. Range: 0–500. Default: 100.
Set it to `0` if filings are not part of your workflow.

#### `maxAccounts`

Maximum annual-account metadata entries per company. Range: 0–500. Default: 50.

### Example: extract a supplied Pappers URL

```json
{
  "startUrls": [
    { "url": "https://www.pappers.fr/entreprise/sg-societe-generale-552120222" }
  ],
  "maxItems": 1,
  "maxOfficers": 10,
  "maxEstablishments": 5,
  "maxDocuments": 5,
  "maxAccounts": 5
}
```

This route applies the same limits and validation as direct SIREN input.

### Example: enrich a small KYB list

```json
{
  "sirens": ["632012100", "780129987", "542065479"],
  "maxItems": 3,
  "maxOfficers": 20,
  "maxEstablishments": 10,
  "maxDocuments": 20,
  "maxAccounts": 10
}
```

Schedule this input in Apify and compare datasets downstream to monitor public changes.
The Actor itself does not calculate diffs or send alerts.

### Output example

The following shape reflects a real successful lookup, shortened to protect readability:

```json
{
  "siren": "552120222",
  "companyName": "SG SOCIETE GENERALE",
  "status": "Active",
  "canonicalUrl": "https://www.pappers.fr/entreprise/sg-societe-generale-552120222",
  "legal": {
    "SIREN": "552 120 222",
    "Forme juridique": "SA à conseil d'administration (s.a.i.)"
  },
  "activity": {
    "Code NAF ou APE": "64.19Z (Autres intermédiations monétaires)"
  },
  "officers": [],
  "establishments": [],
  "financialRows": [],
  "legalDocuments": [],
  "annualAccounts": [],
  "scrapedAt": "2025-01-15T12:00:00.000Z"
}
```

Actual arrays contain records up to the configured limits.

### How much does it cost to extract Pappers company dossiers?

The Actor uses pay-per-event pricing:

- a one-time **Start** event per run;
- one **Item processed** event per company dossier saved.

The current start fee is **$0.005**. The BRONZE item price is **$0.0104**,
with lower six-tier volume pricing at higher account tiers. Apify shows the active tier
for your account before the run starts.

At the BRONZE rate:

| Saved companies | BRONZE event-price calculation |
| ---: | ---: |
| 1 | $0.005 start + 1 × $0.0104 item |
| 10 | $0.005 start + 10 × $0.0104 item |
| 100 | $0.005 start + 100 × $0.0104 item |

Invalid input and failed company lookups do not produce item charges. Apify platform
minimums and your active pricing tier can affect the final displayed amount.

### Data quality and freshness

The Actor exports the page as it appears at run time. It does not certify registry facts,
legal standing, beneficial ownership, or completeness.

For compliance decisions:

- keep the source URL and extraction timestamp;
- review important facts against an authoritative registry;
- expect labels and availability to vary by company;
- treat officer birth-month data as personal data where applicable;
- use a schedule appropriate for your risk process.

### Limits and failure behavior

A run fails instead of returning a misleading empty item when:

- no SIREN or URL is supplied;
- a SIREN or URL has an invalid shape;
- the page does not exist;
- Pappers returns an unsupported status or content type;
- the response looks like a challenge or unknown page;
- the returned profile SIREN differs from the requested SIREN.

Transient timeouts, connection resets, HTTP 429, and selected 5xx responses are retried
up to three times with backoff. Deterministic validation and not-found errors are not
retried.

### Tips for reliable runs

- Start with one known SIREN.
- Use smaller nested limits when a company has thousands of establishments.
- Split lists larger than 100 companies across Tasks or API calls.
- Schedule moderate batches rather than sending simultaneous bursts.
- Keep `canonicalUrl` as the durable source reference.
- Set unused nested limits to `0` to reduce dataset size.
- Inspect run logs before retrying a failed upstream request.

### Export and integration workflows

Common patterns include:

1. Import a SIREN column from a CRM and run bounded enrichment batches.
2. Join output on `siren` in a warehouse.
3. Flatten officers or establishments in your ETL tool.
4. Store daily dataset snapshots and calculate changes downstream.
5. Trigger review when `status`, officers, or filing metadata changes.
6. Send datasets to Google Sheets, Make, Zapier, webhooks, or cloud storage.

Apify datasets support API pagination and multiple export formats.

### Run with the Apify API using cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~pappers-french-company-officer-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sirens":["552120222"],"maxItems":1}'
```

Use `run-sync-get-dataset-items` when your client can wait for the result:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~pappers-french-company-officer-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sirens":["552120222"],"maxItems":1}'
```

### Run with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/pappers-french-company-officer-scraper').call({
  sirens: ['552120222'],
  maxItems: 1,
  maxOfficers: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run with Python

```python
from apify_client import ApifyClient
import os

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/pappers-french-company-officer-scraper').call(
    run_input={'sirens': ['552120222'], 'maxItems': 1}
)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use through MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/pappers-french-company-officer-scraper"
```

Claude Desktop, Cursor, and VS Code can use the same HTTP MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/pappers-french-company-officer-scraper"
    }
  }
}
```

Example prompts:

- “Look up SIREN 552120222 and summarize its public legal status.”
- “Extract officers and annual-account metadata for these three SIRENs.”
- “Return a compact KYB table from the supplied Pappers company URLs.”

### Responsible and legal use

Pappers profiles can contain public company information and personal information about
company officers. You are responsible for having a lawful purpose and complying with
applicable data protection, database, website, and sector-specific rules.

Do not use the Actor to harass people, make solely automated high-impact decisions, or
republish personal data without a lawful basis. Minimize fields and retention periods,
honor valid rights requests, secure exported datasets, and review Pappers terms before
high-volume recurring use.

### Troubleshooting

#### Why does my URL fail validation?

Only public `pappers.fr/entreprise/...` company profile URLs are accepted. Search result,
document-download, unrelated, and non-Pappers URLs are rejected. You can use the final
nine-digit SIREN directly instead.

#### Why is a nested array shorter than the number shown on Pappers?

Your nested limit may be smaller than the available count. Increase the relevant limit up
to 500. Some source sections can also be truncated or unavailable publicly.

#### Why did a missing company fail the whole run?

The Actor fails closed so scheduled pipelines do not mistake missing or challenged pages
for valid empty dossiers. Correct or remove the invalid SIREN and run again.

#### Does the Actor download legal documents or accounts?

No. It exports public filenames, dates, labels, and available formats. It does not download
PDF or spreadsheet contents.

#### Does it search Pappers by company name?

No. Supply known SIRENs or company profile URLs. This keeps the product focused on exact
company enrichment rather than broad lead discovery.

### Related Automation Lab Actors

- [Corporate.AI Company Registry Scraper](https://apify.com/automation-lab/corporate-ai-company-registry-scraper) for a different multi-registry workflow.
- [Belgium CBE Company Registry Scraper](https://apify.com/automation-lab/belgium-cbe-company-registry-scraper) for Belgian company records.

Choose this Actor when the input is a French SIREN or Pappers company URL and the desired
output is a structured Pappers dossier.

### FAQ

**Can I run it on a schedule?**\
Yes. Save the input as an Apify Task and use a schedule. Compare datasets downstream for
monitoring because the Actor does not emit change events itself.

**Is a Pappers API key required?**\
No. The Actor reads anonymous public company profile pages.

**Is a proxy required?**\
No proxy is enabled or required by the current implementation.

**How many output items are created?**\
One item per unique successfully parsed SIREN, up to `maxItems`.

**Are duplicates charged twice?**\
No. Inputs are deduplicated by SIREN before fetching or charging.

**Can fields be missing?**\
Yes. Pappers varies by company, registration history, and publication availability. Use
null-safe downstream mappings.

# Actor input Schema

## `sirens` (type: `array`):

Nine-digit French company identifiers. Spaces are accepted and duplicate identifiers are removed.

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

Public pappers.fr/entreprise/... company profile URLs. Search pages and non-Pappers URLs are rejected.

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

Maximum number of unique company dossiers to save.

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

Maximum current and former officers retained in each company dossier.

## `maxEstablishments` (type: `integer`):

Maximum head-office and secondary-establishment records retained per company.

## `maxDocuments` (type: `integer`):

Maximum public legal-document metadata entries retained per company. Files are not downloaded.

## `maxAccounts` (type: `integer`):

Maximum annual-account filing metadata entries retained per company. Files are not downloaded.

## Actor input object example

```json
{
  "sirens": [
    "552120222"
  ],
  "startUrls": [
    {
      "url": "https://www.pappers.fr/entreprise/sg-societe-generale-552120222"
    }
  ],
  "maxItems": 10,
  "maxOfficers": 100,
  "maxEstablishments": 100,
  "maxDocuments": 100,
  "maxAccounts": 50
}
```

# Actor output Schema

## `dataset` (type: `string`):

Company identity, legal registration, activity, officers, establishments, financial rows, and filing metadata.

# 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 = {
    "sirens": [
        "552120222"
    ],
    "startUrls": [
        {
            "url": "https://www.pappers.fr/entreprise/sg-societe-generale-552120222"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/pappers-french-company-officer-scraper").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 = {
    "sirens": ["552120222"],
    "startUrls": [{ "url": "https://www.pappers.fr/entreprise/sg-societe-generale-552120222" }],
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/pappers-french-company-officer-scraper").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 '{
  "sirens": [
    "552120222"
  ],
  "startUrls": [
    {
      "url": "https://www.pappers.fr/entreprise/sg-societe-generale-552120222"
    }
  ]
}' |
apify call automation-lab/pappers-french-company-officer-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/pappers-french-company-officer-scraper"
        }
    }
}

```

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/OasyxqFhGeElGSVZ9/builds/nagDNqJ1hqLYAI4Sy/openapi.json
