# Leboncoin Listing Lookup: leboncoin scraper from $2/1k (`accountable_eel/leboncoin-listing-lookup`) Actor

leboncoin scraper by keyword: run a search on leboncoin.fr, France's largest classifieds marketplace, and get one row per listing, including title, price, category, city, seller type, link. No login required. Pay per listing returned; empty searches are free.

- **URL**: https://apify.com/accountable\_eel/leboncoin-listing-lookup.md
- **Developed by:** [Adrian Voss](https://apify.com/accountable_eel) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.52 / 1,000 listing returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

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

## Leboncoin Listing Lookup: leboncoin scraper from $2/1k

You type a search the way you'd type it into leboncoin's own search box — "iphone", "peugeot
208", "canape 3 places" — and this actor runs it against **leboncoin.fr's own search-results
pages**, France's largest classifieds marketplace, and returns one clean row per listing: title,
price, category, city, seller type, and a permanent link.

leboncoin sits behind DataDome — a bare request gets a JS-challenge block page, not the listings.
This actor requests every search through Apify's UNBLOCKER proxy, which clears it cleanly (a
real, server-rendered page comes back, no headless browser needed), so you never have to think
about that yourself.

### Who it's for

A reseller or arbitrage buyer watching one category (phones, cars, furniture) for underpriced
listings wants a live feed of what's actually posted right now, across many search terms at once,
without refreshing leboncoin's own search page by hand. A market-research team tracking asking
prices for a product category, or a relocation/real-estate scout scanning a city's listings, gets
the same shape here: paste a list of search terms, get back a flat row per listing, and pay only
for listings actually returned — a search that finds nothing costs nothing.

This actor is leboncoin's counterpart to `kleinanzeigen-listing-lookup` (Germany) and
`otomoto-listing-lookup` (Poland, vehicles) in this catalogue, but shaped differently from both:
those take a specific listing URL and return one row for that one ad. This one takes a search
term and returns every matching listing leboncoin's own search turns up — for when you don't
have specific ad URLs yet, only a category or keyword you're watching.

### Why this one

- **Gets past leboncoin's DataDome wall for you.** A plain request returns an HTTP 403 DataDome
  challenge page — confirmed directly, not assumed. This actor routes every request through
  Apify's UNBLOCKER proxy group, which clears it cleanly: a normal 200 response with the full,
  real, server-rendered search page. No headless browser is needed once past that wall, since
  leboncoin's own listing data is already embedded in the HTML it sends back.
- **Reads leboncoin's own structured data, not scraped text.** Every field here comes from the
  same `__NEXT_DATA__` JSON block leboncoin's own React app renders from — not regex'd out of
  visible page text, so prices, IDs, and location fields are exact, typed values rather than
  parsed strings.
- **Works across every leboncoin category, not just one.** Electronics, vehicles, real estate,
  jobs, general goods — leboncoin's per-listing `attributes` vary by category (phone model and
  storage for a handset, mileage and fuel type for a car), and this actor carries all of them
  through in a generic `attributes` object instead of hardcoding one category's fields and
  dropping the rest.
- **Never charged for a miss, or for a listing outside your price range.** A search that finds
  nothing, or where every result falls outside your `minPrice`/`maxPrice` filter, still gets a
  row explaining what happened — and costs nothing. See "Pricing" below for the found-row rate.
- **Honest about what wasn't verified.** Publish dates are passed through exactly as leboncoin's
  own API sends them (no timezone marker in the source, so none is invented here — see FAQ), and
  this actor fetches one search page per query rather than claiming to page through every result;
  see "vs. alternatives" for what that trade-off costs you.

### What you get

One row per listing by default. (Turn off "One row per listing" in the Input tab to get one row
per *search* instead, with the whole listing list nested in `listings`.) Every row carries these
fields:

| Field | Type / format | Description |
| --- | --- | --- |
| `query` | text | The search term you passed in, unchanged. |
| `found` | boolean | `true` if the search returned at least one listing. `false` rows are never charged. |
| `status` | text | `OK`, `NOT_FOUND` (no listings for that search), `BAD_FORMAT` (a blank line), or `BLOCKED`. |
| `searchQuery` | text | The search text actually sent to leboncoin. |
| `listingCount` | number | How many listings this search returned after your price filters — this is exactly what you're charged for. |
| `totalAvailable` | number | leboncoin's own total-match count for this search. |
| `truncated` | boolean | `true` if more listings were available than this actor's one-page fetch returned. |
| `listings` | array | The full listing list. Present in every row; it's what gets expanded into separate rows in "one row per listing" mode. |
| `listingId` | text | leboncoin's own numeric listing ID. |
| `title` | text | Listing title. |
| `description` | text | Listing description, truncated to 500 characters. |
| `price` | number | Price in EUR, or `null` for a free/exchange/price-on-request listing. |
| `category` | text | leboncoin's own category name, e.g. "Telephones & Objets connectes". |
| `city` / `region` / `department` / `zipcode` | text | Seller's stated location, as leboncoin displays it. |
| `sellerType` | text | `pro` or `private`, from leboncoin's own listing owner data. |
| `sellerName` | text | Seller or shop name. |
| `publishedAt` | text | leboncoin's own first-publication timestamp, verbatim (see FAQ on why this isn't reformatted). |
| `url` | link | Permanent link to the listing on leboncoin.fr. |
| `image` | link | Thumbnail image URL. |
| `imageCount` | number | How many photos the listing has. |
| `attributes` | object | Every category-specific attribute leboncoin shows on the listing (phone model, vehicle mileage, property size, etc.) as a flat key/value object — see "Why this one". |
| `scrapedAt` | date (ISO) | When this actor fetched the row. |

