# Leboncoin Scraper (`mlg14/leboncoin-scraper`) Actor

Collect structured public listings from search and direct listing URLs, including prices, locations, seller type, images, dates, and category details.

- **URL**: https://apify.com/mlg14/leboncoin-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 62.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.80 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Leboncoin Scraper

Scrape public Leboncoin car listings and property sale listings from search URLs, or collect a known listing from its direct URL. Export Leboncoin data to JSON, CSV, or a spreadsheet for price research, inventory tracking, and market analysis; the dataset offers a structured alternative to manually opening each result.

The actor reads the site's structured search page data, which includes complete listing records, and uses the matching structured route for a direct listing. A single run can accept multiple URLs, stop at a requested item count, and combine the results in one dataset. It saves one row per distinct listing ID. The data route is separate from the visible search page, which can be blocked independently.

### What data can you extract from Leboncoin?

Every saved row has a stable set of camelCase fields. A field can be `null` when the advertiser has not supplied it or it does not apply to that category. For example, `surfaceM2` is generally empty on a car listing and `vehicleYear` is generally empty on a property listing. The `attributes` array preserves extra category fields without changing the top level shape of each row.

| Field | Description | Example |
| --- | --- | --- |
| `id` | Listing identifier | `3259194318` |
| `url` | Direct link to the public listing | `/ad/voitures/3259194318` |
| `title` | Listing headline | Vehicle headline |
| `description` | Public description | Vehicle features and sale terms |
| `category` | Category label | `Voitures` |
| `categoryId` | Numeric category code as text | `2` |
| `status` | Published listing status | `active` |
| `listingType` | Offer or request | `offer` |
| `priceEur` | Main advertised price in euros | `7990` |
| `priceCents` | Advertised price in cents | `799000` |
| `city` | Listing city | `La Châtre` |
| `postalCode` | Postal code | `36400` |
| `department` | Department name | `Indre` |
| `region` | Region name | `Centre` |
| `latitude` | Approximate latitude supplied with the listing | `46.57883` |
| `longitude` | Approximate longitude supplied with the listing | `2.00604` |
| `sellerType` | Seller class | `pro` |
| `sellerName` | Public display name, when present | Public profile name |
| `imageCount` | Number of advertised images | `24` |
| `imageUrls` | Public image URL array | Array of image links |
| `thumbnailUrl` | Thumbnail image URL | Image link |
| `publishedAt` | First publication date supplied by the site | `2026-08-29 18:22:59` |
| `indexedAt` | Last indexing date supplied by the site | `2026-09-25 10:25:14` |
| `hasPhone` | Whether a phone option is shown | `true` |
| `isBoosted` | Whether a promotion flag is present | `false` |
| `favoriteCount` | Public favorite counter, if shown | `22` |
| `surfaceM2` | Property floor area in square metres | `65` |
| `rooms` | Property room count | `3` |
| `bedrooms` | Property bedroom count | `2` |
| `energyRating` | Property energy grade | `C` |
| `emissionsRating` | Property emissions grade | `A` |
| `vehicleBrand` | Vehicle make | Make label |
| `vehicleModel` | Vehicle model | Model label |
| `vehicleYear` | Registration year | `2012` |
| `mileageKm` | Odometer reading in kilometres | `223000` |
| `attributes` | Other source attributes, each with key, label, and value | `{"key":"fuel","value":"Diesel"}` |
| `sourceUrl` | Input URL that produced the row | Search URL |
| `pageIndex` | Search result page number, or `1` for a direct URL | `1` |
| `scrapedAt` | UTC time the row was extracted | ISO timestamp |

The listing identifier and URL support joining repeated exports. The pricing fields are both present because downstream systems sometimes use whole euros and sometimes integer cents. Geographic coordinates come from the listing and may be approximate. Dates are copied from the site in its supplied format; `scrapedAt` records when this actor saw the record. The seller fields include only the public display name and seller type; this actor does not reveal phone numbers or private contact details.

### How to scrape Leboncoin

1. Open a public search URL for the category and filters you want, or a direct `/ad/` listing URL. Copy the full HTTPS address, including location and text parameters when relevant.
2. Paste one or more addresses into `startUrls`. A broad category search is a useful first run because it is easy to compare the output with the site's public results.
3. Set `limit` to the number of rows you need. Set `maxPages` to the number of search result pages the actor may read for each URL.
4. Start the run. When it finishes, inspect the item count and export the dataset in your preferred format.

A direct listing URL produces at most one row. A search URL is passed to the site's structured page data route with its query parameters intact, so category, text, location, and other supported filters are evaluated by the site. Each result page carries up to 35 listings, and the actor follows pages until it reaches `limit`, `maxPages`, or the site's page cap.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | Array of URLs | Required | Public search URLs across categories, or direct listing URLs. |
| `limit` | Integer | `100` | Maximum rows across the run. `0` removes the item cap, subject to the site page cap. |
| `maxPages` | Integer | `10` | Maximum result pages per search URL, from 1 to 100. |
| `proxyConfiguration` | Object | Platform proxy | Optional connection setting; the default starts with a datacenter route. |

