# France Company Search (`plusonets/france-company-search`) Actor

Search French companies by name, SIREN/SIRET, NAF code, place, legal form and size. Uses the official open API Recherche d'entreprises (SIRENE / RNE). Unofficial.

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

## Pricing

from $3.00 / 1,000 company results

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

## France Company Search

Search French companies, associations, and public bodies through the official [API Recherche d'entreprises](https://recherche-entreprises.api.gouv.fr). The Actor returns one normalized row per company: SIREN, headquarters SIRET, name, legal form, NAF code and label, headquarters address, creation date, status, headcount band, published executives, and establishment counts.

This Actor is unofficial. It is not affiliated with DINUM, INSEE, data.gouv.fr, or the Annuaire des entreprises.

The default run searches for `boulangerie`, keeps active companies, and saves 5 rows. That run is one API call and finishes well inside a minute.

### Why this source

The API is open, needs no account or key, and is limited to 7 requests per second per IP. It brings together open data from the Sirene register (INSEE) and the Registre national des entreprises. This Actor calls that API directly. It stays at 5 requests per second, sets a descriptive User-Agent, and backs off when the API answers HTTP 429.

### Input

| Field | Required | Default | What it does |
| --- | --- | --- | --- |
| `query` | No | `boulangerie` | Company name, address, or a director's name. At least 3 characters. A single SIREN or SIRET typed here is looked up directly. |
| `identifiers` | No | empty | SIREN (9 digits) or SIRET (14 digits). Spaces are ignored. Up to 1,000 values. |
| `nafCodes` | No | empty | NAF rév. 2 subclass of the legal unit, such as `10.71C` or `62.01Z`. |
| `departments` | No | empty | Department of an establishment: `75`, `13`, `2A`, `974`. |
| `postalCodes` | No | empty | 5-digit postcode of an establishment. |
| `legalForms` | No | empty | INSEE catégorie juridique. Common codes: `5710` SAS, `5499` SARL, `5599` SA, `1000` entrepreneur individuel, `6540` SCI, `9220` association déclarée. |
| `companySize` | No | empty | `PME`, `ETI`, or `GE`. |
| `headcountBands` | No | empty | INSEE workforce bracket: `NN`, `00`, `01`, `02`, `03`, `11`, `12`, `21`, `22`, `31`, `32`, `41`, `42`, `51`, `52`, `53`. |
| `activeOnly` | No | `true` | Keep companies whose administrative status is active (`A`). Set `false` to include ceased companies. |
| `createdFrom` / `createdTo` | No | empty | Inclusive creation dates, `YYYY-MM-DD`. |
| `maxResults` | No | `5` | How many companies to save. From 1 to 1,000. |

An empty run uses the same default as the input form: `boulangerie`, active companies, 5 results.

Several values in one field are combined with OR. Different fields are combined with AND. A department or postcode matches an establishment, so the headquarters address on the row can be in another department. Results follow the API's relevance order. The API reports at most 10,000 hits for a search.

A SIREN or SIRET lookup is exact. The API ignores other parameters on that call, and this Actor applies your filters to the company it returns. On that direct lookup the payload usually contains only the headquarters, so a department or postcode is compared with the headquarters.

`createdFrom` and `createdTo` are applied after each page. The API has no creation-date parameter. With a date window the Actor examines at most 1,000 companies, then stops. Narrow the query or the other filters when you need a date slice.

INSEE retired legal-form codes `5498` (EURL) and `5720` (SASU) in July 2020. Use `5499` and `5710`. The API rejects the retired codes.

### Output

Each dataset item is one legal unit. `siret` is the headquarters establishment. `queriedIdentifier` is set when the row came from your SIREN/SIRET list.

Executives are the `dirigeants` the registry publishes for that company. The array is empty when none are published. For a person, `birthDate` is the year and month the registry publishes (`YYYY-MM`), and `birthYear` is the year. The headcount band is the INSEE bracket of the legal unit, which can differ from the number of establishments.

This row is a real result of the default `boulangerie` search on 23 October 2026:

```json
{
  "siren": "442843942",
  "siret": "44284394200115",
  "name": "LES BOULANGERIES WATRIN",
  "legalName": "LES BOULANGERIES WATRIN",
  "acronym": null,
  "legalFormCode": "5710",
  "legalForm": "SAS, société par actions simplifiée",
  "nafCode": "10.71C",
  "nafLabel": "Boulangerie et boulangerie-pâtisserie",
  "nafSection": "C",
  "nafSectionLabel": "Industrie manufacturière",
  "address": {
    "full": "ZAC BELLE FONTAINE 57185 CLOUANGE",
    "streetNumber": null,
    "streetType": null,
    "streetName": "ZAC BELLE FONTAINE",
    "postalCode": "57185",
    "city": "CLOUANGE",
    "department": "57",
    "region": "44",
    "country": "France"
  },
  "postalCode": "57185",
  "city": "CLOUANGE",
  "department": "57",
  "creationDate": "2002-02-01",
  "closureDate": null,
  "status": "active",
  "statusCode": "A",
  "companyCategory": "PME",
  "companyCategoryLabel": "Petite ou moyenne entreprise",
  "companyCategoryYear": "2024",
  "headcountBand": "NN",
  "headcountBandLabel": "Unité non employeuse",
  "headcountYear": null,
  "executives": [
    {
      "type": "individual",
      "role": "Directeur Général",
      "name": "PAUL JOSEPH ROLAND WATRIN",
      "lastName": "WATRIN",
      "firstNames": "PAUL JOSEPH ROLAND",
      "siren": null,
      "birthYear": "1994",
      "birthDate": "1994-12",
      "nationality": null
    },
    {
      "type": "individual",
      "role": "Président de SAS",
      "name": "YVON WATRIN (WATRIN)",
      "lastName": "WATRIN (WATRIN)",
      "firstNames": "YVON",
      "siren": null,
      "birthYear": "1954",
      "birthDate": "1954-11",
      "nationality": null
    }
  ],
  "establishmentCount": 20,
  "openEstablishmentCount": 11,
  "queriedIdentifier": null,
  "registryUrl": "https://annuaire-entreprises.data.gouv.fr/entreprise/442843942",
  "sourceUpdatedAt": "2026-10-22T08:35:38",
  "source": "API Recherche d'entreprises (DINUM) — Sirene (INSEE) and the Registre national des entreprises",
  "dataLicence": "Licence Ouverte 2.0"
}
```

`postalCode`, `city`, and `department` repeat the headquarters address so the dataset table can show them beside the nested `address` object. `status` is `active`, `ceased`, or `unknown`. `statusCode` is the registry value `A` or `C`.

NAF labels are NAF rév. 2. Legal-form labels are the current INSEE catégories juridiques. A code the nomenclature does not list is still returned, with a null label.

### Pricing

Pay per event. Configure these events in the Apify console:

| Event | When it is charged | Suggested price |
| --- | --- | --- |
| `apify-actor-start` | Once per run, by the platform (memory is capped at 1 GB, so once). The Actor does not call `Actor.charge` for it. | $0.005 |
| `company-result` | One company row saved to the dataset | $0.003 |

A run that saves 100 companies costs about $0.305 ($0.005 start + 100 × $0.003). Platform compute is not billed to you. Leave the default dataset-item event out of the pricing configuration, so each company is billed once. The Actor stops saving rows when a charge tells it the run's spending limit is reached. Rows that were charged are saved. The run still succeeds when the search itself matches nothing.

### Limits

- Upstream ceiling: 7 requests per second per IP, plus a shared limit per network. This Actor sends at most 5 per second. HTTP 429 and 5xx responses are retried with `Retry-After` or an exponential backoff, up to 5 attempts. A shared cloud address can still receive 429s because other clients share it.
- Page size is 25. The API exposes the first 10,000 hits of a search and reports that number when there are more.
- `maxResults` is 1 to 1,000. A SIREN/SIRET list is capped at 1,000 values. One thousand exact lookups take a few minutes at 5 requests per second.
- A creation-date window examines at most 1,000 companies from the relevance ranking. It is a filter on those hits, and it is not a registry-wide date index.
- Companies marked non-diffusible are absent from this API, as are entities whose RCS registration was refused.
- Executive records exist only when the registry publishes them. Birth information stops at year, or year and month.
- The Sirene and RNE extracts behind the API are updated daily. `sourceUpdatedAt` is the update time returned for that company.
- NAF filters use NAF rév. 2 subclasses (`62.01Z`). NAF 2025 codes are a different list and are rejected by the API's activity filter.

### Data licence

Company records come from the API Recherche d'entreprises, operated by the Direction interministérielle du numérique (DINUM):

- API: https://recherche-entreprises.api.gouv.fr
- Service description: https://www.data.gouv.fr/dataservices/api-recherche-dentreprises
- Public company page: https://annuaire-entreprises.data.gouv.fr

The API aggregates open administrative data, in particular the Sirene register published by INSEE and the Registre national des entreprises. Reuse is allowed under the [Licence Ouverte 2.0](https://www.etalab.gouv.fr/licence-ouverte-open-licence). Each dataset row repeats the source and the licence name so the attribution stays with the data.

NAF rév. 2 labels, NAF section labels, and catégorie juridique labels are the INSEE nomenclatures, also under the Licence Ouverte. Headcount bands are the INSEE tranches d'effectifs salariés.

### Run locally

Python 3.12.

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python -m src
```

With no input file, the Actor runs the default `boulangerie` search. To pass input, create `INPUT.json` in the working directory:

```json
{
  "query": "boulangerie",
  "nafCodes": ["10.71C"],
  "departments": ["75"],
  "maxResults": 20
}
```

Local pay-per-event checks use the SDK test switch. Nothing is billed. Charges are written to `storage/datasets/charging-log/`:

```bash
ACTOR_TEST_PAY_PER_EVENT=true python -m src
```

On the platform, deploy with `apify push` from this directory. The image is `apify/actor-python:3.12`. Default memory is 512 MB.

### Tests

Unit tests mock HTTP. They do not call the API.

```bash
pip install -r requirements-dev.txt
python -m pytest
```

# Actor input Schema

## `query` (type: `string`):

Company name, address, or a director's name. At least 3 characters. A single SIREN (9 digits) or SIRET (14 digits) is accepted here too. Leave this empty when you only pass an identifier list or filters.

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

Look up these 9-digit SIREN or 14-digit SIRET numbers. Spaces are ignored. The official API ignores other filters on a direct lookup; this Actor applies them to the returned company. Department and postcode are compared with the headquarters, because a direct lookup does not list branch establishments.

## `nafCodes` (type: `array`):

NAF rév. 2 subclass codes of the legal unit, for example 10.71C (bakery) or 62.01Z (computer programming). One code per line. NAF 2025 codes are not accepted.

## `departments` (type: `array`):

INSEE department codes of an establishment. Examples: 75 (Paris), 13, 2A (Corse-du-Sud), 974 (La Réunion). One code per line.

## `postalCodes` (type: `array`):

5-digit postcodes of an establishment. One code per line.

## `legalForms` (type: `array`):

INSEE catégorie juridique codes. Common codes: 5710 SAS, 5499 SARL, 5599 SA, 1000 entrepreneur individuel, 6540 SCI, 9220 association déclarée. SASU (5720) and EURL (5498) were merged into 5710 and 5499 in 2020.

## `companySize` (type: `array`):

INSEE company category. Leave empty for any size.

## `headcountBands` (type: `array`):

INSEE workforce bracket of the company (tranche d'effectif salarié). Leave empty for any headcount. This is separate from the PME / ETI / GE category.

## `activeOnly` (type: `boolean`):

Keep companies whose administrative status is active (état A). Turn this off to include ceased companies.

## `createdFrom` (type: `string`):

Keep companies created on or after this date (YYYY-MM-DD). Applied locally. A narrow window on a broad query examines at most 1,000 companies and may return fewer rows than the maximum.

## `createdTo` (type: `string`):

Keep companies created on or before this date (YYYY-MM-DD). Applied locally, with the same 1,000-company scan cap as Created from.

## `maxResults` (type: `integer`):

Stop after this many companies. Each saved company is one company-result event. The default is small so a run finishes quickly.

## Actor input object example

```json
{
  "query": "boulangerie",
  "activeOnly": true,
  "maxResults": 5
}
```

# Actor output Schema

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

One row per French company matching the search.

# 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 = {
    "query": "boulangerie",
    "activeOnly": true,
    "maxResults": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("plusonets/france-company-search").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 = {
    "query": "boulangerie",
    "activeOnly": True,
    "maxResults": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("plusonets/france-company-search").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 '{
  "query": "boulangerie",
  "activeOnly": true,
  "maxResults": 5
}' |
apify call plusonets/france-company-search --silent --output-dataset

```

## MCP server setup

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

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/sLIMNkpOysJGFe7eU/builds/v80x78hQzfZh9iuMx/openapi.json
