How to Scrape Leboncoin in 2026
Leboncoin is France's largest classifieds platform with over 28 million monthly visitors. Whether you're building a price tracker, market analysis tool, or real estate aggregator, getting data from leboncoin programmatically is a common need.
The problem: leboncoin uses DataDome at max sensitivity. Every request gets fingerprinted, device-checked, and — if the IP has any history — challenged with a slider CAPTCHA. Standard HTTP libraries, Selenium, and even Playwright with stealth plugins get blocked within seconds.
Why leboncoin is hard to scrape
Leboncoin's DataDome configuration runs at maximum sensitivity:
IP reputation check — DataDome scores every IP before the request reaches leboncoin. Lower-reputation IPs face harder challenges or outright blocks. Sessemi handles this automatically with stealth=True.
Device fingerprinting — DataDome's c.js script fingerprints the browser environment: WebGL renderer, canvas hash, font metrics, screen properties, and dozens more signals.
Slider CAPTCHA escalation — If the device check fails (typically after 10–15 seconds), DataDome escalates to a slider challenge that requires dragging a handle to a target position.
Cookie validation — The datadome cookie is IP-bound. Using it from a different IP instantly triggers a new challenge.
A standard requests.get() returns a 403 with an empty body. Selenium with chromedriver gets blocked on the device check. Even Playwright with playwright-stealth fails because JavaScript-level fingerprint patches are detectable by DataDome's c.js.
Quick start: 3 lines of Python
pip install sessemi export SESSEMI_KEY=your_key_here # Free at app.sessemi.com
from sessemi import Sessemi
client = Sessemi()
result = client.scrape(
url="https://www.leboncoin.fr/recherche?category=10&locations=Paris",
country="FR",
stealth=True
)
print(f"Status: {result.status_code}")
print(f"Size: {result.body_size:,} bytes")
print(result.text[:500])
That's it. Sessemi handles the DataDome challenge automatically — end to end — and returns the real page content.
Using the CLI
If you prefer the command line:
# Single page sessemi scrape "https://www.leboncoin.fr/recherche?category=10" -c FR # Save to file sessemi scrape "https://www.leboncoin.fr/recherche?category=10" -c FR -o leboncoin.html # Full response as JSON (includes metadata) sessemi scrape "https://www.leboncoin.fr/recherche?category=10" -c FR -f json -o result.json # Check your credits sessemi credits
Status info goes to stderr, page content to stdout — so piping works: sessemi scrape URL -c FR | grep "price"
Scraping search results
Leboncoin is a Next.js app. The listing data is embedded as JSON in a <script id="__NEXT_DATA__"> tag — more reliable than parsing HTML elements:
from sessemi import Sessemi
import json
client = Sessemi()
result = client.scrape(
url="https://www.leboncoin.fr/recherche?category=10&locations=Paris&page=1",
country="FR",
stealth=True
)
if result.status_code == 200:
html = result.text
marker = '<script id="__NEXT_DATA__" type="application/json">'
start = html.find(marker)
if start != -1:
start += len(marker)
end = html.find("</script>", start)
data = json.loads(html[start:end])
ads = data["props"]["pageProps"]["searchData"]["ads"]
for ad in ads[:5]:
print(f"{ad['subject']} — {ad['price'][0]}€ — {ad['location']['city']}")
Paginating through results
from sessemi import Sessemi
import json, time
client = Sessemi()
all_listings = []
for page in range(1, 11):
result = client.scrape(
url=f"https://www.leboncoin.fr/recherche?category=10&locations=Paris&page={page}",
country="FR",
stealth=True
)
if result.status_code != 200:
print(f"Page {page}: got {result.status_code}, stopping")
break
html = result.text
marker = '<script id="__NEXT_DATA__" type="application/json">'
start = html.find(marker)
if start != -1:
start += len(marker)
end = html.find("</script>", start)
data = json.loads(html[start:end])
ads = data["props"]["pageProps"]["searchData"]["ads"]
all_listings.extend(ads)
print(f"Page {page}: {len(ads)} listings (total: {len(all_listings)})")
time.sleep(2) # polite crawling
print(f"\nScraped {len(all_listings)} listings total")
Named sessions for faster scraping
The first request to leboncoin solves the DataDome challenge (~30–60 seconds). Named sessions cache the solved cookies so subsequent requests skip the challenge entirely:
from sessemi import Sessemi
client = Sessemi()
# First request: solves challenge, stores cookies
result = client.scrape(
url="https://www.leboncoin.fr/recherche?category=10&page=1",
country="FR",
stealth=True,
session="lbc-paris"
)
# Subsequent requests: reuses IP + cookies (~2-5s each)
for page in range(2, 11):
result = client.scrape(
url=f"https://www.leboncoin.fr/recherche?category=10&page={page}",
session="lbc-paris"
)
print(f"Page {page}: {result.status_code} ({result.body_size:,} bytes, {result.duration_ms}ms)")
Named sessions keep the same proxy IP and cookies across requests. The first request pays the challenge-solve cost; every request after that is a fast cookie replay at 2–5 seconds.
Cost breakdown
Sessemi uses a flat credit system — 5 credits per scrape regardless of whether a challenge was solved.
| Plan | Credits/mo | Pages/mo | Cost/page | Monthly |
|---|---|---|---|---|
| Free | 1,000 | 200 | €0 | €0 |
| Basic | 20,000 | 4,000 | €0.005 | €20 |
| Pro | 100,000 | 20,000 | €0.005 | €100 |
Compare this with per-solve CAPTCHA services that charge $2–4 per 1,000 solves on top of your proxy and infrastructure costs.
Tips for reliable leboncoin scraping
Use stealth=True with country="FR" — Sessemi automatically selects the best proxy pool, enables challenge solving, and adds retries. A French residential IP gives the highest success rate on first attempt.
Use named sessions for multi-page crawls. The first request solves the challenge (~30–60s); subsequent requests reuse the clearance cookie (~2–5s each).
Respect rate limits — Leboncoin monitors request frequency. 1 request every 2–3 seconds is safe. Faster than that risks IP burns.
Parse __NEXT_DATA__ instead of scraping HTML elements. Leboncoin is a Next.js app — the structured JSON data is more reliable than DOM selectors that break on layout changes.
Get started: Sign up at app.sessemi.com — 1,000 free credits, no credit card. Install: pip install sessemi. Set your key: export SESSEMI_KEY=your_key. Start scraping.
Full working example: leboncoin_scrape.py — ready-to-run script with JSON parsing and named sessions.