A practical first input is:

```json
{
  "startUrls": [
    "https://www.leboncoin.fr/recherche?category=2"
  ],
  "limit": 30,
  "maxPages": 1
}
```

To collect a specific known listing, replace the search URL with its `/ad/` URL and set `limit` to `1`. You can mix direct and search URLs in the same input. The total limit applies to the combined dataset, so put your highest priority URL first. Duplicate listing URLs are skipped within one run.

The actor accepts HTTPS addresses on `leboncoin.fr` and `www.leboncoin.fr`. It rejects addresses from other hosts. A search URL must use `/recherche`; category and other query parameters can follow the site's public search format. This validation keeps the collection scope clear and prevents accidental requests to unrelated domains.

### Output example

The following trimmed row comes from a successful 30 item car search on 26 September 2026. Long text, image links, extra attributes, and fields empty for this category are omitted from this display; they are present in the dataset when supplied by the listing.

```json
{
  "id": "3267877401",
  "url": "https://www.leboncoin.fr/ad/voitures/3267877401",
  "category": "Voitures",
  "categoryId": "2",
  "status": "active",
  "listingType": "offer",
  "priceEur": 17990,
  "priceCents": 1799000,
  "city": "Seyssinet-Pariset",
  "postalCode": "38170",
  "department": "Isère",
  "sellerType": "pro",
  "imageCount": 11,
  "publishedAt": "2026-09-12 03:39:19",
  "indexedAt": "2026-09-26 11:40:52",
  "hasPhone": true,
  "isBoosted": true,
  "favoriteCount": null,
  "vehicleYear": 2024,
  "mileageKm": 54685,
  "sourceUrl": "https://www.leboncoin.fr/recherche?category=2",
  "pageIndex": 1
}
```

The source listing contained additional category attributes and 11 image URLs. The full record also includes location coordinates and an extraction timestamp. The identifier is a string so it remains stable when datasets are exported to systems that handle large numbers differently.

### Use cases

- **Used vehicle pricing:** collect asking prices, years, mileage, and locations to compare advertised vehicles within a chosen category. Asking prices are not confirmed sale prices; treat them as market offers.
- **Inventory monitoring:** schedule repeated collections of a broad car search and compare `id` values across exports to spot additions. Compare `indexedAt` carefully because a listing can remain available after a new index date.
- **Local market views:** group rows by city, department, or region, then calculate advertised counts and median prices. Search URL location filters are applied by the site's result data route.
- **Property sale research:** collect public property advertisements from a property search URL. Surface, rooms, bedrooms, and energy fields depend on the individual advertisement.
- **Known listing tracking:** use direct listing URLs to retain a structured snapshot of selected public advertisements, including images and category attributes.
- **Catalog cleanup:** join rows by `id`, inspect missing fields, and standardize category attributes in your own reporting system.

### How much does it cost to scrape Leboncoin?

The configured result event rate is $0.80 per 1,000 saved listings. At that rate, 30 saved listings correspond to $0.024, 1,000 correspond to $0.80, and 5,000 correspond to $4.00 in event charges. Check run billing for any platform usage charged under your account settings. Actual runtime varies with page size, blocks, retries, and how many candidate listings must be opened to satisfy a filter.

A direct URL that does not yield a row produces no saved item. A filtered search can return fewer rows when the site reports fewer matches or applies a result cap. Start with a small `limit`, examine the item count and run usage, then raise it when the chosen category and filters behave as expected. A larger `maxPages` can increase runtime when more result pages are requested.

### Tips for best results

Start broad. A car category URL with no city filter is more likely to reach `limit` quickly because each result page can contain 35 rows. Add a text filter when the requested term is common in titles or descriptions. If your filter is narrow, check the site's reported match count before raising `limit`; increasing `maxPages` cannot create more matching listings.

For location searches, copy the location parameter from a real public URL. The actor passes it through to the site's structured search data route, which applies its own location rules. Check the exported locations before making geographic claims from a small sample. A location URL that produces zero results in the site's data route will also produce zero rows here.

For repeat monitoring, keep the same input URL and compare stable IDs across runs. Store your own observation time as well as `publishedAt` and `indexedAt`: publication and indexing dates describe the listing, while the observation time describes your collection. Avoid treating an absent record from one result page as proof that a listing was removed; rankings and page positions can change.

When a direct listing has a temporary access error, retry later. The connection layer rotates datacenter sessions for structured page data and can try another route for a direct page fallback. Repeated blocks can still prevent collection. A search run can save 30 rows from one structured result page without opening 30 listing pages.

### Limits

The structured search route was verified with car `category=2`, property sale `category=9`, a text query, and a location query. Other public category URLs use the same route, but field availability and access may differ. Query parameters are forwarded to the site's data route rather than interpreted locally. Verify less common filters against the visible search and the returned records before using them in a decision.

