# France Companies (SIRENE) - Legal Entities, NAF & Financials (`jpopendata/france-companies-sirene`) Actor

French companies from the official INSEE Sirene search API: SIREN, head-office SIRET, legal form, NAF code, staff band, city/postcode, revenue and labels. Legal entities only; no officers' names or street addresses. Licence Ouverte 2.0. Unofficial; not affiliated with INSEE.

- **URL**: https://apify.com/jpopendata/france-companies-sirene.md
- **Developed by:** [JP Open Data](https://apify.com/jpopendata) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 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 Companies (SIRENE) - Legal Entities, NAF & Financials

**French companies from the official INSEE Sirene search API, one row per company (SIREN): name, head-office SIRET, legal form, NAF/APE activity code with its label, staff band, SME/mid-size/large category, city and postcode, published revenue and net income, VAT number, labels (RGE, Qualiopi, ESS ...) and a link to the official company page.**

The data comes from the **API Recherche d'entreprises**, the free public API behind the French government's *Annuaire des Entreprises* (DINUM), which serves INSEE's Sirene register together with the INPI/BCE financial ratios and other public registers. This Actor searches it by keyword, activity, place, legal form, staff band, category, labels and revenue, or looks up a list of SIREN/SIRET numbers, and turns the results into a clean table.

> **Unofficial tool. Not affiliated with or endorsed by INSEE, DINUM, the Annuaire des Entreprises or the French Government.** Public data only. **Legal entities only:** sole proprietors are never returned, and no officers' names, birth dates or street addresses are output (see *Personal data*).

### Quick start — verified input

Run on 2026-10-13 on the Apify platform: 20 rows, one API request, a few seconds. An empty input `{}` runs exactly this.

```json
{
  "nafCodes": ["62.01Z"],
  "departments": ["75"],
  "maxItems": 20
}
```

Building firms with 10–49 employees and at least €1M revenue in Lyon's department, SAS and SARL only:

```json
{
  "nafCodes": ["F"],
  "departments": ["69"],
  "employeeBands": ["10-49"],
  "legalForms": ["SAS", "SARL"],
  "revenueMin": 1000000,
  "maxItems": 500
}
```

Look up known companies (SIREN, SIRET or VAT number):

```json
{
  "sirens": ["356000000", "552 100 554", "FR39851035329"]
}
```

#### Common input mistakes

| Wrong | Right | Why |
|---|---|---|
| `"nafCodes": ["software"]` | `"keywords": ["software"]` or `"nafCodes": ["62.01Z"]` | NAF codes look like `62.01Z` (`6201Z`, a class `62.01`, a division `62` or a section `J` also work). |
| `"departments": ["Lyon"]` | `"departments": ["69"]` or `"postalCodes": ["69002"]` | Cities are not departments. |
| `"keywords": ["Jean Dupont"]` | — | Keywords match company names, acronyms and trade names only. Searching companies by a person's name is not supported. |
| `"keywords": ["boulangerie paris"]` | `"keywords": ["boulangerie"], "departments": ["75"]` | Put places in departments, regions or postcodes. |
| `"legalForms": ["EI"]` | — | Sole proprietors are never returned (privacy). |
| `"employeeBands": ["15-30"]` | `"employeeBands": ["10-49"]` | Ranges follow the INSEE bands (0, 1, 3, 6, 10, 20, 50, 100, 200, 250, 500, 1000, 2000, 5000, 10000). |

An invalid value stops the run before any request, with a message that names the field and lists the valid values.

#### Empty results?

The run ends successfully with 0 rows when nothing matches. Typical reasons: the keyword is not part of any company name (results the API found through officers, elected officials, addresses or approximate spelling are dropped), too many filters combined (they are combined with AND), or a search that only finds sole proprietors. `RUN_SUMMARY` in the key-value store shows how many results each query returned and how many were left out and why.

### Input

All fields are optional.

- **keywords** — words from the company name, acronym or trade name. Each keyword is a separate search combined with the filters; results are merged without duplicates.
- **sirens** — a list of SIREN (9 digits), SIRET (14 digits) or French VAT numbers to look up directly. When set, only these are looked up (keywords and filters are ignored, as the API ignores filters for a direct lookup); every listed number is looked up regardless of `maxItems`.
- **nafCodes** — NAF rev. 2 codes, classes, divisions or section letters.
- **departments**, **regions**, **postalCodes** — places. They match companies with at least one establishment there (not only the head office); departments and postcodes given together are treated as "either". Former regions (Alsace, Rhône-Alpes ...) are accepted.
- **legalForms** — INSEE codes or common names: SAS, SARL, SA, SCI, SNC, SCOP, SELARL, SELAS, GIE, association, fondation, a code `5710` or a prefix `54`.
- **employeeBands** — `10-49`, `250+`, `0`, or INSEE codes.
- **companyCategories** — PME (SME), ETI (mid-size), GE (large).
- **labels** — ess, rge, qualiopi, bio, siae, societe_mission, association, finess, uai, organisme_formation, egapro, patrimoine_vivant, achats_responsables, alim_confiance, entrepreneur_spectacle, collectivite_territoriale, administration, convention_collective (all must apply).
- **status** — active (default), ceased or any.
- **revenueMin / revenueMax** — latest published revenue in euros.
- **includeCorporateOfficers** — add officers that are companies (e.g. the statutory auditor firm), with name, SIREN and role.
- **maxItems** (default 20, up to 200,000) and **maxApiRequests** (default 500) — limits for searches.

### Output

One row per company:

```json
{
  "siren": "851035329",
  "siret": "85103532900024",
  "name": "CHAPSVISION",
  "legalName": "CHAPSVISION",
  "acronym": null,
  "tradeNames": [],
  "nameWithheld": false,
  "legalFormCode": "5710",
  "legalForm": "SAS, société par actions simplifiée",
  "nafCode": "62.01Z",
  "nafLabel": "Programmation informatique",
  "nafSection": "J",
  "nafSectionLabel": "Information et communication",
  "nafCode2025": "62.10Y",
  "status": "active",
  "createdOn": "2019-05-16",
  "closedOn": null,
  "employeeBandCode": "22",
  "employeeBand": "100-199 employees",
  "employeeBandYear": 2024,
  "isEmployer": null,
  "companyCategory": "ETI",
  "companyCategoryYear": 2024,
  "city": "SURESNES",
  "postalCode": "92150",
  "communeCode": "92073",
  "departmentCode": "92",
  "department": "Hauts-de-Seine",
  "regionCode": "11",
  "region": "Île-de-France",
  "country": "France",
  "establishmentsCount": 15,
  "openEstablishmentsCount": 14,
  "financials": [{ "year": 2024, "revenue": 156671000, "netIncome": -38221000 }],
  "latestFinancialYear": 2024,
  "latestRevenue": 156671000,
  "latestNetIncome": -38221000,
  "vatNumbers": ["FR39851035329"],
  "labels": ["qualiopi", "organisme_formation", "egapro", "convention_collective"],
  "associationId": null,
  "collectiveAgreements": ["1486"],
  "partialDiffusion": false,
  "canonicalSiren": null,
  "corporateOfficers": null,
  "naturalPersonOfficersOmitted": null,
  "matchingEstablishments": [
    { "siret": "85103532900040", "isHeadOffice": false, "status": "active", "nafCode": "62.01Z", "city": "PARIS", "postalCode": "75002",
      "communeCode": "75102", "departmentCode": "75", "regionCode": "11", "tradeNames": [], "createdOn": "2026-01-01", "closedOn": null,
      "employeeBandCode": "NN", "partialDiffusion": false }
  ],
  "lastUpdatedAt": "2026-10-12T09:51:21",
  "annuaireUrl": "https://annuaire-entreprises.data.gouv.fr/entreprise/851035329",
  "matchedBy": "quick-start",
  "source": "API Recherche d'entreprises (DINUM, Annuaire des Entreprises) - data from INSEE Sirene, INPI/BCE financial ratios and other public registers",
  "sourceUrl": "https://www.data.gouv.fr/dataservices/api-recherche-dentreprises",
  "license": "Licence Ouverte / Open Licence 2.0 (Etalab), https://www.etalab.gouv.fr/licence-ouverte-open-licence/. Source: INSEE (base Sirene), ...",
  "retrievedAt": "2026-10-13T06:30:00.000Z"
}
```

- Legal-form, NAF and section labels are INSEE's official French labels; staff bands are in English.
- `matchingEstablishments` lists up to 10 establishments that matched a place filter or a keyword (city and postcode only); it is empty for direct lookups.
- `financials` holds the published revenue and net income by financial year when the company filed public accounts (often the latest year only).
- `nafCode2025` is INSEE's forthcoming NAF 2025 code, published for information until it replaces the current code in January 2027.

### How it reads the API

- One request returns up to 25 companies. Requests go one at a time, at least 1.2 seconds apart (the API allows up to 7 per second per IP), and an HTTP 429 is retried only after the wait the API asks for (`Retry-After`). About 1,200 rows per minute.
- The API returns at most 10,000 results per query. When a search has more and you ask for more, the Actor splits it automatically — by legal form, then by activity section/division/code, then by department — and removes duplicates. If one slice still has more than 10,000 results after every split, the run reads the first 10,000 of it and ends with `complete: false` and the slice listed in `RUN_SUMMARY.cappedSlices`: results are never cut silently. Splits by legal form, activity and department reach companies through INSEE's code tables and French establishments; `RUN_SUMMARY.splitNotes` says which were used.
- If the API fails mid-run, or `maxApiRequests` or the run timeout is reached, the rows read so far are kept and the run succeeds with `complete: false` and a `stopReason`. If nothing could be read at all, the run fails visibly.
- robots.txt is checked at the start of every run.

### Personal data

- **Sole proprietors are never returned.** Units of legal-form category 1 (entrepreneur individuel, micro-entrepreneur, EIRL) and category 2 (indivisions, sociétés créées de fait or en participation, fiducies — groupings without legal personality) are dropped whole, because their names are the names of private persons. The API is also asked to leave sole proprietors out (`est_entrepreneur_individuel=false`).
- **No officers who are natural persons.** Their names, birth dates and nationalities are not requested by default; with `includeCorporateOfficers` only officers that are companies are output, and natural persons are only counted.
- **No street addresses or coordinates.** Location stops at city, postcode, department and region. Elected officials of local authorities are never output.
- **Partial diffusion respected.** Where INSEE masks data after an objection (statut de diffusion "P"), the masked values are returned as `null` with `partialDiffusion: true`; nothing is rebuilt from other fields. Data is read live at run time, so the latest diffusion status applies; if you store results, refresh them and keep honouring later objections.
- **Keywords match company names only.** Results the API found through officers, elected officials or addresses are dropped, so the Actor cannot be used to list the companies of a person.
- Company names are the registered names of legal entities and can contain a founder's family name (e.g. a property company named after a family). Use the data in line with the GDPR, the French Data Protection Act and the rules on direct marketing; you are responsible for your use of the data.

### Licence and attribution

The data is published under the **Licence Ouverte / Open Licence 2.0** (Etalab): INSEE's *Base Sirene des entreprises et de leurs établissements*, DINUM's *Données des entreprises utilisées dans l'Annuaire des Entreprises* and the Ministry of Economy's *Ratios financiers (BCE/INPI)*. The licence asks you to credit the source and the date of the last update: every row carries `source`, `license` and `lastUpdatedAt`. Keep them when you republish the data.

This is an unofficial tool. It uses only the public API, does not log in anywhere and does not bypass any protection. You are responsible for complying with the source's conditions and with the law in your use of the data.

### Pricing

Pay per row stored in the dataset. A run stops by itself when it reaches the maximum charge you set.

# Actor input Schema

## `keywords` (type: `array`):

Optional. Words from the company's name, acronym or trade name, e.g. "carrefour", "boulangerie", "cabinet comptable". Each keyword is a separate search combined with the filters below; results are merged without duplicates. Only companies whose own names contain the keyword are kept (searches by a person's name or a street address return nothing). Put places in Departments / Postcodes, not here.

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