A search that returns no listings comes back as a single `found: false` row with a
`status`/`message` explaining why, and is never charged.

### Pricing

- **Listing returned**: $2 per 1,000 listings

Plus a $0.00005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (`found:false`) are never charged.

Pay-per-event, per listing returned:

- **Listing returned**: $2 per 1,000 listings, less on paid Apify plans.

Plus a $0.00005 start fee per run. Misses (`found: false`) are never charged.

You're charged **per listing returned**, not per search — a search that returns 30 listings costs
thirty, a search that returns none costs nothing, and a blank line costs nothing.

Getting past leboncoin's DataDome wall needs Apify's UNBLOCKER proxy group, already configured
by default — there's nothing for you to set up, but it is a real, metered cost on this actor's
own side, which is reflected in the price: this is higher per row than a plain-HTTP classifieds
actor like `kleinanzeigen-listing-lookup`, which needs no proxy at all.

1,000 listings through this actor: **~$2** if every search finds results, less on a paid Apify
plan. Because you pay per listing, "Most listings to return per search" is your budget control:
leave it at 35 and a ten-search run costs at most 350 listings' worth.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `searches` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~leboncoin-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"searches":["iphone"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

Paste one search per line:

```
iphone
peugeot 208
appartement 3 pieces paris
```

**Narrow the results** — applied here, to the listings after they arrive:

| Input | What it does |
| --- | --- |
| `minPrice` | Drop listings priced below this (EUR). |
| `maxPrice` | Drop listings priced above this (EUR). |
| `maxListingsPerQuery` | Most listings to return per search. Default 35 — leboncoin's own per-page count. |

### Input

```json
{
  "searches": [
    "iphone"
  ]
}
```

One search per line — any keywords, e.g. "iphone 14", "peugeot 208", "canape 3 places". No login required. Accepted formats: iphone, peugeot 208, appartement 3 pieces paris.

### Output

| query | found | status | searchQuery | listingCount | totalAvailable | truncated | listings | listingId | title | price | category | city | region | sellerType | publishedAt | url | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| iphone | true | OK | iphone | 35 | 377462 | true | \<all listings found (full list)> | 3223572311 | IPhone 13 Pro & iPhone 12 Pro avec facture et garantie 🤩 | 200 | Téléphones & Objets connectés | Toulouse | Midi-Pyrénées | pro | 2026-08-29 19:47:06 | https://www.leboncoin.fr/ad/telephones\_objets\_connectes/3223572311 | 2026-09-08T17:45:05.612Z |