The site reports a 100 page cap per search; with up to 35 listings per page, a single search URL exposes at most about 3,500 results. To collect more, supply several nonoverlapping search URLs with narrower filters and let the actor deduplicate IDs across them. Very narrow searches may produce fewer rows than `limit`. If `limit` is `0`, `maxPages` and the site cap still bound each search URL.

Availability differs across endpoints and over time. The visible search pages and sitemap files returned repeated 403 responses during discovery. The structured search data route then returned complete car and property result sets, including 35 records on a broad first page; that route is now the primary source. A run with no collected listings fails explicitly. Public advertisements can disappear, change status, or omit fields between observations. Empty fields reflect source availability; the actor does not invent missing values.

The actor does not access accounts, private messages, hidden contact details, or logged in content. It saves a public seller display name only when that name is included in the listing's public structured record. Use the dataset in line with the site's terms and applicable privacy rules.

### Use in automated workflows

A scheduled collection can track broad car inventory with the input above and compare the newest dataset against a prior export. Another workflow can pass known direct listing URLs and extract price, status, images, and indexed date for a watchlist. The input schema exposes each option and its description for systems that build a run request programmatically.

Two example requests are: “Collect 30 public car advertisements from this category URL and return the price, city, year, and listing link,” and “Read these known listing URLs and report which ones still return a structured public record.” The dataset can be consumed as JSON or exported as a table for further analysis.

### FAQ

#### Is scraping public Leboncoin listings permitted?

Check the site's terms and the rules that apply to your use case. Its robots file states that automated access requires special permission. This actor uses public pages, but public visibility alone does not grant permission for every use. Handle any public personal data responsibly, especially names in seller profiles.

#### Do I need to set a proxy?

The default connection setting rotates datacenter sessions for structured page data. A direct listing page fallback can escalate after repeated blocks. You can supply your own proxy configuration when your environment requires it. Access restrictions can still prevent some pages from loading.

#### How fast is a run?

It depends on blocks, retries, category, and filters. One measured 30 item car search completed in about 26 seconds, including startup. Structured search pages include up to 35 listings per request, so the actor does not need to open every listing separately for a search. A direct listing URL is at most one row. Check the run duration for your own URL and connection conditions rather than assuming a fixed speed.

#### Can I schedule monitoring?

Yes. Save an input and run it on a schedule. Compare `id` across completed datasets and check the returned item count before interpreting a change as a market change. A blocked or partial run may be missing listings that still exist.

#### Can I export to a spreadsheet?

Yes. Export the dataset as a table format or consume it from the dataset endpoint. The main fields are flat and stable; `imageUrls` and `attributes` contain arrays for richer downstream processing.

#### Why is a field empty?

The field may not apply to the category, the advertiser may have left it blank, or the public structured record may not expose it. Inspect `attributes` for additional category data before concluding that the source lacks a detail. The actor does not estimate missing prices, ratings, or mileage.

#### Why did a filtered search return fewer rows than requested?

The site's search data may report fewer matches than `limit`, the search may have reached its page cap, or a request may have been blocked. Increase `maxPages` only when more result pages exist. For a wider collection, use additional filtered URLs and verify the returned categories, locations, and dates in the dataset.

### Integrations

The default dataset can be retrieved through the platform API, used in scheduled runs, connected to a webhook, or exported for a spreadsheet or reporting pipeline. Use `id` as the durable join key, `sourceUrl` to track which input led to a row, and `scrapedAt` to distinguish repeated observations of the same public listing.

### Support

Open an issue on the actor's Issues tab with the input URL, the run link, the expected field, and a short description of the result. Field requests and reproducible access problems are welcome.

# Actor input Schema

## `startUrls` (type: `array`):

HTTPS leboncoin.fr search URLs across public categories or direct /ad/ listing URLs. Search parameters are sent to the site’s structured page data route.

## `limit` (type: `integer`):

Maximum saved listings across all URLs. Set 0 for no item cap; the site limits each search to 100 result pages.

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

Connection route for public pages. Structured requests rotate datacenter sessions; a direct listing fallback may escalate after blocks.

## `maxPages` (type: `integer`):

Maximum result pages to read for each search URL. Each page contains up to 35 listings; the site exposes at most 100 pages per search.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.leboncoin.fr/recherche?category=2"
  ],
  "limit": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxPages": 10
}
```

# Actor output Schema

## `listings` (type: `string`):

Public listings in the default dataset.

# 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 = {
    "startUrls": [
        "https://www.leboncoin.fr/recherche?category=2"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/leboncoin-scraper").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 = { "startUrls": ["https://www.leboncoin.fr/recherche?category=2"] }

# Run the Actor and wait for it to finish
run = client.actor("mlg14/leboncoin-scraper").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 '{
  "startUrls": [
    "https://www.leboncoin.fr/recherche?category=2"
  ]
}' |
apify call mlg14/leboncoin-scraper --silent --output-dataset

```

## MCP server setup

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

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/WewLIo9jaV3Jl5TT0/builds/bWZEWhpGFEwd72f2E/openapi.json
