Marktplaats.nl $1💰 Listings, Prices, Sellers
Pricing
from $1.00 / 1,000 listing scrapeds
Marktplaats.nl $1💰 Listings, Prices, Sellers
From $1/1K. Scrape Marktplaats.nl listings: title, price, condition, location with coordinates, all photos, seller name/type/rating/reviews, shipping, views, and full per-category attributes (cars, bikes, electronics). Search by keyword or paste URLs.
Pricing
from $1.00 / 1,000 listing scrapeds
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
2
Monthly active users
6 days ago
Last modified
Categories
Share
Marktplaats.nl Scraper
Extract structured listing data from Marktplaats.nl, the largest online marketplace in the Netherlands. Search by keyword and filters or paste listing and result-page URLs, and get clean JSON for every advert: title, price, condition, location with GPS coordinates, every photo, seller name/type/rating/reviews, shipping options, view and favorite counts, and the complete per-category attribute set (cars, bikes, electronics, and more).
Why This Scraper?
- Complete field coverage: 150+ fields per listing including price, condition, full description, all photos, GPS coordinates, seller profile, shipping and per-category attributes.
- Rich automotive data: for vehicle adverts it pulls make, model, trim, construction year, mileage, fuel, transmission, body type, power, cylinder capacity, energy label, options and more.
- Seller insight: seller name, private vs professional, active-since, rating and number of reviews, and payment method.
- Two input modes: build searches from keywords plus filters, or paste any listing or result-page URL.
- Fast and lightweight: runs on the free tier with the default datacenter proxy.
- Result paging with duplicate protection: collects result pages up to your chosen limit without returning repeats.
- Optional detail enrichment: toggle full detail pages on for views, favorites, shipping, bids, reviews and the full description.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
| id | m0000000000 |
| title | Koga elektrische fiets |
| priceNumeric | 399.0 |
| priceType | MIN_BID |
| currency | EUR |
| condition | Zo goed als nieuw |
| brand | Koga |
| description | Nette elektrische fiets, inclusief oplader. |
| location_cityName | Amsterdam |
| location_latitude | 52.3702 |
| location_longitude | 4.8952 |
| sellerName | Jane Doe |
| sellerType | CONSUMER |
| sellerRating | 4.9 |
| sellerReviews | 37 |
| viewCount | 73 |
| savedCount | 3 |
| mileage | 89900 |
| fuelType | Benzine |
| transmission | Automaat |
| imageUrl | https://images.marktplaats.com/api/v1/.../image.jpg |
| url | https://www.marktplaats.nl/v/.../m0000000000-koga |
Incremental mode only. When incrementalMode is on, every returned record also carries:
| Field | Description |
|---|---|
| changeType | NEW | UPDATED | UNCHANGED | REAPPEARED | EXPIRED |
| changedFields | Top-level fields that changed since last seen; non-empty only for UPDATED |
| firstSeenAt | When this listing was first observed by this monitoring campaign |
| lastSeenAt | When this listing was last observed |
How to Use
1. Keyword search with detail enrichment
{"mode": "search","queries": ["fiets"],"fetchDetails": true,"maxListings": 50,"proxy": { "useApifyProxy": true }}
2. Browse a category with price and seller filters
{"mode": "search","queries": [""],"categoryId": 91,"minPrice": 5000,"maxPrice": 20000,"sellerType": "COMMERCIAL","sortBy": "PRICE","sortOrder": "INCREASING","maxListings": 100,"proxy": { "useApifyProxy": true }}
3. Search near a postcode
{"mode": "search","queries": ["bankstel"],"postcode": "1011AB","distanceMeters": 15000,"maxListings": 40,"proxy": { "useApifyProxy": true }}
4. URL mode (listing or result pages)
{"mode": "url","urls": ["https://www.marktplaats.nl/l/auto-s/","https://www.marktplaats.nl/v/fietsen-en-brommers/fietsen-dames-damesfietsen/m0000000000-koga"],"fetchDetails": true,"maxListings": 60,"proxy": { "useApifyProxy": true }}
Input Parameters
| Parameter | Type | Description |
|---|---|---|
| mode | select | search (keyword + filters) or url (paste URLs). |
| queries | array | One or more search keywords. Empty browses a whole category. |
| categoryId | integer | Numeric category id to restrict results (e.g. 91 = Auto's). |
| sortBy | select | OPTIMIZED, SORT_INDEX, PRICE, DATE. |
| sortOrder | select | DECREASING or INCREASING. |
| minPrice / maxPrice | integer | Keep listings within this euro range. |
| sellerType | select | any, CONSUMER, or COMMERCIAL. |
| postcode | string | Dutch postcode to centre a distance search on. |
| distanceMeters | integer | Radius in meters around the postcode. |
| urls | array | Listing or result-page URLs (URL mode). |
| fetchDetails | boolean | Visit each detail page for views, shipping, reviews, full description. |
| maxPages | integer | Optional bound on result pages walked per keyword/category/URL; leave empty to walk every result page. The run size is controlled by maxListings, which this field defers to. |
| maxListings | integer | THE run cap: total listings to return; default 20, 0 = unlimited. |
| resumeFromRunId | string | Optional. ID of a previous run of this actor (or a dataset ID). Listings already in that dataset are skipped, so this run returns only NEW listings (a delta). Continues ONE specific interrupted run — for recurring monitoring of the same search, use incrementalMode instead. |
| incrementalMode | boolean | Off by default. Turn on for daily/recurring monitoring of the same search: the first run returns everything as NEW; later runs return only NEW/UPDATED/REAPPEARED listings, each carrying changeType, changedFields, firstSeenAt, lastSeenAt. State is scoped per mode/queries/categoryId/urls/fetchDetails/filters, so two differently-filtered runs never share a baseline. |
| stateKey | string | Optional, incremental mode only. Name a monitoring campaign to keep its state stable or deliberately share it across runs. Leave empty to derive the key automatically from the search + filter settings. |
| emitUnchanged | boolean | Off by default, incremental mode only. Also return listings unchanged since the last run, marked UNCHANGED (bills those rows too). |
| emitExpired | boolean | Off by default, incremental mode only. Also return listings from a previous run no longer found, marked EXPIRED. Only produced after a complete, uncapped, non-resumed scan of the tracked search. |
| proxy | object | Proxy configuration; Apify datacenter proxy by default (works on the free tier). |
| residentialCountries | array | Countries rotated through when the residential tier is used as a fallback. Default NL, BE, DE, FR, GB. |
| maxResidentialRequests | integer | Cap on residential requests per run, to control cost; the run auto-downgrades to datacenter once spent. Default 200. 0 disables residential. |
| backupProxyUrl | string | Optional last-resort proxy gateway URL. Leave blank to use the built-in default. |
| mcpConnectors | array | Optional MCP connectors to pipe a copy of each listing into (Notion, Linear, Airtable, Apify). Authorize one under Apify → Settings → Integrations, then pick it here. Leave empty to skip. |
| notionParentPageUrl | string | Notion only: URL (or id) of the page under which listing pages are created. Required to enable the Notion export; ignored by other connectors. |
| maxNotifyListings | integer | Cap on items written to each connector per run. Does not affect the dataset. Default 50. |
Resume & recurring updates
Two different things — pick the one that matches what you're doing:
| Need | Use |
|---|---|
| A crawl stopped and should continue | resumeFromRunId / automatic checkpoint recovery |
| Run the same search every day and receive only changes | incrementalMode |
| Keep separate daily campaigns for similar searches | distinct stateKey values |
| Run a normal full snapshot | leave both off |
Resume (resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips listings already collected there, returning only the remaining new listings. An automatic same-run checkpoint also protects against platform migrations/Resurrects without any input needed.
Incremental mode (incrementalMode) is for a schedule (for example, daily): the actor remembers the previous run of the same search by itself, so you never paste a run ID. The first run returns everything as NEW. Later runs return only NEW, UPDATED, and REAPPEARED listings by default — duplicates and unchanged listings are suppressed (and not charged). Turn on emitUnchanged or emitExpired only when you also want those rows returned (and billed for). State is isolated per mode/queries/categoryId/urls/fetchDetails/filter combination automatically; set stateKey to name or deliberately share a monitoring campaign.
Scheduled-run example — same search, run daily:
Day 1 (first run ever for this search):
{ "mode": "search", "queries": ["fiets"], "incrementalMode": true }
→ every listing comes back with "changeType": "NEW".
Day 2 (the schedule fires again, identical input):
{ "mode": "search", "queries": ["fiets"], "incrementalMode": true }
→ listings whose price/condition/etc. changed come back as "changeType": "UPDATED" with changedFields listing what changed, brand-new listings come back as "changeType": "NEW", listings that vanished and came back come back as "changeType": "REAPPEARED" — and listings that are still there, unchanged, are not returned at all (suppressed, not charged) unless emitUnchanged is on.
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "m0000000000","title": "Koga elektrische fiets","url": "https://www.marktplaats.nl/v/fietsen-en-brommers/fietsen-dames-damesfietsen/m0000000000-koga","priceNumeric": 399.0,"priceType": "MIN_BID","currency": "EUR","condition": "Zo goed als nieuw","brand": "Koga","description": "Nette elektrische fiets, inclusief oplader en fietstassen.","categoryId": 447,"category": { "id": 447, "name": "Damesfietsen", "parentName": "Fietsen en Brommers" },"location_cityName": "Amsterdam","location_latitude": 52.3702,"location_longitude": 4.8952,"imageUrl": "https://images.marktplaats.com/api/v1/listing/images/0000.jpg","image_urls": ["https://images.marktplaats.com/api/v1/listing/images/0000.jpg"],"attributes": { "condition": "Zo goed als nieuw", "brand": "Koga", "delivery": "Ophalen of Verzenden" },"seller": {"id": 0,"name": "Jane Doe","type": "CONSUMER","activeSince": "1 jaar","paymentMethod": "ideal"},"sellerName": "Jane Doe","sellerType": "CONSUMER","sellerRating": 4.9,"sellerReviews": 37,"viewCount": 73,"savedCount": 3,"shipping": { "method": "DELIVERY", "carrierName": "PostNL", "price": "€ 5,49" },"date": "Vandaag","scrapedAt": "2026-01-01T00:00:00+00:00"}
Send results into your apps (MCP connectors)
Optionally pipe the scraped listings into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape — the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each listing — not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where listings should be created. - Use
maxNotifyListingsto cap how many listings are written to each connector per run.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Plan Requirement
Runs on any Apify plan, including the free tier, using the default Apify datacenter proxy. Heavier runs with detail enrichment benefit from a paid plan for higher concurrency and proxy throughput.
Proxy policy
The scraper uses a tiered, cost-first proxy strategy:
- Datacenter (default). Datacenter is the default and works on every plan, including the free tier.
- Residential (optional, budgeted fallback). Selecting the residential proxy group is bounded by
maxResidentialRequests. Because residential traffic is billed at a higher rate, the run falls back to datacenter once that budget is spent. - Backup gateway (last resort). If the Apify proxy is unavailable on your plan, the run uses a backup gateway (override with
backupProxyUrl) instead of returning nothing.
Run logs reference only the abstract tier (datacenter / residential / backup) and never expose any geography.