Optional. Look up these companies directly: SIREN (9 digits, e.g. "552100554"), SIRET (14 digits) or French VAT number ("FR40552100554"); spaces and dots are fine. When set, the run ONLY looks up these (keywords and filters are ignored) and every listed number is looked up regardless of Max rows. Up to 10,000 per run (about 1.2 s each).

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

Optional. NAF rev. 2 codes: "62.01Z" (or "6201Z"), a class "62.01", a division "62" (every code 62.xxx) or a section letter "J" (information and communication). Several values = any of them. Codes: https://www.insee.fr/fr/information/2406147

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

Optional. Department codes or names: "75", "69", "2A", "971", "Bouches-du-Rhône". Matches companies with at least one establishment there (not only the head office). Several values = any of them.

## `regions` (type: `array`):

Optional. Regions by name or INSEE code: "Île-de-France" (11), "Auvergne-Rhône-Alpes" (84), "Occitanie" (76), "PACA" (93), "Bretagne" (53) ... Former regions such as "Alsace" or "Rhône-Alpes" are turned into their departments. Combined with Departments as any of them.

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

Optional. 5-digit French postcodes, e.g. "75011", "69002", "13008". Matches companies with at least one establishment at that postcode. If you also give departments, a company matching either is returned.

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

Optional. INSEE legal-form codes or common names: "SAS" (5710), "SARL" (all 54xx), "SA", "SCI", "SNC", "SCOP", "SELARL", "GIE", "association", "fondation", a code "5710" or a prefix "54". Sole proprietors (EI, micro-entrepreneur, code 1000) and groupings without legal personality (2xxx) are never returned. Codes: https://www.insee.fr/fr/information/2028129

