Mentions Legales Scraper - French SIREN, RCS, TVA & Contacts
Pricing
$4.00 / 1,000 per legal-notice lead returneds
Mentions Legales Scraper - French SIREN, RCS, TVA & Contacts
Turn French business domains into registry-grade B2B leads from each site's legally-mandated mentions legales page: SIREN, SIRET, RCS + greffe, TVA, capital social, APE, directeur de la publication, hebergeur, email, phone and address. No login, no API key.
Pricing
$4.00 / 1,000 per legal-notice lead returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
🇫🇷 Mentions Légales Scraper — French company leads with a Luhn-checked SIREN
Paste a list of French business domains (or point this Actor at another Actor's dataset) and get back one clean B2B/KYB lead per domain, read off each site's statutory mentions légales page: the legal entity name and form, the SIREN checked against the Luhn algorithm, the SIRET, the RCS entry + greffe, the TVA intracommunautaire number, the capital social, the APE/NAF code, the directeur de la publication, the hébergeur, and a contact email, phone and postal address — for $4 per 1,000 leads.
Why a legal notice and not a directory? Because LCEN art. 6-III (loi n° 2004-575) obliges every commercial French website to publish one. The corpus is therefore the whole French commercial web — not one directory's member list — and every field is a public disclosure the company published about itself, by law.
✅ What does the Mentions Légales Scraper do?
For each domain you give it, two plain HTTP hops. No browser, no login, no API key.
- Discovery. Fetch the homepage and rank every
<a href>on both its href and its anchor text — exact "Mentions légales" (100) beats a text match (90) beats anhrefmatch (85) beats "Informations légales" (80) beats "Legal notice" (70), with CGV / CGU / cookies / privacy links demoted to 30 so a combined footer link can still be a last resort without outranking the real thing. If nothing is linked, fall through to the XML sitemap, the WordPress REST page index, then 15 conventional paths. - Resolution. Fetch the winning candidate, gate it on a statutory content marker — a bare HTTP 200 is not enough — then read the fields out of the page text with anchored, case-sensitive patterns.
The four things a naive legal-notice scraper gets wrong
- 🎯 Guessing
/mentions-legalesis not the job. On the recon corpus a naive path guess hit 2 of 10 domains. Ranked footer anchors won 73 of the 76 leads in the benchmark below; guessed paths won 2 and the sitemap won 1. The engineering is in the ranking, not the guessing. - 🧮 It derives the SIREN from the TVA number, then Luhn-checks it. A French TVA number is
FR+ a 2-digit key + the SIREN, so it is an exact algebraic container for the registry id. Ondelitaly.fra plain RCS regex pulled a 9-digit window out of the TVA string and emitted SIREN624223821for a company whose real SIREN is422382184. This Actor prefers TVA → labelled SIREN → SIRET → RCS, records the disagreement insirenConflict, and emitssirenValidso you can see the checksum result rather than trust it silently. - 📍 The postcode comes from the parsed address, never from the page. A page-wide
\d{5}scan once emitted Beverly Hills'90210for a company in Toulouse (31100).postalCodeandcityare only ever read out of an address block that also carried a street. - 🏛 An RCS number that disagrees with the SIREN is dropped, not published. By French law the RCS registration number is the company's SIREN. When they differ, the RCS statement on the page belongs to another entity — usually the web agency that built the site — so publishing it as this company's register entry would be wrong. The greffe city is kept, the mismatched number is moved to
rcsConflict.
📊 Measured, from real runs
Everything below is from actual runs, not estimates.
End-to-end over 150 real French SME domains
Sourced from OpenStreetMap (shop / office / craft entries carrying a website tag) across Paris, Toulouse, Bordeaux, Nantes, Strasbourg, Marseille and Lille — a realistic buyer list, not a hand-picked one. Apify datacenter proxy, concurrency 12, default settings.
| Outcome | Domains | Share | Billed? |
|---|---|---|---|
✅ ok — a parsed, billable lead | 76 | 51 % | yes |
🔁 duplicate — same SIREN as a row already delivered | 3 | 2 % | no |
⚪ no_legal_page — the site publishes none | 53 | 36 % | no |
💀 unreachable — dead host (NXDOMAIN / TLS / refused) | 15 | 10 % | no |
🔴 blocked by an anti-bot wall | 2 | 1 % | no |
134 of the 149 domains were reachable; 79 of those 134 (59 %) published a findable legal notice, and 76 became billable leads after the SIREN-level dedupe. One duplicated input line was collapsed before it cost a request. A second run of the same list a few hours earlier returned 81 leads — expect a few points of run-to-run variance from transient host failures.
A tighter, curated 76-domain recon corpus scored higher — 46 of 62 reachable domains = 74 %. Both numbers are real; which one you see depends on how clean your list is. Budget somewhere between them.
Per-field fill, over the 76 delivered leads
| Field | Fill | Field | Fill | |
|---|---|---|---|---|
companyName | 97 % | socialLinks | 72 % | |
addressLine | 92 % | legalForm | 63 % | |
postalCode | 92 % | shareCapital | 58 % | |
city | 92 % | publicationDirector | 50 % | |
email | 76 % | hostingProviderAddress | 46 % | |
phone | 76 % | privacyPolicyUrl | 45 % | |
siren | 71 % | siret | 41 % | |
hostingProvider | 71 % | rcsNumber | 38 % | |
vatNumber | 34 % | cgvUrl | 30 % | |
rcsCity | 29 % | apeCode | 24 % | |
legalRepresentative | 20 % | dpoContact | 11 % |
Any registry id (SIREN, SIRET or TVA): 71 % · any contact (email or phone): 92 % · postal address: 92 %. Median row carries 11 of the 17 value fields (p90 = 14, best = 15).
The SIREN was derived from the TVA number on 26 rows, from the SIRET on 15, from the RCS entry on 7 and from an explicit label on 6. 53 of the 54 SIRENs passed the Luhn checksum; the one failure is flagged sirenValid: false rather than dropped. The cross-field guards fired for real: 1 sirenConflict and 5 rcsConflict rows would have shipped another company's register entry without them.
Transport
Sustained-load tested on the winning transport (got-scraping over the Apify datacenter proxy, ~350 sequential calls in 4 independent batches): 61 of 62 reachable domains usable = 98.4 %, with zero 403s, zero CAPTCHAs and zero challenge interstitials across the SME corpus. Residential exit nodes changed nothing there, so datacenter is the default and residential is a per-block escalation, not the norm. Chromium is never launched. 512 MB, 847 requests for 149 domains ≈ 5.7 requests per domain; 20 blocks escalated to residential, 2 recovered.
Per-domain latency on delivered rows: p50 4.5 s, p90 13.5 s, max 36.3 s — which is why perDomainTimeoutSecs exists.
⚠️ Honest limits — read these before you buy
- Roughly a third of reachable French SME sites publish no legal notice at all. That is not a parser gap: those domains were re-probed through the sitemap (287- and 500-URL sitemaps read), the WordPress REST index, 15 guessed paths and
/,/contact,/cgv,/conditions-generales-de-vente,/a-propos. They carry no SIREN, SIRET, TVA, RCS, capital or directeur de la publication anywhere on the site. They are LCEN-non-compliant micro-businesses. You are never charged for them. - Stale lists have dead hosts. 15 of 149 domains (10 %) did not resolve at all — verified identical from a home IP, a datacenter IP and a residential-FR IP, so these are stale directory entries, not blocks. Never charged.
- A CDN-fronted enterprise tail is genuinely walled. Of 10 large French brands probed, datacenter cleared 6 and residential-FR cleared 7;
leroymerlin.fr,fnac.com,decathlon.frandboulanger.comrefused both. This Actor is built for the SME long tail, which is unaffected.Escalate to residential on blockis on by default and is what recovers the middle of that band. - This Actor does not confirm the SIREN against INSEE/Sirene. It reports what the company published, plus a checksum. A registry cross-check is a different data source and a different job.
legalRepresentative(gérant / président) fills on ~20 % of pages — French legal notices name the directeur de la publication far more often than the company officer.
🧾 Output
One row per domain. flattenOutput (default on) gives you flat columns for Sheets / Clay; turn it off for nested registry{} / people{} / contact{} / hosting{} / policies{} objects.
| Field | Description |
|---|---|
domain | Registrable domain (eTLD+1, www-stripped) — the fallback stable id. |
mentionsLegalesUrl | The exact page the data came from. |
discoveryChannel | anchor · sitemap · wpjson · guess · input — how the page was found. |
companyName | The legal entity name. |
legalForm | SAS · SASU · SARL · EURL · SA · SNC · SCI · SELARL · SCOP · EI · association loi 1901 · micro-entreprise. Matched case-sensitively, longest form first (SAS is never read as SA). |
siren | The 9-digit registry id. |
sirenValid | Luhn checksum result. false means the page carries a typo — the row is flagged, never silently dropped. |
sirenSource | vat · label · siret · rcs — which statement the SIREN came from. |
sirenConflict | A second, disagreeing SIREN found on the page (the cross-field trap, surfaced instead of hidden). |
siret | The 14-digit establishment id. |
vatNumber | TVA intracommunautaire, normalised (FR 62 422 382 184 → FR62422382184). |
rcsCity / rcsNumber | Greffe (register court) and the RCS registration number, cross-checked against the SIREN. |
rcsConflict | An RCS number that disagreed with the SIREN — kept visible, not published as the company's. |
shareCapital / shareCapitalCurrency | Capital social as a number ("2.500 €" → 2500, EUR). |
apeCode | APE / NAF activity code (7733Z). |
publicationDirector | Directeur / directrice de la publication. |
legalRepresentative | Gérant · président · représentant légal · dirigeant. |
hostingProvider / hostingProviderAddress | The hébergeur — OVH, Scaleway, Ionos, o2switch, Gandi, Infomaniak, Hostinger, Wix, Shopify, Cloudflare, AWS… A resellable technographic signal. |
dpoContact | Délégué à la protection des données (GDPR/KYB buyers). |
addressLine / postalCode / city | Registered address, parsed as a block. |
email / emails[] | Contact addresses, mailto: preferred, obfuscated (at) forms decoded. |
phone / phones[] | Normalised to E.164 (01 23 45 67 89 → +33123456789). |
socialLinks[] | LinkedIn / Facebook / Instagram / X / YouTube / TikTok / Vimeo profiles on the page. |
cgvUrl / privacyPolicyUrl | The site's CGV and politique de confidentialité. |
stableId | The Luhn-valid SIREN when present, else the registrable domain. The dedupe key. |
fieldCount · status · missReason · fetchedAt · elapsedMs | Row quality, outcome and provenance. |
Example row (share-wood.fr, real output):
{"domain": "share-wood.fr","mentionsLegalesUrl": "https://share-wood.fr/mentions-legales/","discoveryChannel": "anchor","companyName": "SHARE-WOOD","legalForm": "SAS","siren": "433115904", "sirenValid": true, "sirenSource": "vat","vatNumber": "FR35433115904","rcsCity": "Paris", "rcsNumber": "433115904","shareCapital": 214410.5, "shareCapitalCurrency": "EUR","apeCode": "7733Z","publicationDirector": "Romain ABBÜHL","hostingProvider": "SCALEWAY","hostingProviderAddress": "8 RUE DE LA VILLE L EVEQUE, 75008 PARIS","addressLine": "47, Boulevard Burel, 13014 Marseille","postalCode": "13014", "city": "Marseille","email": "contact@share-wood.fr", "phone": "+33465430300","stableId": "433115904", "status": "ok"}
⌨️ Input
Five ways to hand over a list, because agencies do not all work the same way.
| Field | What it is |
|---|---|
domains | One entry per company. A bare domain (donatek.fr), a homepage URL, or a direct mentions-légales URL — a direct URL skips the homepage hop entirely and costs one request. |
startUrls | The standard Apify request-list editor, so Make / Zapier / Google Sheets can hand over a URL list natively. |
sourceDatasetId + domainFieldName | Read the domain list straight out of another Actor's dataset — the real agency workflow: enrich the output of a Maps or directory scrape. |
domainsFileUrl | A CSV / TXT / JSON / JSONL file at a URL, for lists too big to paste. The column is found by header name or by looking like a domain. |
skipDomains + previousDatasetId | Suppression. Point previousDatasetId at last month's run and this month's re-run never re-buys a lead you already paid for. |
Then the knobs that matter:
| Field | Default | What it does |
|---|---|---|
maxItems | 1000 | Hard cap on rows delivered and billed. 0 = unlimited. |
maxDomains | 0 | Cap on domains attempted — a different number, because yield is ~51-74 %. |
discoveryChannels | all 4 | A real cost lever: anchors alone cost ~2 requests/domain, the full cascade up to 14. |
maxDiscoveryRequestsPerDomain | 12 | Hard ceiling on the guessed-path channel. |
perDomainTimeoutSecs | 60 | Per-domain deadline, so one slow host cannot stall the run (recon saw 130 s and 152 s outliers). |
requestConcurrency | 10 | 1–30. |
proxyConfiguration | Apify datacenter | The measured winner. Bring your own proxies if you prefer. |
proxyCountry | none | FR / BE / CH / LU / MC / CA. Note: Apify datacenter proxies cannot be country-pinned (they answer HTTP 407), so choosing a country switches the run to residential exit nodes. |
escalateToResidentialOnBlock | true | One residential-FR retry on a real 403 or challenge — never on a dead host, never on a 404. |
requireRegistryId / requireContact / minFieldsRequired | off | Quality floors. A row filtered out here is never billed. |
emailPolicy | all | role-only (contact@, info@…) or exclude-role (named mailboxes only). |
dedupeBy | SIREN, else domain | Or domain, siren, or none. |
includeMissRows | false | Emit an unbilled row with status + missReason for every dead / walled / notice-less domain, for coverage accounting. |
includeRawText / includeRawHtml | false | Attach the source for audit or your own LLM re-parse. |
flattenOutput | true | Flat columns vs nested objects. |
respectRobotsTxt | false | Exposed as a switch. Measured: 0 of 10 French sites disallow the legal-notice path. |
customUserAgent / extraHttpHeaders | — | Bring your own fingerprint. |
Example input:
{"domains": ["donatek.fr", "sapio-arts.fr", "https://pao-ceramique.fr/mentions-legales"],"maxItems": 1000,"requireRegistryId": false,"includeMissRows": false}
💰 Pricing
Pay per event — one event, mentions-legales-scraped, at $0.004 per delivered lead ($4 per 1,000).
Rows are delivered and billed atomically through the same call, so if you hit a charge cap you never keep a row you were not billed for, and never pay for a row you did not receive.
You are not charged for:
- a domain whose host is dead,
- a domain blocked by an anti-bot wall,
- a domain that publishes no legal notice,
- a duplicate collapsed by
dedupeBy, - a row filtered out by
requireRegistryId/requireContact/minFieldsRequired, - any
includeMissRowscoverage row.
| Price per row | |
|---|---|
| Generic EU imprint extractors | $0.0025 |
| Domain → SIREN lookups | $0.0045 – $0.006 |
| This Actor | $0.004 |
| Our own DACH Impressum scraper | $0.015 |
At 51–74 % yield, a 1,000-domain list costs roughly $2.00 – $3.00 in event fees.
❓ FAQ
What is a "mentions légales" page? The legal notice every commercial French website must publish under LCEN art. 6-III / art. 19 (loi n° 2004-575 pour la confiance dans l'économie numérique). It identifies the publisher: company name, legal form, share capital, registered address, SIREN/RCS, TVA number, the directeur de la publication and the site's host.
Is this legal to scrape?
These pages are statutory public disclosures that exist precisely to be read, and they are meant to be indexed — 0 of 10 French sites we checked disallow the path in robots.txt. You remain responsible for each site's Terms of Service, and for handling any personal data in the output (a named directeur de la publication, a personal email) under the GDPR. See the legal note below.
Why is siren only ~71 % and not 100 %?
Because ~29 % of legal notices name a company and an address but no registry id — commonly auto-entrepreneurs and associations. Turn on requireRegistryId and those rows are neither delivered nor billed.
Can I run it on Belgian, Swiss or Canadian French-language sites?
Yes — set proxyCountry and, if you want, tldFilter. The registry patterns (SIREN/SIRET/RCS/TVA FR) are French, so a .be or .ch site will return contact and address data but usually no French registry id.
How is a duplicate handled?
Two ways. A repeated input line is collapsed at queue time, before it costs a single request. Two different domains that turn out to share one SIREN are collapsed at delivery time, before pushData — so a duplicate can never double-charge.
Can I get only rows with an email?
Set requireContact: true. Rows without an email or phone are then neither delivered nor billed.
How do I re-run monthly without paying twice?
Put the previous run's dataset id in previousDatasetId. Every stableId, domain and siren it contains is suppressed.
Does it need a browser or a residential proxy? No. Datacenter HTTP measured 98.4 % usable on the French SME corpus with zero CAPTCHAs. Residential is a per-block escalation for the CDN-fronted enterprise tail only.
Does it use the INSEE/Sirene API? No. It reports what the company itself published, plus an offline Luhn checksum. No external API calls, no keys, no rate limits.
What happens if my list is entirely dead domains? The run exits cleanly with zero billed rows and a status message telling you why. It only fails loudly when the transport itself is broken — 80 %+ of domains refused with a challenge — because that is a proxy problem, not an empty market.
Can I export to Google Sheets / Clay / HubSpot?
Yes. Leave flattenOutput on and use Apify's CSV / Excel / JSON export or the dataset API.
⚖️ Legal
This Actor reads statutory public disclosures that French law requires websites to publish, over ordinary HTTP requests to ordinary public pages. It does not log in, does not bypass any anti-abuse control, does not solve CAPTCHAs, and does not forge authentication. robots.txt compliance is available as an input switch (measured: 0 of 10 French sites disallow the legal-notice path).
Output may contain personal data — a named directeur de la publication, a named gérant, a personal email address. Under the GDPR you are the controller of what you do with it: have a lawful basis, honour erasure requests, and respect each site's Terms of Service. Scraping and using this data is your responsibility, not Apify's and not this Actor's.