Marktplaats.nl Scraper
Scrape Marktplaats.nl as clean JSON: paste your search links, filters included, or run several searches at once, and get only new listings on a schedule.
Scrape Marktplaats.nl as clean JSON: paste your search links, filters included, or run several searches at once, and get only new listings on a schedule. Prices, condition, category specs, locations and images. GDPR-clean: no seller names or contact data, ever.
$1.99 / 1,000 · 99.7% success over 2,272 public runs in the last 30 days.
Run it on Apify → Free to try - runs bill per result on your own account.
What you give it
Every field is optional unless marked; sensible defaults do the rest.
| Field | Type | What it does | Default |
|---|---|---|---|
searchQuery |
string | Free-text search. Provide this, a category, or both. | fiets |
searchQueries |
array | Several searches in one run, one per line, e.g. gazelle and sparta. Each one uses the filters below. A listing found by two searches is delivered once. Up to 50. |
- |
startUrls |
array | Set up a search on marktplaats.nl with any filters you like (category, condition, brand, price, distance...), then paste the address of the results page here, including everything after the #. Add as many as you watch, up to 50. When URLs are given, the search fields of this form are ignored and the run status says which ones were. Posted-date window, max items and only-new mode still apply. A listing page or another site is refused with the reason. |
- |
categoryId |
integer | Numeric marketplace category ID to scope the crawl. Every result includes its categoryId, so run a broad search first to discover the IDs you need. Optional. |
- |
listingIds |
array | Fetch these exact listings instead of searching, e.g. ["m2421501285"] - the id is in every listing URL and every dataset item. Useful to re-check price or availability of listings you found earlier. When set, all search filters are ignored. | [] |
postcode |
string | Dutch postcode to search around, e.g. "3511AA". Combine with radiusKm to narrow the search area. The distance itself is not returned as a field. | - |
radiusKm |
integer | Only return listings within this many km of the postcode. Requires postcode. | - |
conditions |
array | Only return listings in these conditions. Empty = all conditions. Without a category ID the search runs category by category, because the marketplace applies this filter only inside a category. | [] |
delivery |
string | Only listings offering pickup, or only listings that ship. "any" = no filter. | any |
buyItNowOnly |
boolean | Only listings with the "Direct Kopen" (buy it now) option. | False |
priceMinEur |
integer | Only return listings priced at or above this amount. Optional. | - |
priceMaxEur |
integer | Only return listings priced at or below this amount. Optional. | - |
sortBy |
string | Order of the results. Newest first is the default and the right choice for monitoring. | date |
postedAfter |
string | Only keep listings posted on or after this date. Listings whose posting date cannot be read are excluded when a window is set. Format: YYYY-MM-DD (for example 2026-09-08) or a full ISO timestamp such as 2026-09-08T14:30:00Z. Slash dates like 08/09/2026 are refused on purpose: they are read as September in Europe and August in the United States, and this actor will not guess which you meant. |
- |
postedBefore |
string | Only keep listings posted on or before this date. Format: YYYY-MM-DD (for example 2026-09-08) or a full ISO timestamp such as 2026-09-08T14:30:00Z. Slash dates like 08/09/2026 are refused on purpose: they are read as September in Europe and August in the United States, and this actor will not guess which you meant. |
- |
maxItems |
integer | Stop after this many listings, across all searches of the run. With several searches, each gets an equal share of what is left. | 1000 |
onlyNewListings |
boolean | For scheduled runs: return only listings this search has not delivered before. The first run returns the usual results and remembers them; later runs skip them, and skipped listings are not charged. The memory is kept per search (and per task) in a key-value store named marktplaats-scraper-seen-listings in your own account, for 90 days. Changing a search's filters starts a fresh memory. |
False |
resetState |
boolean | With only-new mode on: forget what the searches of this run delivered before, return the full results once and remember again. | False |
scrapeDetails |
boolean | The search returns only a ~200-character description snippet and one photo per listing. Turn this on to read each listing's own page for the seller's full description and every photo in its gallery. This makes one extra request per listing, so a run is slower and costs one more page fetch each. The seller/trader block is never read; only the description text and image URLs reach the output. Leave off for a fast search-only sweep. | False |
reportFailures |
boolean | When a run fails, send the developer the actor name and build, an error category, the error message (truncated) and a one-way hash of your input - so a bug can be fixed without anyone asking you to reproduce it. Your input itself, your results and your identity are never sent, and successful runs send nothing at all. Switch this off and the actor behaves exactly the same. | True |
What you get back
One JSON object per result, with exactly these fields - no seller identities, no contact data, ever.
A real result row from a recent run:
{
"attributes": {
"color": "Wit",
"constructionYear": "2020",
"driveTrain": "Voorwielaandrijving",
"fuel": "Diesel",
"numberOfCilindersCars": "4 cilinders",
"transmission": "Handgeschakeld"
},
"categoryId": 95,
"city": "Amsterdam",
"country": "Nederland",
"description": "Opel vivaro diesel uit 2020 kilometerstand 168.690. Vraagprijs €8999,- inclusief btw met factuur algemene informatie carrosserievorm: bestel...",
"imageUrls": [
"//images.marktplaats.com/api/v1/hz-mp-pro-listing/images/fd3d7d2c-423e-4fbd-ba54-fb8ae01ee0d6?rule=ecg_mp_eps$_82.jpg"
],
"latitude": 52.380485764006,
"listingId": "m2448779143",
"longitude": 4.8691689174877,
"postedAt": "Vandaag",
"postedDate": "2026-10-18",
"priceCents": 899900,
"priceType": "MIN_BID",
"reserved": false,
"sellerType": "private",
"title": "Opel Vivaro GB 1.5 Diesel 100pk L2h1 S/S 2020 Wit",
"url": "https://www.marktplaats.nl/v/auto-s/bestelauto-s/m2448779143-opel-vivaro-gb-1-5-diesel-100pk-l2h1-s-s-2020-wit"
}
| Field | Type | Meaning |
|---|---|---|
listingId |
string | Marketplace listing ID, e.g. m2420174899. |
title |
string | Listing title as posted. |
description |
string | Listing description. The ~200-character search snippet by default, or the seller's full free-text description when Fetch full descriptions is on (read from the listing's own page; the seller/trader block is never read). |
priceCents |
integer | Asking price in euro cents. Absent when the listing has no price. |
priceType |
string | Marketplace price kind, e.g. FIXED or MIN_BID. |
city |
string | Municipality of the listing. |
country |
string | Country of the listing (usually Nederland). |
latitude |
number | Marketplace-provided municipality-level coordinate, not a seller address. |
longitude |
number | Marketplace-provided municipality-level coordinate, not a seller address. |
postedAt |
string | Posting date as the marketplace displays it: a date, or a relative label like 'Vandaag' (today). |
imageUrls |
array | Protocol-relative image URLs; prepend https: to use them. |
categoryId |
integer | Numeric marketplace category ID. Reusable as the categoryId input. |
url |
string | Direct link to the listing. |
attributes |
object | Whitelisted, non-personal listing attributes that vary by category — e.g. condition and delivery on any item; constructionYear, mileage, fuel, transmission and options for cars; livingArea and numberOfRooms for property; storage and cameraResolution for phones. Present when the listing has them. |
reserved |
boolean | Whether the listing is currently marked as reserved by the marketplace. |
sellerType |
string | Whether the listing comes from a business or a private seller. The only seller-related field in the output. |
postedDate |
string | Posting date normalized to YYYY-MM-DD (from the site's display date). |
Health
99.7% success over 2,272 public runs in the last 30 days. Live record, failures included: status page.
Full documentation, examples and the AI-assistant prompt live on the store page.
Questions
Is scraping Marktplaats legal?
This is not legal advice. The actor reads what any logged-out visitor sees on marktplaats.nl, with no login, no CAPTCHA solving and no private endpoints, and it extracts no seller name, contact detail or profile, so the output holds no personal data. Whether your own use of the listings is allowed under the site's terms and your jurisdiction's rules is yours to assess.
Can I get only new listings?
Yes. Switch on onlyNewListings and every scheduled run delivers only the listings it has not delivered before, which is what an hourly watch needs. The first run returns the full result set as a baseline, and resetState starts the memory over.
How much do 10,000 listings cost?
$19.90, billed per delivered listing at $1.99 per 1,000. That price covers the run's platform usage, and a run that fails or returns nothing bills nothing.
Does it return seller phone numbers?
No. The only seller field is whether the seller is a business or a private person. Names, phone numbers, profiles and exact addresses are never extracted, and a test on every build fails if one ever appears, so this is not a setting that can be switched off.
Does a big search come through complete?
Yes. The marketplace caps what one query will page through, so the actor splits a large search by category and price band, runs the parts and removes duplicates, and the run says so when a part is still larger than the site's window.
Do I get the full description and all photos?
By default a row carries the short snippet and the one photo the search page shows. Turn on scrapeDetails and each listing is read from its own page for the full text, every gallery photo and a second-precise posting timestamp, at the cost of one extra request per listing.
The history behind this tool
This tool answers what a source shows today. Its output also feeds a series recorded every day and kept: Used car asking prices and listing lifecycles. A run gives you the current market; the series is the part that cannot be reconstructed afterwards, because the source overwrites it.