France BOAMP Public Tenders Scraper avatar

France BOAMP Public Tenders Scraper

Pricing

$3.00 / 1,000 notice returneds

Go to Apify Store
France BOAMP Public Tenders Scraper

France BOAMP Public Tenders Scraper

French public procurement tenders from the official BOAMP open-data API (DILA/Opendatasoft): buyer, deadline, CPV codes, department, contact email.

Pricing

$3.00 / 1,000 notice returneds

Rating

0.0

(0)

Developer

Jason

Jason

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Pulls French public procurement notices from BOAMP (Bulletin officiel des annonces de marchés publics), the French government's official tender bulletin, through its open-data API on the DILA / Opendatasoft portal. No API key, no account, no browser automation. You get one flat JSON record per notice with the buyer, the publication date, the response deadline, the market type (works / supplies / services), the notice type, the department code(s), the region (derived from the department), the city, the CPV-style descriptor codes and labels, and the buyer's contact name and e-mail where the notice publishes them - filtered by publication-date window, keyword, market type, department, region, buyer name and response deadline. On 10 September 2026 the dataset held 1,704,443 notices going back to a publication date of 2 March 2015, and BOAMP publishes roughly 400 notices per business day (399 on 9 September 2026).

What you get

Every record contains:

FieldDescription
idBOAMP notice id (idweb), for example 26-87284
sourceboamp, constant
urlThe public notice page, e.g. https://www.boamp.fr/pages/avis/?q=idweb:26-87284 (the API's own url_avis)
titleThe subject (objet), trimmed to 200 characters on a word boundary
buyerNameThe contracting authority (nomacheteur), e.g. FRANCE TRAVAIL - IdF
publicationDateDate the notice was published (dateparution), YYYY-MM-DD
deadlineResponse deadline (datelimitereponse) as an ISO timestamp with timezone, or null when the notice has none (award and result notices)
marketTypeArray of market types: TRAVAUX (works), FOURNITURES (supplies), SERVICES. Empty when the notice carries none (some corrigenda/results)
natureTypeNotice type in French, e.g. Avis de marché, Rectificatif, Résultat de marché, Modification
noticeStateThe notice's state (etat), e.g. INITIAL
procedureTypeThe procurement procedure label (procedure_libelle), e.g. Procédure Adaptée, or null
departmentArray of French department codes (code_departement), e.g. ["93","75","77","92","94","95"]
regionRegion name derived from the department code(s), e.g. Île-de-France; multiple regions are joined with ; (see Limits and freshness)
cityThe buyer's city, read from the notice body (donnees); null when the notice omits it
cpvCodesArray of BOAMP descriptor codes (descripteur_code), the CPV-style subject codes, e.g. ["274"]
cpvLabelsThe matching descriptor labels (descripteur_libelle), e.g. ["Prestations de services"]
contactNameThe buyer's published contact person or service, read from the notice body; null when none is published
contactEmailThe buyer's published contact e-mail, read from the notice body; null when none is published or the value is not a well-formed address
descriptionThe full subject (objet), untrimmed
fetchedAtISO timestamp of the run that produced the record

city, contactName and contactEmail are read out of each notice's source form (donnees), whose shape differs by notice family - the national MAPA and FNS forms keep them under organisme, and the EU eForms (JOUE) notices reference the buyer by an organisation id that the Actor resolves to that organisation's own address and contact, never the publishing platform's. The dataset has two views: Overview (dates, buyer, market type, department, region, city, CPV, link) and Buyer contacts (buyer, contact name, e-mail, city, region, deadline, link).

Input