## `employeeBands` (type: `array`):

Optional. Ranges following the INSEE bands, e.g. "10-49", "50-249", "250+", "1-9", "0" (no employees), or INSEE codes (NN, 00, 01, 02, 03, 11, 12, 21, 22, 31, 32, 41, 42, 51, 52, 53).

## `companyCategories` (type: `array`):

Optional. INSEE size categories: PME (SME), ETI (mid-size), GE (large).

## `labels` (type: `array`):

Optional. Keep only companies with ALL of these: ess, rge, qualiopi, bio, siae, societe_mission, association, finess, uai, organisme_formation, egapro, patrimoine_vivant, achats_responsables, alim_confiance, entrepreneur_spectacle, collectivite_territoriale, administration, convention_collective.

## `status` (type: `string`):

Active companies (default), ceased ones, or both.

## `revenueMin` (type: `integer`):

Optional. Minimum latest published revenue (chiffre d'affaires) in euros, e.g. 1000000. Companies without published accounts are left out when this is set.

## `revenueMax` (type: `integer`):

Optional. Maximum latest published revenue in euros.

## `includeCorporateOfficers` (type: `boolean`):

Add officers that are companies (e.g. the statutory auditor firm or a holding acting as president): name, SIREN and role. Officers who are natural persons are never returned; only their number is given.

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

Maximum company rows from keyword/filter searches (1..200,000). You are charged per row. Large searches are split automatically past the API's 10,000-result limit; about 1,200 rows per minute.

## `maxApiRequests` (type: `integer`):

Safety cap on API requests for searches (1..20,000; 25 companies per request, at least 1.2 s apart). Each listed SIREN/SIRET adds one request on top. If the cap is reached the rows read so far are kept and the run says it is incomplete.

## Actor input object example

```json
{
  "keywords": [],
  "sirens": [],
  "nafCodes": [],
  "departments": [],
  "regions": [],
  "postalCodes": [],
  "legalForms": [],
  "employeeBands": [],
  "companyCategories": [],
  "labels": [],
  "status": "active",
  "includeCorporateOfficers": false,
  "maxItems": 20,
  "maxApiRequests": 500
}
```

# Actor output Schema

## `records` (type: `string`):

One row per French legal unit (SIREN) with the Licence Ouverte 2.0 attribution (source, sourceUrl, license, retrievedAt) on every item.

# 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 = {
    "keywords": [],
    "sirens": [],
    "nafCodes": [],
    "departments": [],
    "regions": [],
    "postalCodes": [],
    "legalForms": [],
    "employeeBands": [],
    "companyCategories": [],
    "labels": [],
    "status": "active",
    "includeCorporateOfficers": false,
    "maxItems": 20,
    "maxApiRequests": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("jpopendata/france-companies-sirene").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 = {
    "keywords": [],
    "sirens": [],
    "nafCodes": [],
    "departments": [],
    "regions": [],
    "postalCodes": [],
    "legalForms": [],
    "employeeBands": [],
    "companyCategories": [],
    "labels": [],
    "status": "active",
    "includeCorporateOfficers": False,
    "maxItems": 20,
    "maxApiRequests": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("jpopendata/france-companies-sirene").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 '{
  "keywords": [],
  "sirens": [],
  "nafCodes": [],
  "departments": [],
  "regions": [],
  "postalCodes": [],
  "legalForms": [],
  "employeeBands": [],
  "companyCategories": [],
  "labels": [],
  "status": "active",
  "includeCorporateOfficers": false,
  "maxItems": 20,
  "maxApiRequests": 500
}' |
apify call jpopendata/france-companies-sirene --silent --output-dataset

```

## MCP server setup

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

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/8E39sXJDmTjConmTk/builds/JXlxNnxnRnWWqoaZu/openapi.json
