# BOAMP France Public Tenders Scraper (`hermingway/boamp-tenders-scraper`) Actor

French public procurement tenders from BOAMP — appels d'offres, MAPA and award results, updated daily. Filter by sector, department, deadline, keywords; get clean JSON with buyer, deadline and direct notice links.

- **URL**: https://apify.com/hermingway/boamp-tenders-scraper.md
- **Developed by:** [Hermingway](https://apify.com/hermingway) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

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

## BOAMP France Public Tenders Scraper

**Veille automatisée des marchés publics français — appels d'offres, MAPA et avis d'attribution, en JSON propre.**
Automated monitoring of French public procurement — tender notices, MAPA procedures and award results, as clean JSON.

[**Run it on Apify →**](https://apify.com/hermingway/boamp-tenders-scraper)

***

### Pourquoi cet Actor ?

Chaque jour ouvré, environ 400 avis de marchés publics sont publiés sur BOAMP — près de 2 000 par semaine, 1,7 million depuis 2015. Les lire à la main est impossible ; les manquer coûte des contrats. Cet Actor interroge la source officielle (DILA / bulletin BOAMP) et rend chaque avis exploitable : acheteur, date limite de remise, objet, département, descripteurs — dans un JSON structuré, prêt pour votre veille, vos alertes ou votre CRM.

### Why this Actor?

- **Official data, no scraping fragility** — queries the DILA open-data mirror of the BOAMP bulletin. No proxies, no CAPTCHAs, no HTML parsing that breaks when the site redesigns.
- **Fast**: a Rust core fetches pages concurrently; a full sweep of the day's notices takes seconds, not minutes. Your compute bill stays tiny.
- **Server-side filtering**: département, market type, procedure family and BOAMP descripteur codes are filtered *at the source*, so you don't pay to download notices you'll throw away.
- **New-only alert mode**: schedule daily runs and get only notices you have never seen before — a monitoring feed, not a repeated scrape.

### Sample output

```json
{
  "idweb": "26-88433",
  "objet": "Accord-cadre à bons de commande relatif à l'acquisition de Dvd vidéo pour le réseau des bibliothèques de la Ville de Perpignan",
  "nomAcheteur": "Mairie de Perpignan",
  "nature": "APPEL_OFFRE",
  "natureLibelle": "Avis de marché",
  "famille": "FNS",
  "familleLibelle": "Marchés entre 90 k€ et seuils européens",
  "procedure": "Procédure Ouverte",
  "typesMarche": ["FOURNITURES"],
  "departements": ["66"],
  "descripteurs": ["Cd, DVD"],
  "descripteurCodes": ["45"],
  "dateParution": "2026-09-11",
  "dateLimiteReponse": "2026-10-09T12:00:00+00:00",
  "urlAvis": "https://www.boamp.fr/pages/avis/?q=idweb:26-88433"
}
```

### Example input configurations

**IT services tenders in Paris, deadline ahead:**

```json
{
  "nature": ["APPEL_OFFRE"],
  "descripteurs": ["163", "186"],
  "departements": ["75", "77", "78", "91", "92", "93", "94", "95"],
  "deadlineFrom": "2026-09-13"
}
```

**Construction works (Bâtiment, code 33) nationwide, published this week:**

```json
{
  "nature": ["APPEL_OFFRE"],
  "typeMarche": ["TRAVAUX"],
  "descripteurs": ["33"],
  "dateFrom": "2026-09-07"
}
```

**Daily award-notices alert (new-only mode):**

```json
{
  "nature": ["ATTRIBUTION"],
  "dateFrom": "2026-09-12",
  "newOnly": true
}
```

**Everything mentioning "informatique":**

```json
{
  "query": "informatique",
  "maxPages": 20
}
```

### Input fields

| Field | Type | Meaning |
|---|---|---|
| `nature` | list | Notice type: `APPEL_OFFRE` (call for tenders), `ATTRIBUTION` (award), `RECTIFICATIF`, `PRE-INFORMATION`, `MODIFICATION`, `ANNULATION`, `INTENTION_CONCLURE`, `EX_ANTE_VOLONTAIRE`, `AUTRE`. Default: APPEL\_OFFRE + ATTRIBUTION. |
| `famille` | list | `JOUE` (EU-threshold), `FNS` (90 k€ to EU thresholds, national), `MAPA` (below 90 k€), plus `DSP` (délégations de service public) and `DIVERS`. |
| `typeMarche` | list | `TRAVAUX` / `FOURNITURES` / `SERVICES`. |
| `departements` | list | Two-digit codes (`75` = Paris). Empty = all France. |
| `descripteurs` | list | BOAMP descripteur codes, filtered server-side. See table below. |
| `query` | string | Server-side full-text search on the notice. |
| `keywords` | list | Client-side OR filter on object + descriptors (applied after fetch). |
| `dateFrom` | date | Only notices published on/after (YYYY-MM-DD). |
| `deadlineFrom` | date | Only notices with response deadline on/after. |
| `maxPages` | int | Max API pages (100 notices/page). Default 5. |
| `maxItems` | int | Stop after N notices (0 = no limit). |
| `newOnly` | bool | Emit only notices never returned in any previous run of this Actor. State persists in the Actor's key-value store. First run returns everything — combine with `dateFrom` to start clean. |

### Common descripteur codes

| Code | Libellé |
|---|---|
| 33 | Bâtiment |
| 163 | Informatique (prestations de services) |
| 162 | Informatique (matériel) |
| 186 | Logiciel |
| 197 | Maîtrise d'oeuvre |
| 196 | Maintenance |
| 105 | Electricité (travaux) |
| 116 | Espaces verts |
| 144 | Gros oeuvre |
| 239 | Nettoyage de locaux |
| 138 | Gardiennage |
| 66 | Concession (services restauration) |

The full official vocabulary (370 codes) is on [data.boamp.fr](https://data.boamp.fr). The Actor also returns each notice's descripteur codes and labels in the output, so you can discover the codes relevant to your sector from real data.

### Field dictionary

| Output field | Always present | Meaning |
|---|---|---|
| `idweb` | ✅ | Unique BOAMP notice ID (e.g. `26-88433`). Use for dedup. |
| `objet` | ✅ | Notice subject/title. |
| `nomAcheteur` | ✅ | Buyer (entity that published the notice). |
| `urlAvis` | ✅ | Direct link to the notice on boamp.fr. |
| `dateParution` | ✅ | Publication date. |
| `nature` / `natureLibelle` | ✅ | Notice type code + label. |
| `famille` / `familleLibelle` | ✅ | Procedure family code + label. |
| `departements` | most | Département(s) of execution. |
| `dateLimiteReponse` | tender notices | Response deadline (ISO 8601). Absent on some award notices. |
| `descripteurs` / `descripteurCodes` | most | Activity descriptors, labels + codes. |
| `typesMarche` | most | TRAVAUX / FOURNITURES / SERVICES. |
| `procedure` | most | Procedure name (e.g. Procédure Ouverte). |
| `titulaires` | award notices | Winner(s) of the contract. |
| `criteres` | sometimes | Award criteria (e.g. environmental). |
| `dateFinDiffusion` | most | Last date the notice is published. |

### Limitations (read before you buy)

- **Sub-90k MAPA coverage is partial.** Publication on BOAMP is optional below €90,000 HT, so many small MAPA markets never appear — even though the dataset does carry hundreds of thousands of them. If your market is sub-90k public work, BOAMP cannot be your only source.
- **Buyer-profile-only notices are invisible.** Some entities publish exclusively on their own profil acheteur without a BOAMP notice.
- **Field richness varies.** Pre-2024 notices carry less structured detail than eForms-era notices; `dateLimiteReponse` is missing on some award notices.
- **No personal contact data.** The Actor returns the buyer organisation, never named individuals — no natural person's name appears in the output.
- Source: [DILA BOAMP open dataset](https://boamp-datadila.opendatasoft.com) — updated daily by the French government. This Actor is an independent tool and is not affiliated with DILA.

### FAQ

**Est-ce que l'Actor fonctionne pour la veille quotidienne ?**
Oui — programmez une exécution quotidienne avec `newOnly: true` et `dateFrom` d'hier : vous ne recevez que les nouveaux avis.

**Is this free to run?**
The underlying government dataset is free and public; the Actor charges only Apify platform compute, which is minimal thanks to the Rust core.

**Comment récupérer les appels d'offres BOAMP en JSON ?**
C'est exactement ce que fait cet Actor : chaque avis est rendu en JSON structuré (acheteur, objet, deadline, département, descripteurs) dans le dataset Apify, exportable en CSV/Excel/JSON ou via API.

**Does it cover EU-threshold (JOUE) notices?**
Yes — including notices also published on TED. Note that above-threshold notices appear in both BOAMP and TED; this Actor covers the BOAMP side.

**Can I get award results with winners?**
Yes — set `nature: ["ATTRIBUTION"]`. Award notices include `titulaires` when published.

### Changelog

- **2026-09-13** — Added BOAMP descripteur-code server-side filtering, cross-run new-only alert mode, and maxItems early-stop. Rewritten buyer-facing README.
- **2026-09-12** — Initial release: nature/famille/type-marche/département filters, keyword and full-text search, deadline and date filters, concurrent Rust fetcher.

### Links

- [Official BOAMP portal](https://www.boamp.fr) — the source bulletin
- [DILA BOAMP open dataset](https://boamp-datadila.opendatasoft.com) — the dataset this Actor queries
- [TED (Tenders Electronic Daily)](https://ted.europa.eu) — EU-level publication
- [data.boamp.fr](https://data.boamp.fr) — documentation of the descripteur vocabulary

***

*Acteur indépendant, non affilié au gouvernement français. Independent tool, not affiliated with the French government.*

# Actor input Schema

## `nature` (type: `array`):

Type of notice. APPEL\_OFFRE = call for tenders, ATTRIBUTION = award result, RECTIFICATIF = amendment, PRE-INFORMATION, MODIFICATION, ANNULATION, INTENTION\_CONCLURE.

## `famille` (type: `array`):

JOUE = EU directives, MAPA = procédure adaptée, FNS = national (arrêtés).

## `typeMarche` (type: `array`):

TRAVAUX = works, FOURNITURES = supplies, SERVICES = services.

## `departements` (type: `array`):

Two-digit French département codes (e.g. 75 = Paris). Leave empty for all France.

## `descripteurs` (type: `array`):

Official BOAMP activity codes, filtered server-side (precise, faster than keywords). Common codes: 33=Bâtiment, 163=Informatique (prestations), 162=Informatique (matériel), 186=Logiciel, 197=Maîtrise d'oeuvre, 196=Maintenance, 105=Electricité (travaux), 116=Espaces verts, 239=Nettoyage de locaux, 138=Gardiennage. Full 370-code list linked in the README.

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

Server-side free-text search over the notice (ODS search()). Example: 'construction'

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

Keep only notices whose title or descriptors contain at least one keyword (case-insensitive). Matched after fetching, so it reduces the dataset, not the API pages.

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

Only notices published on/after this date (YYYY-MM-DD). Leave empty for all.

## `deadlineFrom` (type: `string`):

Only notices whose response deadline is on/after this date (YYYY-MM-DD). Leave empty for all.

## `maxPages` (type: `integer`):

Maximum number of API pages to fetch (100 notices per page).

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

Maximum number of tenders to save (0 = no limit).

## `concurrency` (type: `integer`):

Parallel page fetches (default 4).

## `newOnly` (type: `boolean`):

Only emit notices never returned in any previous run of this Actor (state kept in the Actor's key-value store). Use with a daily schedule to get only fresh opportunities. Note: the first run with this enabled returns everything, so set a dateFrom like yesterday's date to start clean.

## Actor input object example

```json
{
  "nature": [
    "APPEL_OFFRE",
    "ATTRIBUTION"
  ],
  "famille": [],
  "typeMarche": [],
  "departements": [],
  "descripteurs": [],
  "query": "",
  "keywords": [],
  "dateFrom": "",
  "deadlineFrom": "",
  "maxPages": 5,
  "maxItems": 0,
  "concurrency": 4,
  "newOnly": false
}
```

# Actor output Schema

## `results` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("hermingway/boamp-tenders-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("hermingway/boamp-tenders-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 '{}' |
apify call hermingway/boamp-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hermingway/boamp-tenders-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/Uvav5XD1yXt0hk4Oa/builds/9LaygAaQu3CE4vYg0/openapi.json