InputTypeDefaultDescription
daysBackinteger3Look-back window in days on the publication date, ending today. Ignored when dateFrom/dateTo are set. Max 3,660.
dateFromstring-Start of the publication-date window, YYYY-MM-DD, inclusive. Overrides daysBack.
dateTostringtodayEnd of the publication-date window, YYYY-MM-DD, inclusive.
keywordsstring[]noneTerms matched against the subject and the buyer name with BOAMP's full-text search, which matches whole words (so eau does not match bureau). Terms are ORed.
marketTypesstring[]allAny of Travaux, Fournitures, Services. Notices with no market type are excluded when this is set.
departmentsstring[]allFrench department codes, e.g. 75, 13, 2A, 971, 973. A notice is kept when any of its departments matches.
regionsstring[]allRegion names, matched as a case-insensitive substring of the derived region, e.g. Bretagne, Occitanie, Île-de-France. Terms are ORed.
buyersstring[]anyBuyer-name terms matched against nomacheteur with the full-text search, e.g. mairie, metropole. Terms are ORed.
deadlineAfterstring-Keep only notices whose response deadline is on or after this date, YYYY-MM-DD. Notices with no deadline are excluded when this is set.
maxItemsinteger500Stop after this many notices. You are charged per notice, so this is also the cost cap. Newest publication date first, so a value below the window's volume drops the oldest notices in the window.

The default of 500 is a little above one business day's volume (about 400), so a daily run with the defaults captures a full day with headroom. Keyword, market-type, department, buyer and deadline filters are applied by the BOAMP API; the region filter is applied locally to the derived region.

Example - open works and supplies tenders in Île-de-France published in the last week, with a deadline still to come:

{ "daysBack": 7, "marketTypes": ["Travaux", "Fournitures"], "regions": ["Île-de-France"], "deadlineAfter": "2026-09-20", "maxItems": 500 }

Example - a daily watch on every IT-related notice, run on a schedule:

{ "daysBack": 2, "keywords": ["informatique", "logiciel", "cloud"], "maxItems": 200 }

Example - every notice from a set of departments over a quarter:

{ "dateFrom": "2026-06-01", "dateTo": "2026-09-01", "departments": ["75", "92", "93", "94"], "maxItems": 5000 }

Bad input fails fast: an unknown market type, a malformed department code or a malformed date stops the run with the validation message as its status, before any request is made.

Output example

A real record from a live run on 10 September 2026 ({"daysBack": 2, "maxItems": 5}), unedited:

{
"id": "26-87284",
"source": "boamp",
"url": "https://www.boamp.fr/pages/avis/?q=idweb:26-87284",
"title": "PRESTATION DE SERVICE SOCIALE AU BENEFICE DES AGENTS DE FRANCE TRAVAIL ILE DE FRANCE PUBLIC ET PRIVE",
"buyerName": "FRANCE TRAVAIL - IdF",
"publicationDate": "2026-09-09",
"deadline": "2026-10-13T16:00:00+00:00",
"marketType": ["SERVICES"],
"natureType": "Avis de marché",
"noticeState": "INITIAL",
"procedureType": "Procédure Adaptée",
"department": ["93", "75", "77", "92", "94", "95"],
"region": "Île-de-France",
"city": "MONTREUIL",
"cpvCodes": ["274"],
"cpvLabels": ["Prestations de services"],
"contactName": "Nacéra Djelti",
"contactEmail": "nacera.djelti@francetravail.fr",
"description": "PRESTATION DE SERVICE SOCIALE AU BENEFICE DES AGENTS DE FRANCE TRAVAIL ILE DE FRANCE PUBLIC ET PRIVE",
"fetchedAt": "2026-09-10T00:15:09.032Z"
}

An EU-threshold notice (family JOUE, published as eForms) looks the same: for example 26-86644, buyer MAIRIE DE GISORS, region Normandie, city Gisors, contactEmail direction.generale@mairie-gisors.fr resolved from the buyer's own organisation block rather than the publishing platform's.

Every run also writes a SUMMARY record to the key-value store with the resolved date window, the filters used, how many records the local region filter dropped, the number of pages read, and the windowExhausted completeness flag (see Limits and freshness).

Pricing

Pay per result: US$0.003 per notice delivered (US$3 per 1,000 notices). You are charged only for records pushed to the dataset; a run that returns nothing costs nothing. Runs on the Apify free plan are limited by the platform's free-tier usage allowance.

