# Marktplaats.nl Scraper — Dutch Classifieds Search & Monitoring (`yadroo/marktplaats-nl`) Actor

Marktplaats.nl listings for AI agents and analysts: keyword + category (2,000 L1/L2) search with postcode radius, price, condition, delivery, seller type and raw facet filters; price, price type, city, coordinates, seller, date, attributes, photos, URL.

- **URL**: https://apify.com/yadroo/marktplaats-nl.md
- **Developed by:** [Samat Makatov](https://apify.com/yadroo) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 result items

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?

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

Search **marktplaats.nl** (the Netherlands' #1 classifieds, 2,000+ categories) by keyword and/or category with the same filters the site offers — postcode + radius, price, condition, delivery, seller type (cars), attribute facets — and get clean JSON: price and price type, city, coordinates, distance, seller, category, date, attributes, photos, URL. Optionally open every listing page for the full description, exact publish time, view/favourite counts, seller type and bids (paced for marktplaats.nl's per-IP limit, see Limits). Built for AI agents, analysts and monitoring jobs: reads the site's own JSON search API, **no browser, no API key, no proxy needed**. Big `detail: true` jobs can use the optional **fast mode** (turn on a proxy): listing pages are opened with up to 8 IPs at once — see [Speed and pricing](#speed-and-pricing).

### Use cases

- **Price monitoring** — track asking prices for a product ("iphone 15 pro", "gazelle e-bike") daily; `sortBy: PRICE` gives the cheapest offers first.
- **Sourcing / arbitrage** — find under-priced items in a category near a warehouse postcode; filter `condition`, `delivery: shipping`, `sellerType: private`.
- **Lead generation** — list business sellers (dealers, refurbishers, contractors in *Diensten en Vakmensen*) with their profile URL and years active (`detail: true`).
- **New-listing alerts** — run every hour with `sinceHours: 1` (+ `detail`) and push fresh matches to Slack/CRM.
- **Market research** — count listings and price distribution per subcategory; `mode: facets` returns the facet histogram (brands, conditions, fuel types…) with counts.
- **Used-car analysis** — category `auto-s` with `attributeRanges` (construction year, mileage), fuel/transmission ids and `sortAttribute`.

### Input

| Field | Type | Default | Notes / allowed values |
|---|---|---|---|
| `query` | string | – (UI prefill `fiets`) | Keyword(s). Optional when `category` is set; leave empty to browse a whole category. |
| `category` | string | – | L1 key or id, optionally `l1/l2`: `fietsen-en-brommers`, `445`, `fietsen-en-brommers/fietsen-racefietsen`, `445/464`. L1 table below; L2 keys via `mode: categories`. |
| `subcategory` | string | – | L2 key / id / (part of) name, e.g. `racefietsen`. Alternative to the `l1/l2` notation. |
| `mode` | select | `search` | `search` = listings · `categories` = full category tree (~2,000 rows, about $4 — see Speed and pricing) · `facets` = filter values valid for the query/category (with ids and counts). |
| `postcode` | string | – | Dutch postcode (`1012AB`) — enables `distanceMeters` filter, distance in output and `sortBy: LOCATION`. |
| `distanceMeters` | integer | – | Radius in metres (site presets: 3000 … 100000). Needs `postcode`. |
| `priceFrom` / `priceTo` | integer | – | Euro. |
| `condition` | array | – | `new`, `like-new`, `used`, `refurbished` (OR). |
| `delivery` | select | – | `pickup` (Ophalen) / `shipping` (Verzenden). |
| `sellerType` | select | `all` | `private` / `business`. Server-side for cars (`auto-s`). Other categories: with `detail: true` every listing page is checked and a listing whose page could not be read is dropped (counted in the status). Without `detail`, `private` drops listings whose search data shows a business (website link, dealer tools, company logo) and keeps the rest unverified (`sellerType: null`); `business` keeps only listings whose search data shows a business. |
| `offeredSince` | select | – | `Vandaag`, `Gisteren`, `Een week`, `Altijd`. Sent to the site and enforced client-side on the list date (day precision). |
| `sinceHours` | integer | – | Keep listings newer than N hours. Exact with `detail: true`; a row without a listing page (no `detail`, or its page could not be read) is judged by its day label: kept when its day started less than N + 24 h ago. |
| `priceTypes` | array | – | Client-side keep-list: `FIXED`, `MIN_BID`, `SEE_DESCRIPTION`, `NOTK`, `FREE`, `ON_REQUEST`, `EXCHANGE`, `RESERVED`. |
| `attributeIds` | integer\[] | – | Raw facet value ids (`attributesById`), e.g. `[473, 534]` = Benzine + Automaat. Discover with `mode: facets`. |
| `attributesByKey` | string\[] | – | Raw `key:value` facets, e.g. `"offeredSince:Vandaag"`. |
| `attributeRanges` | string\[] | – | Range facets `key:from:to`, e.g. `"constructionYear:2018:2024"`, `"mileage:0:100000"`. |
| `sortBy` | select | `SORT_INDEX` | `SORT_INDEX` (date), `OPTIMIZED` (relevance), `PRICE`, `LOCATION` (needs postcode), `ATTRIBUTE` (cars, with `sortAttribute`). |
| `sortOrder` | select | auto | `DECREASING` / `INCREASING` (PRICE and LOCATION default to INCREASING). |
| `sortAttribute` | select | – | `constructionYear` / `mileage` (cars). |
| `includeSponsored` | boolean | `false` | Also return paid Admarkt listings from the top block (`sponsored: true`). |
| `detail` | boolean | `false` | Open each listing page: full description, `publishedAt`, views, favourites, seller type/years, bids, shipping, all photos. At most 40 listing pages a minute (~1.5 s per listing); see Limits for what happens on a block. |
| `maxItems` | integer | `50` | 1–2000 listings saved (100 per request; the site caps a query at 5,000 results). Rows dropped by filters do not count. Modes `categories` and `facets` return their whole list. |
| `maxPages` | integer | `20` | 1–50 search pages. |
| `proxyConfiguration` | object | off | **Off = the normal run.** On = fast mode for `detail: true`: Apify Proxy → 8 IPs (group RESIDENTIAL) or 4 IPs (datacenter groups, whose IPs are shared) open listing pages at once, at the fast-mode price; your own proxy URLs (`http://user:pass@host:port`, one per IP, up to 10 at once) → as many IPs as URLs, at the normal price. The search API is always read directly; without `detail` the proxy is not used. See [Speed and pricing](#speed-and-pricing). |
| `fields` | string\[] | – | Keep only these output fields, in this order. Every row keeps `id` (facets rows: `facetKey`, `valueKey`), and with `detail: true` also `detailError` when the listing page was not read; they come first unless you list them. A different letter case or a near miss (`titel`) is read as the field and noted in the status; unknown names (and detail-only fields without `detail`) are ignored with a note; if no name is an output field the run fails before any request and lists the valid names. |

### Reference

#### L1 categories (`category`)

| id | key | name | id | key | name |
|---|---|---|---|---|---|
| 1 | antiek-en-kunst | Antiek en Kunst | 565 | kinderen-en-baby-s | Kinderen en Baby's |
| 31 | audio-tv-en-foto | Audio, Tv en Foto | 621 | kleding-dames | Kleding | Dames |
| 91 | auto-s | Auto's | 1776 | kleding-heren | Kleding | Heren |
| 2600 | auto-onderdelen | Auto-onderdelen | 678 | motoren | Motoren |
| 48 | auto-diversen | Auto diversen | 728 | muziek-en-instrumenten | Muziek en Instrumenten |
| 201 | boeken | Boeken | 1784 | postzegels-en-munten | Postzegels en Munten |
| 289 | caravans-en-kamperen | Caravans en Kamperen | 1826 | sieraden-tassen-en-uiterlijk | Sieraden, Tassen en Uiterlijk |
| 1744 | cd-s-en-dvd-s | Cd's en Dvd's | 356 | spelcomputers-en-games | Spelcomputers en Games |
| 322 | computers-en-software | Computers en Software | 784 | sport-en-fitness | Sport en Fitness |
| 378 | contacten-en-berichten | Contacten en Berichten | 820 | telecommunicatie | Telecommunicatie |
| 1098 | diensten-en-vakmensen | Diensten en Vakmensen | 1984 | tickets-en-kaartjes | Tickets en Kaartjes |
| 395 | dieren-en-toebehoren | Dieren en Toebehoren | 1847 | tuin-en-terras | Tuin en Terras |
| 239 | doe-het-zelf-en-verbouw | Doe-het-zelf en Verbouw | 167 | vacatures | Vacatures |
| 445 | fietsen-en-brommers | Fietsen en Brommers | 856 | vakantie | Vakantie |
| 1099 | hobby-en-vrije-tijd | Hobby en Vrije tijd | 895 | verzamelen | Verzamelen |
| 504 | huis-en-inrichting | Huis en Inrichting | 976 | watersport-en-boten | Watersport en Boten |
| 1032 | huizen-en-kamers | Huizen en Kamers | 537 | witgoed-en-apparatuur | Witgoed en Apparatuur |
| | | | 1085 | zakelijke-goederen | Zakelijke goederen |
| | | | 428 | diversen | Diversen |

There are ~1,960 L2 subcategories (e.g. `fietsen-en-brommers` has 76: `fietsen-racefietsen` 464, `elektrische-fietsen` 451, `fietsen-bakfietsen` 446 …). Run `{"mode": "categories"}` once to get the whole tree as dataset rows (`level`, `id`, `key`, `name`, `parentKey`, `howToUse`), or `{"mode":"categories","category":"auto-s"}` for one branch. They also appear in the site URL: `marktplaats.nl/l/<l1key>/<l2key>/`.

#### Generic facet ids

| Facet | Values (id) |
|---|---|
| condition | Nieuw 30 · Zo goed als nieuw 31 · Gebruikt 32 · Refurbished 14050 (cars: Nieuw 30 · Gebruikt 14049) |
| delivery | Ophalen 33 · Verzenden 34 |
| offeredSince (by key) | Vandaag · Gisteren · Een week · Altijd |
| advertiser (cars only) | Particulier 10898 · Bedrijf 10899 |
| priceType (cars) | Vraagprijs 10882 · Leaseprijs 10883 |

Cars (`auto-s`) additionally expose ~40 facets: `fuel` (Benzine 473, Diesel 474, Elektrisch 11756, Hybride 13838/13839, LPG 475), `transmission` (Automaat 534, Handgeschakeld 535), `body`, `color`, `energyLabel` (A 13947 … G 13953), `options`, ranges `constructionYear`, `mileage`, `engineHorsepower`, `roadTax`, `batteryCapacity`… Every category has its own set (bikes: `brand`, `frameHeight`, `brakeType`) — `mode: facets` lists them with live counts and the exact `howToUse` string.

#### Sort options

`SORT_INDEX`+`DECREASING` newest first · `SORT_INDEX`+`INCREASING` oldest first · `OPTIMIZED` site relevance · `PRICE` asc/desc · `LOCATION`+`INCREASING` nearest first (postcode) · `ATTRIBUTE` + `sortAttribute` `constructionYear` / `mileage` (cars).

#### Price types

`FIXED` fixed price · `MIN_BID` "bieden vanaf" (price = minimum bid) · `SEE_DESCRIPTION` · `NOTK` n.o.t.k. (negotiable) · `FREE` gratis · `ON_REQUEST` · `EXCHANGE` ruilen · `RESERVED`.

### Examples

**Cheapest used road bikes within 25 km of Utrecht, shipped or picked up**

```json
{ "query": "racefiets", "category": "fietsen-en-brommers/fietsen-racefietsen", "postcode": "3511AB", "distanceMeters": 25000, "priceTo": 800, "condition": ["like-new", "used"], "sortBy": "PRICE", "maxItems": 100 }
```

**Hourly new-listing alert with exact timestamps and seller type**

```json
{ "query": "iphone 15 pro", "category": "telecommunicatie", "sinceHours": 1, "detail": true, "sortBy": "SORT_INDEX", "sortOrder": "DECREASING", "maxItems": 60 }
```

**Private-seller used cars: Volvo, 2018+, under 100,000 km, automatic, petrol/hybrid**

```json
{ "query": "volvo", "category": "auto-s", "sellerType": "private", "attributeRanges": ["constructionYear:2018:", "mileage:0:100000"], "attributeIds": [534, 473, 13838], "sortBy": "ATTRIBUTE", "sortAttribute": "mileage", "sortOrder": "INCREASING", "maxItems": 200 }
```

**Lead list of business sellers in a category (with profile URL and years active)**

```json
{ "category": "zakelijke-goederen/horeca-keukenapparatuur", "sellerType": "business", "detail": true, "fields": ["id", "title", "price", "city", "sellerName", "sellerType", "sellerActiveYears", "sellerProfileUrl", "url"], "maxItems": 150 }
```

**Discover the filters of a category before building a search**

```json
{ "mode": "facets", "category": "auto-s", "query": "tesla" }
```

### Output

```json
{
  "id": "m2440133929",
  "title": "Gazelle Balance Innergy €500,-",
  "description": "Gazelle balance innergy zeer goede staat goede accu en met acculader",
  "price": 500, "currency": "EUR", "priceType": "FIXED",
  "city": "Houten", "distanceMeters": 7000, "distanceKm": 7,
  "latitude": 52.0346, "longitude": 5.1558, "countryName": "Nederland",
  "sellerName": "Ferdinand", "sellerId": 23350124, "isVerifiedSeller": false, "sellerHasWebsite": false,
  "categoryId": 451, "categoryName": "Elektrische fietsen",
  "date": "7 sep 26", "dateIso": "2026-09-07",
  "priorityProduct": "NONE", "sponsored": false, "reserved": false, "traits": ["PACKAGE_FREE"],
  "condition": "Gebruikt", "delivery": "Ophalen", "constructionYear": null, "mileageKm": null, "fuel": null, "transmission": null, "advertiserType": null,
  "attributes": { "condition": "Gebruikt", "delivery": "Ophalen", "frameHeight": "Minder dan 47 cm" },
  "images": ["https://images.marktplaats.com/api/v1/…?rule=ecg_mp_eps$_82.jpg"], "imagesCount": 1,
  "url": "https://www.marktplaats.nl/v/fietsen-en-brommers/elektrische-fietsen/m2440133929-gazelle-balance-innergy-500",
  "query": "gazelle", "searchUrl": "https://www.marktplaats.nl/lrp/api/search?…", "fetchedAt": "2026-09-12T23:48:40.800Z",

  "descriptionFull": "Gazelle Balance Innergy\nZeer goede staat\nGoede accu en met acculader",
  "publishedAt": "2026-09-07T16:06:08Z", "viewCount": 212, "favoritedCount": 2,
  "sellerType": "CONSUMER", "sellerActiveYears": 10, "sellerProfileUrl": "https://www.marktplaats.nl/u/ferdinand/23350124/", "sellerCity": "Houten",
  "adType": "RegularFree", "biddingEnabled": false, "bidCount": 0, "highestBid": null, "minimumBid": null,
  "shippingType": "Ophalen", "buyItNow": false, "buyerProtection": false, "isReserved": false, "allImages": ["…"]
}
```

| Field | Description |
|---|---|
| `id`, `url`, `title`, `description` | Listing id (`m…` / `a…` for Admarkt), canonical URL, title, list snippet. |
| `price`, `currency`, `priceType` | Euro; see price types above (`MIN_BID` = bidding from this amount). |
| `city`, `distanceMeters`, `distanceKm`, `latitude`, `longitude`, `countryName` | Location; distance only when `postcode` is given. |
| `sellerName`, `sellerId`, `isVerifiedSeller`, `sellerHasWebsite` | From the list. |
| `sellerType`, `sellerTypeSource` | `CONSUMER` (private) or `TRADER` (business), as on the listing page. `sellerTypeSource`: `filter` = the server-side seller filter of a car search, `listing` = the search data (car "advertiser" attribute, or a business-only website link / dealer tools / company logo), `detail` = the listing page. `null` when the search data has no signal and `detail` is off (no logo or website does not prove a private seller). |
| `categoryId`, `categoryName` | L2 category of the listing. |
| `date`, `dateIso` | Site label ("Vandaag", "7 sep 26") and ISO date (Dutch calendar day). |
| `priorityProduct`, `sponsored`, `reserved`, `traits` | Paid placement (`DAGTOPPER`…), Admarkt top-block flag, reserved flag, feature traits. |
| `condition`, `delivery`, `constructionYear`, `mileageKm`, `fuel`, `transmission`, `advertiserType` | Most-used attributes lifted to top level (null when the category has no such attribute; `advertiserType` = "Bedrijf"/"Particulier", cars only) |
| `attributes` | Flat map of all listing attributes (condition, delivery, brand, mileage, fuel…). `pricePerKm` = price ÷ mileage for vehicles. |
| `images`, `imagesCount` | Thumbnail URLs from the list. |
| `query`, `searchUrl`, `fetchedAt` | Provenance. |
| *detail only:* `descriptionFull`, `publishedAt`, `viewCount`, `favoritedCount`, exact `sellerType` for every listing, `sellerActiveYears`, `sellerProfileUrl`, `sellerCity`, `sellerPhoneHidden`, `adType`, `categoryFullName`, `parentCategoryId`, `biddingEnabled`, `bidCount`, `highestBid`, `minimumBid`, `shippingType`, `buyItNow`, `buyerProtection`, `isReserved`, `allImages` | Read from the listing page. |
| `detailError` | *detail only:* why the listing page of this row was not read — `skipped: …` after marktplaats.nl kept refusing listing pages (see Limits), or the page's own error (removed listing). The row then holds the search data only. |

`mode: categories` rows: `level`, `id`, `key`, `name`, `parentId`, `parentKey`, `howToUse`, `url`. `mode: facets` rows: `facetKey`, `facetLabel`, `valueId`, `valueKey`, `valueLabel`, `count`, `howToUse`. The Output tab has a view per row type (Listings, Listings with detail, Categories, Filter values).

Every run also writes a `SUMMARY` record (linked in the run's output): rows saved, matching total, `detailFor` ("N of M" rows with a listing page read), pauses for the per-IP limit, rows dropped by each filter, notes, and why the run stopped early (spending limit, timeout, block). The run's status message says the same in one line.

### Use it from code / agents

```bash
curl -X POST "https://api.apify.com/v2/acts/yadroo~marktplaats-nl/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"query":"racefiets","postcode":"1012AB","distanceMeters":25000,"priceTo":800,"maxItems":50}'
```

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/marktplaats-nl').call({ query: 'iphone 15 pro', sinceHours: 2, detail: true, maxItems: 40 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/marktplaats-nl").call(run_input={"category": "auto-s", "query": "volvo", "sellerType": "private", "maxItems": 100})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

MCP: add `https://mcp.apify.com` to your agent (Claude, Cursor, custom) and call the `yadroo/marktplaats-nl` tool with the same JSON input — the input schema descriptions are written for agents.

### Speed and pricing

The search API is quick (100 listings per request, 2,000 listings in about 30–40 s), so runs without `detail` are fast in every mode. With `detail: true` the run opens one listing page per row, and marktplaats.nl refuses listing pages from one IP after about 60 a minute — so the normal run opens at most **40 a minute** (see Limits). Fast mode opens them with several IPs at once, each at that same pace. Pick the mode with the `proxyConfiguration` input:

| Mode | How | 150 listings, `detail: true` | 1,000 listings, `detail: true` | Price per listing |
|---|---|---|---|---|
| **Normal** (default) | proxy off | ≈ 4 min | ≈ 25 min | **$0.002** |
| **Fast, Apify Proxy** | proxy on → Apify Proxy, group RESIDENTIAL (8 IPs) | **≈ 1.1 min** (measured) | ≈ 5–7 min (estimated) | **$0.003** from 17 October 2026 (until then $0.002) |
| **Fast, Apify Proxy datacenter** | proxy on → any other Apify Proxy group (4 IPs: datacenter IPs are shared) | ≈ 1 min (estimated) | ≈ 7 min (estimated) | **$0.003** from 17 October 2026 (until then $0.002) |
| **Fast, your proxies** | proxy on → your proxy URLs, one per IP | like Apify Proxy with 8 or more URLs; one URL = normal speed | | **$0.002** |

Measured in the Apify cloud on 2026-10-03 (build 0.1.9) with `query: "fiets"`, `detail: true`, 150 listings on RESIDENTIAL: 67 s, every row with its detail fields, one IP replaced on the way, ≈ 26 KB of proxy traffic per listing; each IP opened about 20–30 listing pages a minute (the proxy adds latency), below the 40-a-minute cap. On the automatic (datacenter) group: 40 listings in 18 s on 4 IPs, all with detail fields. Datacenter IPs are shared with other Apify users, so some may already be refused — the run replaces those. Normal-mode times follow from the 40-a-minute pace (Limits).

- **One price per listing in each mode.** From 17 October 2026 (06:00 UTC) a fast run on Apify Proxy charges the *fast-mode listing* event **instead of** the normal *listing* event, not on top of it; the extra $0.001 pays for the proxy traffic (≈ 26 KB per listing, measured 2026-10-03). With your own proxies the traffic is yours, so the normal price stays. Without `detail` the proxy is not used and the normal price applies. Until 17 October every row costs the normal price in every mode. Run start: $0.005 in every mode.
- **Same pace per IP.** Each IP starts its next listing page at least 1.5 s after its previous one (≤ 40 a minute), like a normal run. Before a proxy IP is used, the run reads it (Apify's own echo endpoint, not marktplaats.nl): two IP slots never share one IP. An IP marktplaats.nl refuses (HTTP 403/429) or that stops answering is replaced by a new one (up to 3 times per IP slot) and its listing is opened on another IP; a listing refused on 3 IPs keeps its search data with `detailError`. If every IP is used up, the rest of the current results page is saved with search data only (`detailError: "skipped: …"`) and no further pages are read — like a normal run after a block it could not wait out. A challenge or captcha page is never routed around: it counts as a failed listing page.
- **Which proxy.** Your own proxies: `http://` or `https://` URLs (SOCKS is not supported), one URL per IP; a "rotating" gateway URL counts as one IP. `SUMMARY.speed` shows the mode, the IPs used, IPs replaced and the charged event.

**Discounts:** Bronze −10 %, Silver −20 %, Gold and above −30 % on the listing price (normal and fast); the start event ($0.005) is the same on every plan; platform usage and, in fast mode on Apify Proxy, the proxy traffic are included.

**Typical runs (normal price):** a 100-item price check costs about $0.205; a `detail: true` run costs the same per item. `mode: categories` writes the whole tree — about 1,960 rows, so **about $4** on the free plan (pass a `category` for one branch); `mode: facets` rows are billed as rows too (normal price). The run stops at your "Maximum cost per run" and says so in its status.

### Limits & FAQ

- **Speed** — the search API returns 100 listings per request and is not throttled (2,000 listings in about 30–40 s, measured October 2026). The site caps a query at 5,000 results (`maxAllowedPageNumber`); narrow with category/price/postcode for more coverage.
- **Listing pages (`detail: true`)** — marktplaats.nl refuses listing pages from one IP after about 55–65 of them in a minute (HTTP 403; measured October 2026 at ~70 a minute) and lifts the block within about 3.5 minutes. The actor therefore opens at most **40 listing pages a minute** (~1.5 s each: 100 listings ≈ 3 min, 300 ≈ 8 min, 1,000 ≈ 25 min — keep the run timeout above that); at that pace a 300-listing run read 298 pages without a single block (2 listings had been removed), October 2026. If a 403 comes anyway (another run on the same Apify server counts too), the run pauses 3.5 min, retries the same listing and goes on more slowly; a second pause is 4 min (fast mode replaces a refused IP instead of waiting, see [Speed and pricing](#speed-and-pricing)). If the block outlasts both pauses, the rest of the current results page is saved with list data only and `detailError: "skipped: …"`, no further pages are read, and the status says "detail for N of M" and that the run stopped early — wait 15 minutes before the next detail run. Rows are saved every 10 listings, so a stop or an abort loses at most a few page reads.
- **Freshness** — live search results. List dates are day labels; `detail: true` gives the exact `publishedAt`.
- **Blocking** — the search API has been stable without proxies (fast mode never uses a proxy for it). If it answers 403 or a challenge page on the first page, the run fails with a clear error; on a later page the run keeps what it saved and the status names the page that failed. A removed listing (HTTP 404) carries its own `detailError` ("listing no longer on marktplaats.nl"); 3 listing pages in a row that fail for another reason (layout change, no answer) stop listing pages like a block.
- **Spending limit and timeout** — the run never goes over your "Maximum cost per run": it stops at it with "Stopped at your spending limit: N rows delivered". Near the run timeout it stops opening pages, saves what it has and ends SUCCEEDED with "Stopped before the run timeout".
- **Seller type** — the API only filters private/business for cars; there every row gets `sellerType` from the filter. Elsewhere the search data identifies business sellers only when they show a website link, dealer tools or a company logo — not every business does (3 of 9 business listings in a small September 2026 sample had none). So without `detail`, `private` may keep a few businesses (they stay `sellerType: null`, counted in the status) and `business` returns only the businesses that show such a signal; use `detail: true` for an exact answer.
- **Not included** — phone numbers, bidder identities, private messages. Only what the public page shows.
- **Roadmap** — saved-search diffing (only items not seen in a previous run), seller-profile mode.

***

Made by **Yadroo**. Related actors: [kleinanzeigen-de](https://apify.com/yadroo/kleinanzeigen-de) · [willhaben-at](https://apify.com/yadroo/willhaben-at) · [otodom-pl](https://apify.com/yadroo/otodom-pl) · [rightmove-uk](https://apify.com/yadroo/rightmove-uk) · [autoscout24-cars](https://apify.com/yadroo/autoscout24-cars) · [krisha-kz](https://apify.com/yadroo/krisha-kz) · [kolesa-kz](https://apify.com/yadroo/kolesa-kz)

# Actor input Schema

## `query` (type: `string`):

Keyword(s) searched in title and description, e.g. "racefiets", "iphone 15", "bakfiets elektrisch". Optional when a category is given.

## `category` (type: `string`):

L1 category key or id, optionally with an L2 subcategory: "fietsen-en-brommers", 445, "fietsen-en-brommers/fietsen-racefietsen", "445/464". Subcategory ids/keys are resolved live against the site. Full L1 list in the README; run mode "categories" for the complete tree.

## `subcategory` (type: `string`):

Alternative to the "l1/l2" notation: L2 key, id or (part of the) name, e.g. "racefietsen" or 464. Requires category.

## `mode` (type: `string`):

"search" returns listings. "categories" returns the whole category tree (no query needed): about 2,000 rows, billed as rows like listings — roughly $4 on the free plan; pass a category to get one branch. "facets" returns every filter value (condition, brand, delivery…) valid for the given query/category, with the exact ids to pass in attributeIds / attributesByKey / attributeRanges. maxItems applies to search only.

## `postcode` (type: `string`):

Dutch postcode used as the centre for distance filtering and sorting, e.g. 1012AB. Each listing then gets distanceMeters.

## `distanceMeters` (type: `integer`):

Radius around the postcode in metres. The site UI offers 3000, 5000, 10000, 15000, 25000, 50000, 75000, 100000; any value works. Requires postcode.

## `priceFrom` (type: `integer`):

Minimum price in euro.

## `priceTo` (type: `integer`):

Maximum price in euro.

## `condition` (type: `array`):

Item condition (facet "Conditie"). Several values = OR.

## `delivery` (type: `string`):

Only listings offering this delivery method.

## `sellerType` (type: `string`):

Cars (category auto-s) are filtered by the site itself. Other categories have no seller filter on the site: with detail: true the seller type is read from each listing page and filtered exactly (a listing whose page could not be read is dropped and counted). Without detail, "private" drops listings whose search data shows a business (website link, dealer tools, company logo) and keeps the rest unverified (sellerType null); "business" keeps only listings whose search data shows a business — about 1 in 3 business sellers shows none of these and is found only with detail: true.

## `offeredSince` (type: `string`):

Site filter "Aangeboden sinds". Passed to the site and additionally enforced client-side on the listing date (day precision).

## `sinceHours` (type: `integer`):

Drop listings older than N hours. With detail: true the cut-off is exact (publish time from the listing page); a listing whose page could not be read, and every listing without detail, is judged by its list date label (whole days: kept when its day started less than N + 24 hours ago). Combine with sortBy SORT\_INDEX for monitoring runs.

## `priceTypes` (type: `array`):

Client-side filter on the price type. Empty = keep all.

## `attributeIds` (type: `array`):

Raw facet value ids (attributesById), e.g. \[473] = fuel Benzine, \[534] = Automaat in cars, \[30] = Nieuw. Get them from mode "facets".

## `attributesByKey` (type: `array`):

Raw key:value facet filters (attributesByKey), e.g. "offeredSince:Vandaag". Get keys/values from mode "facets".

## `attributeRanges` (type: `array`):

Range facets as key:from:to, e.g. "constructionYear:2018:2024", "mileage:0:100000" (cars), "engineHorsepower:150:". Keys from mode "facets".

## `sortBy` (type: `string`):

SORT\_INDEX + DECREASING = newest first (best for monitoring). PRICE + INCREASING = cheapest first.

## `sortOrder` (type: `string`):

Defaults to DECREASING, except PRICE and LOCATION which default to INCREASING.

## `sortAttribute` (type: `string`):

Only for category auto-s.

## `includeSponsored` (type: `boolean`):

Also return the paid "topBlock" listings shown above organic results (flagged sponsored: true).

## `detail` (type: `boolean`):

Open every listing's page for the full description, exact publish time, view/favourite counts, seller type & years active, bids, shipping and all photos. marktplaats.nl refuses listing pages from one IP after about 60 in a minute (HTTP 403, lifted within ~3.5 min), so the run opens at most 40 a minute (~1.5 s per listing: 100 listings ≈ 3 min, 300 ≈ 8 min). On a 403 it pauses 3.5 min (then 4 min), retries the same listing and goes on more slowly. If the block does not lift, the rest of the current results page is saved with list data only and detailError "skipped: …", the run stops early and the status says "detail for N of M".

## `maxItems` (type: `integer`):

Stop after this many listings (search mode; 100 per search page, pagination automatic; the site stops at 5,000 results per query). Rows dropped by client-side filters do not count. Modes categories and facets return their whole list.

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

Hard cap on search-result pages (100 listings each).

## `fields` (type: `array`):

Keep only these top-level fields in each item, in this order (e.g. \["id","title","price","city","url"]). Every row keeps id (facets rows: facetKey and valueKey), and with detail: true also detailError when a listing page was not read; they come first unless you list them. A different letter case or a near miss ("titel") is read as the output field and noted in the status; detail-only fields without detail: true and unknown names are ignored with a note; if no name is an output field the run fails and lists the valid names. Empty = all fields.

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

Off (default) = the normal run: listing pages at most 40 a minute on one IP. On = fast mode for detail: true: several IPs open listing pages at once, each at that same pace (Apify Proxy RESIDENTIAL: 8 IPs, datacenter groups: 4). Apify Proxy: from 17 Oct 2026 $0.003 per listing instead of $0.002 (one price, not both). Own proxy URLs (one per IP, up to 10): normal price. Without detail the proxy is not used.

## Actor input object example

```json
{
  "query": "fiets",
  "mode": "search",
  "sellerType": "all",
  "sortBy": "SORT_INDEX",
  "includeSponsored": false,
  "detail": false,
  "maxItems": 50,
  "maxPages": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One item per listing: id, title, description, price, priceType, city, distance, coordinates, seller, category, date, attributes, images, url — plus descriptionFull, publishedAt, viewCount, sellerType, bids when detail is on (detailError when a listing page was not read). In mode categories/facets the dataset holds reference rows instead.

## `summary` (type: `string`):

SUMMARY record: rows saved, matching total, "detail for N of M", pauses for marktplaats.nl's per-IP limit, rows dropped by each filter, notes, and why the run stopped early (spending limit, timeout, block).

# 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 = {
    "query": "fiets",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yadroo/marktplaats-nl").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 = {
    "query": "fiets",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("yadroo/marktplaats-nl").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 '{
  "query": "fiets",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call yadroo/marktplaats-nl --silent --output-dataset

```

## MCP server setup

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

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/7Qwae6VOnrBJ7J18b/builds/YTlLvbRsBdh4hRaEN/openapi.json
