# BODACC Commercial Announcements Scraper (France) (`steadfetch/bodacc-monitor`) Actor

Structured French BODACC announcements as JSON: company, family, court, department and publication date, with family/department/date filters and a company watchlist monitor. For KYB, supplier vetting and liquidation judiciaire alerts. Official DILA open data, legal entities only.

- **URL**: https://apify.com/steadfetch/bodacc-monitor.md
- **Developed by:** [Steadfetch](https://apify.com/steadfetch) (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 $1.60 / 1,000 notice delivereds

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/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

## steadfetch/bodacc-monitor

French BODACC commercial announcements as structured JSON, plus a monitor that
delivers only new notices for the companies or departments you watch.

### What it does

BODACC (*Bulletin officiel des annonces civiles et commerciales*) is the
official French register of commercial announcements: company creations,
filings, insolvency proceedings, business sales, changes and deregistrations.
The public Opendatasoft dataset holds more than 51 million records with no
saved filters, no alerts and no ready-made monitor.

This Actor turns it into a product:

- one structured row per announcement: company, family, notice type, court,
  city, postal code, department, publication date and the official notice URL;
- filters by notice family, French department and publication date window;
- free-text search over the notice;
- **monitor mode**: watch a company name (and optionally a department or
  family) and receive only notices never delivered before, deduplicated by
  the official notice id.

Public official data only: no login, no CAPTCHA, no paywall. Source: DILA -
BODACC, licence Etalab 2.0 (retrieved 2026-10-25).

#### Legal entities only (privacy)

BODACC also publishes sole traders (*personnes physiques*), whose notices carry
personal names. This Actor delivers **legal entities only**: a record is
emitted only when its `listepersonnes` payload proves `typePersonne: "pm"` for
every person in the notice **and** its `commercant` name carries no sole-trader
marker. DILA sometimes labels an *entreprise individuelle* (EI) as `pm`, so a
civil title (`Monsieur`, `Madame`, `Mme`, `Mlle`) or a trailing `EI` / `E.I.`
also excludes the row. Sole-trader rows and rows without that proof are
excluded before validation, never reach the dataset and are never charged. No
personal-name field exists in the output schema.

Residual risk: a sole trader published by DILA with a `pm` label, no civil
title and no `EI` marker in `commercant` would pass. The rule is deterministic
and tested against the captured rows; it does not guess at names.

### Example output

```json
{
  "url": "https://bodacc-datadila.opendatasoft.com/api/v2/catalog/datasets/annonces-commerciales/records?limit=100&offset=0&order_by=dateparution+desc",
  "scrapedAt": "2026-10-25T20:00:00.000Z",
  "noticeId": "A20260205241",
  "company": "ESPACE AUTOMATISMES",
  "noticeFamily": "Ventes et cessions",
  "noticeType": "Avis initial",
  "court": "Greffe du Tribunal de Commerce de Saintes",
  "city": "Cozes",
  "postalCode": "17120",
  "department": "Charente-Maritime",
  "publicationDate": "2026-10-25",
  "sourceUrl": "https://www.bodacc.fr/pages/annonces-commerciales-detail/?q.id=id:A20260205241"
}
```

### Input

| Field | Type | Meaning |
| --- | --- | --- |
| `mode` | `search` or `monitor` | Search once, or check a watchlist. |
| `fulltext` | string | Free-text search (company, activity, keyword). |
| `noticeFamily` | string | Exact BODACC family, e.g. `Ventes et cessions`, `Modifications diverses`, `Radiations`, `Immatriculations`. The Store form lists every family label (some keep their French accents). Empty means all families. |
| `department` | string | French department code (`06`, `31`, `2A`, `971`) or official name (`Alpes-Maritimes`). |
| `dateFrom`, `dateTo` | `YYYY-MM-DD` | Publication date window. Empty means no bound. |
| `watchlist` | array | Monitor mode: `{ "keyword": "KAOLY", "department": "06", "noticeFamily": "Ventes et cessions" }`. `keyword` is required; the other two fall back to the top-level values. One check is billed per watchlist item per run. |
| `maxRows` | integer | 1-1,000. Output cap; in monitor mode it also caps how many new notices are delivered per run. |
| `strictSchema` | boolean | Keep enabled: every row is validated against the output schema. |

#### Monitor mode

Each watch item searches the company name (`commercant`, case-insensitive
contains; `*` is not allowed in the keyword), optionally narrowed by department
and family. The Actor stores the delivered notice ids in its named key-value
store and emits only ids never seen before. New notices beyond `maxRows` stay
unseen and are delivered on a later run.

### Pricing

Pay per event, no subscription:

- **2.00 USD per 1,000 results** (notices delivered) - charged by the platform
  through `apify-default-dataset-item`, the only per-result charge. Rows
  rejected by the output schema, sole-trader rows and quiet monitor checks are
  never charged.
- **0.05 USD per 1,000 checks** (watchlist items) - charged through the reserved
  `monitor-check` event once per watchlist item actually checked in a monitor
  run. Search runs never charge this event. A check with no new notice still
  costs the check only.
- **0.00005 USD per run start** - the Apify-recommended `apify-actor-start`
  price, which also includes the first 5 seconds of compute.

On the Apify free plan (5 USD monthly credit) that is about 2,500 delivered
notices at 2.00 USD per 1,000 results, before the per-check charge.

**Measured cost:** the official JSON API needs no proxy and no browser. One
request returns 100 records, so a 1,000-notice run is 11 requests; the Actor
runs at 256 MB and finishes in a few seconds locally, i.e. about **0.0001 USD
per 1,000 notices** of platform compute. Margin against the 2.00 USD price is
positive.

### FAQ

**Is this scraping?** No browser and no HTML scraping: it reads the official
public Opendatasoft API published by DILA, under the Etalab 2.0 licence. Each
row keeps the public bodacc.fr notice URL for attribution.

**Why are some notices missing?** Notices about sole traders (*personnes
physiques*), including *entreprises individuelles* that DILA labels `pm`, are
excluded on purpose (privacy). They are dropped before validation, so they
never reach the dataset or the bill.

**How do I monitor insolvency proceedings in one department?** Set
`mode: "monitor"`, `department: "06"` and `noticeFamily` to the insolvency
family label shown in the Store form, then add the companies you watch. Use a
`maxRows` large enough for a day of new notices.

**Can I get every notice ever published?** The API caps a single query at
10,000 records (`offset + limit`). Use date windows to page through history;
`maxRows` caps each run at 1,000 delivered rows.

**Which departments use a code?** Metropolitan departments use two digits
(`06`, `31`), Corsica uses `2A`/`2B` and overseas departments use three digits
(`971`). An official name also works.

### Maintenance

Tested daily by Steadfetch. The source is the official DILA Opendatasoft API
(no HTML layout to break). If the dataset schema or the API changes, the
schema validation and the daily QA run fail loudly; the Actor is fixed before
new features. Only `bodacc-datadila.opendatasoft.com` is requested; the
`sourceUrl` field is returned, never crawled.

# Actor input Schema

## `mode` (type: `string`):

search returns the newest matching notices. monitor checks each watchlist item and delivers only notices never seen before.

## `fulltext` (type: `string`):

Free-text search across the notice (company name, activity, keyword). Leave empty to browse the chosen family.

## `noticeFamily` (type: `string`):

Exact BODACC family, e.g. "Procédures collectives", "Créations", "Ventes et cessions", "Modifications diverses", "Radiations", "Immatriculations", "Dépôts des comptes". Empty means all families.

## `department` (type: `string`):

French department code (06, 31, 2A, 971) or official name (Alpes-Maritimes). Empty means all departments.

## `dateFrom` (type: `string`):

Lower bound of the publication date (ISO). Empty means no lower bound.

## `dateTo` (type: `string`):

Upper bound of the publication date (ISO). Empty means no upper bound.

## `watchlist` (type: `array`):

Required in monitor mode. One check is billed per watchlist item per run. Each item: { "keyword": "KAOLY", "department": "06", "noticeFamily": "Procédures collectives" } (department and noticeFamily are optional and fall back to the top-level values).

## `maxRows` (type: `integer`):

Maximum number of validated notices to push to the dataset (and, in monitor mode, the most new notices delivered per run).

## `strictSchema` (type: `boolean`):

Fail the run when an item does not match the OUTPUT schema. Keep enabled: Steadfetch never publishes Actors without output-schema validation.

## Actor input object example

```json
{
  "mode": "search",
  "fulltext": "",
  "noticeFamily": "Procédures collectives",
  "department": "",
  "dateFrom": "",
  "dateTo": "",
  "watchlist": [],
  "maxRows": 10,
  "strictSchema": true
}
```

# Actor output Schema

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

Dataset items validated against the item schema in dataset_schema.json (fields).

# 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 = {
    "mode": "search",
    "fulltext": "",
    "noticeFamily": "Procédures collectives",
    "department": "",
    "dateFrom": "",
    "dateTo": "",
    "watchlist": [],
    "maxRows": 10,
    "strictSchema": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadfetch/bodacc-monitor").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 = {
    "mode": "search",
    "fulltext": "",
    "noticeFamily": "Procédures collectives",
    "department": "",
    "dateFrom": "",
    "dateTo": "",
    "watchlist": [],
    "maxRows": 10,
    "strictSchema": True,
}

# Run the Actor and wait for it to finish
run = client.actor("steadfetch/bodacc-monitor").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 '{
  "mode": "search",
  "fulltext": "",
  "noticeFamily": "Procédures collectives",
  "department": "",
  "dateFrom": "",
  "dateTo": "",
  "watchlist": [],
  "maxRows": 10,
  "strictSchema": true
}' |
apify call steadfetch/bodacc-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadfetch/bodacc-monitor"
        }
    }
}
```

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/zNOR6gix3czxYYPUF/builds/6ovobZZdKsUPVHuMc/openapi.json