Data source and licence

  • Endpoint. GET https://boamp-datadila.opendatasoft.com/api/explore/v2.1/catalog/datasets/boamp/records, the Opendatasoft Explore v2.1 API for DILA's BOAMP dataset. Public, no authentication. Dataset page: https://boamp-datadila.opendatasoft.com/explore/dataset/boamp/ (read 10 September 2026).
  • Licence. BOAMP open data is published under the Licence Ouverte / Open Licence 2.0 (Etalab), https://www.etalab.gouv.fr/licence-ouverte-open-licence/ (read 10 September 2026). It permits reuse for any purpose, including commercial reuse, provided the source and the date of the last update are acknowledged. Attribute as "Source: DILA / BOAMP, Licence Ouverte 2.0" and link to the notice page.
  • Personal data. contactName and contactEmail are the contact each contracting authority publishes on its own notice so that suppliers can ask questions and submit bids - sometimes a named officer (Nacéra Djelti), often a service or a shared mailbox (marchespublics@…). BOAMP publishes them lawfully as part of the official bulletin. Using them for anything other than responding to the tender - marketing in particular - is the buyer's responsibility under the applicable regime (the GDPR and the French loi Informatique et Libertés for contacts in France). Some notices also name individuals in the subject text.

Limits and freshness

  • Volumes, measured 10 September 2026 with this Actor's own date filter: notices with a publication date in the last 1 full day (9 September) - 399; last 3 days - 697; last 7 days - 1,683; last 30 days - 7,704. That is roughly 400 per business day. A single keyword narrows it sharply: informatique over the last 30 days returned 104; department 75 over the last 7 days, 163. The whole dataset was 1,704,443 notices back to a publication date of 2 March 2015.
  • Size maxItems to the window, and check windowExhausted. maxItems counts records delivered and the stream is newest-first on publication date, so a value below the window's volume drops the oldest notices in it - but never silently. The run stops when the cap is filled and warns maxItems (N) was reached before the window was exhausted, and the SUMMARY record carries limitReached: true with windowExhausted: false. windowExhausted: true is the guarantee that you hold the complete window: it is set only when the run read every matching notice and delivered every record it kept.
  • The 10,000-row offset ceiling is handled for you. The Explore API refuses offset + limit > 10000 (verified 10 September 2026). A window with more matches than that - about 25 days at the current rate, or fewer with looser filters - is walked in date sub-windows: when the offset ceiling is reached the Actor re-anchors the upper date bound on the oldest publication date seen and continues, de-duplicating the re-read boundary date by idweb. So an arbitrarily deep window is delivered complete and in order; only a single day holding more than ~9,900 matching notices (never observed - the busiest day seen was 399) would be unreachable, and the run warns if that ever happens.
  • Speed, measured 10 September 2026. A complete 3-day window of 697 notices (7 pages of 100) delivered in 11.3 s; a capped run of 300 notices (3 pages) in 6.1 s - roughly 60 notices a second, paging included. A full 30-day window of about 7,700 notices takes on the order of two to three minutes.
  • Rate limits. The Actor requests one 100-row page at a time and retries 429 and 5xx responses with exponential back-off, honouring Retry-After (via the shared fetchWithRetry). No documented hard quota was hit in testing.
  • Missing values are the notice's, not the Actor's. deadline is null for award and result notices, which have no response date; marketType is empty on some corrigenda and results; contactName is absent on the FNS simplified form, which carries no correspondant; city and contactEmail are present on most notices but not all. These stay null/empty rather than being guessed. contactEmail is returned only when the published value is a well-formed address.
  • Freshness. Notices appear on business days; the newest publication date on 10 September 2026 was 9 September, with nothing yet published for the 10th at run time. Run an overlapping window (daysBack: 2 daily) rather than one that exactly abuts the previous run. A notice is corrected in place with a Rectificatif/Modification notice carrying its own idweb, so re-run with an overlap to catch changes.

Use cases

  • Bid pipeline for a supplier or contractor: a scheduled daily run over your departments or regions and market type, with the deadline, cpvCodes and the buyer's contact e-mail already on the record, so a bid/no-bid call takes minutes.
  • Lead generation for firms that sell to the public sector: filter by keywords and buyers, and use buyerName, city, contactName and contactEmail to reach the contracting authority behind each notice.
  • Public-procurement research and dashboards: pull a full quarter or year by publication date and analyse spend intentions by region, department, CPV code, market type or buyer across France's 1.7-million-notice archive back to 2015.

Support

Open an issue on the Actor's page on Apify Store. Issues are answered within 14 days, as the Store terms require. Bug reports that name the run id and the input used are fixed fastest.