A miss comes back as a row with `"found": false` and is never charged.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~leboncoin-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"searches":["iphone"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~leboncoin-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"searches":["iphone"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~leboncoin-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"searches":["{{search}}"]}`, mapping the row's search into the `searches` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Leboncoin Scraper | Apify" — the agent will find and run this actor.

### Tips

- Run "Try it first" on a handful of searches you already know return results for, to sanity-check
  the shape before spending on a full list.
- Keep `maxListingsPerQuery` at or below 35 (leboncoin's own per-page count) — this actor fetches
  one search page per query, so raising it above 35 has no effect until a future version adds
  paging.
- Use `minPrice`/`maxPrice` to cut noise from a broad category search before you pay for rows you
  don't want, rather than filtering client-side after the fact.
- `attributes` varies by category — inspect a few real rows for your search term before building a
  downstream schema around specific attribute keys, since a phone search and a car search return
  different keys.
- `sellerType` lets you split professional listings (shops, resellers) from private-party ones if
  you only want one or the other.

### vs. alternatives

| | What it costs | What you get | Trade-off |
|---|---|---|---|
| **This actor** (`leboncoin-listing-lookup`) | $0.002 per listing returned (less on paid Apify plans), $0.00005 actor start, nothing for a search that finds nothing | One row per leboncoin listing — title, price, category, city, seller type, and link — filtered by min/max price | One search page per query (up to 35 listings); no paging past that yet. Publish timestamps are passed through verbatim, without a timezone marker (see FAQ). |
| **fatihtahta/leboncoin-fr-scraper** | Pay-per-result on Apify (81 u30, rated 3.65 on 8 reviews) | Also scrapes leboncoin search results | A modest review base at a middling rating. This actor prices per listing, reads leboncoin's own structured JSON rather than parsed HTML, and carries every category's attributes through generically. |
| **Doing it yourself** | Your time + a DataDome-clearing proxy, tracking leboncoin's own `__NEXT_DATA__` shape as it changes, and handling category-specific fields by hand | The same data | The DataDome-clearing proxy wiring and the generic attribute handling this actor already does are the maintenance burden it absorbs. |

Prices for third-party tools are their published figures as of September 2026 and are not tracked
here — check the vendor before relying on the comparison.

### FAQ

**Why is a row empty, or why does `found` say `false`?**
Either the input line is blank (`status: BAD_FORMAT`), leboncoin/DataDome blocked the request
(`status: BLOCKED`, HTTP 403/429/503), the request failed after retries
(`status: REQUEST_FAILED`), or the search genuinely has no matching listings right now
(`status: NOT_FOUND`). Check the `message` column for the specific reason. None of these are
billed.

**Am I charged for a miss?**
No. You're only charged for listings actually returned. A blocked search, a search with zero
matches, or a search where every result falls outside your price filter all produce a row (unless
you turn on "Hide rows with no result") and none of them cost anything.

**Why is `publishedAt` not a normal ISO timestamp?**
leboncoin's own API returns it as a plain `"YYYY-MM-DD HH:MM:SS"` string with no timezone marker.
Rather than guess a timezone (leboncoin doesn't say whether it's UTC or Europe/Paris local time)
and fabricate a false-precision ISO instant, this actor passes the value through exactly as
leboncoin sends it.

**Does this actor page through more than one screen of results?**
Not yet. Each search fetches leboncoin's first results page (up to 35 listings) through UNBLOCKER.
`totalAvailable` still reports leboncoin's true match count so you know how many more exist;
`truncated` is `true` whenever there are more.

**Does this handle DataDome's block on leboncoin?**
Yes, automatically. Every request goes through Apify's UNBLOCKER proxy group by default — there's
nothing for you to configure. If leboncoin still re-challenges a session, that shows up as a
`BLOCKED` status on the affected search rather than a silent failure.

**Do I need to configure proxies?**
No. UNBLOCKER is the default proxy group for this actor specifically, because a plain request to
leboncoin is blocked by DataDome. You don't need to change anything to use it.

**Can I schedule this to re-check the same searches on a cadence?**
Yes — set up an Apify Task with a schedule (daily, weekly, whatever cadence fits) and point it at
this actor with a saved input. Each run is a fresh fetch against leboncoin's live listings — handy
for catching a new listing the moment it's posted.

**Can an AI agent call this directly?**
Yes. It's registered on the Apify MCP server — an agent in Claude, Cursor, or another MCP client
can find and run it by name ("Leboncoin Listing Lookup | Apify"), or you can call the REST
endpoint shown above from any script or workflow tool.

### Related actors

- [Kleinanzeigen Listing Lookup](https://apify.com/accountable_eel/kleinanzeigen-listing-lookup) —
  the same classifieds category, for Germany's Kleinanzeigen — takes a listing URL rather than a
  search term.
- [OLX Listing Lookup](https://apify.com/accountable_eel/olx-listing-lookup) — the same
  search-by-keyword shape, for Poland's OLX.pl.
- [Otomoto Listing Lookup](https://apify.com/accountable_eel/otomoto-listing-lookup) — a
  vehicle-specific classifieds lookup for Poland's largest car marketplace.

# Actor input Schema

## `searches` (type: `array`):

One search per line — any keywords, e.g. "iphone 14", "peugeot 208", "canape 3 places". No login required. Accepted formats: iphone, peugeot 208, appartement 3 pieces paris. You're only charged for the ones we actually find — a miss costs nothing.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

## `maxResults` (type: `integer`):

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `minPrice` (type: `integer`):

Optional. Drop listings priced below this. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Optional. Drop listings priced above this. Leave empty for no maximum.

## `maxListingsPerQuery` (type: `integer`):

leboncoin returns up to 35 listings per search page (this actor fetches one page per search). You pay per listing returned, so this is also your budget control.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `expandRows` (type: `boolean`):

When on, each listing found gets its own row instead of being grouped under its search. You're still only charged once per search, no matter how many rows it produces.

## `maxConcurrency` (type: `integer`):

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

## `proxyConfiguration` (type: `object`):

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "searches": [
    "iphone"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "maxListingsPerQuery": 35,
  "columns": [
    "searchQuery",
    "listingCount",
    "totalAvailable",
    "truncated",
    "listings",
    "listingId",
    "title",
    "price",
    "category",
    "city",
    "region",
    "sellerType",
    "publishedAt",
    "url"
  ],
  "expandRows": true,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# 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 = {
    "searches": [
        "iphone"
    ],
    "includeKeywords": [],
    "excludeKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/leboncoin-listing-lookup").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 = {
    "searches": ["iphone"],
    "includeKeywords": [],
    "excludeKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/leboncoin-listing-lookup").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 '{
  "searches": [
    "iphone"
  ],
  "includeKeywords": [],
  "excludeKeywords": []
}' |
apify call accountable_eel/leboncoin-listing-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/leboncoin-listing-lookup"
        }
    }
}

```

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/LkbdQq03TyFFvoviq/builds/ILml5RGeQPZbvd1G8/openapi.json
