← Back to blog

How to Scrape Leboncoin in 2026

20 May 2026 · Andrew Odiit

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.

PlanCredits/moPages/moCost/pageMonthly
Free1,000200€0€0
Basic20,0004,000€0.005€20
Pro100,00020,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.