Marktplaats.nl Scraper avatar

Marktplaats.nl Scraper

Pricing

from $1.50 / 1,000 results

Go to Apify Store
Marktplaats.nl Scraper

Marktplaats.nl Scraper

Scrape listings from Marktplaats.nl, 2dehands.be and 2ememain.be — Benelux's largest classifieds platforms with 10M+ active listings. Extract price, seller info, condition, location and category via internal JSON API. No browser needed.

Pricing

from $1.50 / 1,000 results

Rating

0.0

(0)

Developer

Haketa

Haketa

Maintained by Community

Actor stats

1

Bookmarked

14

Total users

5

Monthly active users

13 days ago

Last modified

Share

Marktplaats.nl Scraper — Dutch Classifieds Data Extractor for Cars, Real Estate, Electronics, Fashion & Used Items

The most complete Marktplaats.nl data extraction tool on Apify. Pull live listings from the Netherlands' largest classifieds marketplace — plus its Belgian sister sites 2dehands.be (Flemish) and 2ememain.be (French) — with prices in EUR, normalized condition flags, seller type (particulier / zakelijk), category-specific attributes, location, images and full descriptions. Built for price benchmarking, used-car arbitrage, rental real-estate comps, reseller market intel, dropshipping research and demand-trend analytics across the Benelux region.

Apify Actor


What This Actor Does

The Marktplaats.nl Scraper is a production-ready Apify Actor that extracts live classified listings from marktplaats.nl — the Netherlands' dominant consumer-to-consumer marketplace with over 10 million active listings at any moment — and from the two Belgian sister platforms that share its backend: 2dehands.be (Flemish-speaking Belgium) and 2ememain.be (French-speaking Belgium / Wallonia). The three sites are operated by the same group and expose the same internal JSON API, so a single actor covers the entire Benelux second-hand market.

Marktplaats has been the default place Dutch consumers go to buy and sell used cars, apartments, bicycles (fietsen are a whole vertical of their own), electronics, furniture, fashion, jobs, services and antiques since the late 1990s. The actor hands you back the same data a buyer sees — but as clean, normalized JSON ready for a warehouse, a dashboard, a price-monitoring system or an ML training pipeline. In a single run you can pull thousands of listings filtered by keyword, category, postcode radius, price band and sort order, with optional detail-page enrichment for full descriptions and category-specific attribute tables.

Each record can include:

  • Listing corelistingId (Marktplaats m- identifier), title, price in EUR (parsed from the API's priceCents integer field), normalized priceType (fixed / bidding / free / asking / trade / negotiable / on_request / see_description), the original Dutch priceTypeOriginal (Vaste prijs, Bieden, Gratis, Vraagprijs, Ruilen, Nader overeen te komen), currency (always EUR)
  • Condition — normalized condition (new / like_new / used / not_applicable) and the original Dutch conditionOriginal (Nieuw, Zo goed als nieuw, Gebruikt, Niet van toepassing) — with Belgian French fallbacks (Neuf, Comme neuf, Utilisé) where applicable
  • Taxonomy — L1 category and L2 subcategory names (e.g. Auto'sBMW, TelecommunicatieMobiele telefoons, Huis en InrichtingBanken)
  • SellersellerName, sellerId, and sellerType (private for particulieren / business for zakelijke verkopers and dealers flagged with the SOI-498 trade label)
  • Geolocation city/district string (Amsterdam, Rotterdam, Den Haag, Utrecht, Eindhoven, Groningen, Tilburg, Almere and every Dutch and Belgian gemeente in between)
  • Recencydate in ISO format (the Marktplaats publish/refresh timestamp)
  • Mediaimages array with the largest-available image URLs from the listing gallery
  • LogisticsshippingAvailable boolean indicating whether the seller supports Marktplaats's verzendservice
  • Category-specific attributes — a flexible attributes object that surfaces vehicle specs (kilometerstand, bouwjaar, brandstof, transmissie), property details (oppervlakte, slaapkamers, huurprijs), phone specs (merk, model, opslag) and whatever else the vertical exposes
  • Description — partial from the API search response, full from the detail page when scrapeDetails: true
  • Metadata — the originating platform (marktplaats.nl / 2dehands.be / 2ememain.be), the searchQuery and searchCategory used, full canonical url, and a scrapedAt ISO timestamp on every row

Whether you run a Rotterdam used-car dealership, an Amsterdam sneaker reseller, a Den Haag rental-comp analytics product or a market-intel team tracking second-hand pricing across the Benelux, this actor is the fastest path from Marktplaats.nl to a usable dataset — without writing a line of scraping code.

Why scrape Marktplaats yourself when this exists?

Marktplaats looks like a simple classifieds site. Scraping it at any meaningful scale is not. Teams who try DIY hit the same wall:

  • The public site is a Next.js SPA — requests.get() against a search URL returns a thin HTML shell with no listings; the data only appears after JavaScript executes
  • The internal JSON API at /lrp/api/search is undocumented and the schema is not stable; field names change without notice (sellerInformation vs seller, imageUrls vs pictures, vipUrl vs selfLink, categorySpecificDescription vs description)
  • Prices come back as priceCents integers (a €1,499 BMW is 149900) and must be divided cleanly — naive string parsing of the rendered € 1.499,00 Dutch number format breaks on the thousands-separator dot
  • priceType is an opaque uppercase enum (FIXED, BID, FAST_BID, MIN_BID, FREE, ASKING, TRADE, SEE_DESCRIPTION, RESERVED) that has to be mapped to both human English and the Dutch labels shown on the site
  • Condition is buried inside the attributes array under key: "condition", with Dutch values (Zo goed als nieuw) that need translation to a stable English enum
  • Pagination is capped at 5000 results per query (offset × limit < 5000) — exceed it and the API silently returns empty listings
  • Private vs business sellers are not a clean flag — the API uses a showSoi498Label boolean derived from the EU's Sales of Items 498 commercial-trader label
  • Belgian variants (2dehands.be, 2ememain.be) share the schema but switch the Accept-Language requirement and the price-type labels into Flemish and French — easy to break a parser that hard-codes Dutch
  • Cloudflare and bot-fingerprinting checks kick in for unbranded user agents — the API returns 403 to anything that doesn't look like a real Chrome on Windows with nl-NL locales
  • Detail-page descriptions live inside the __NEXT_DATA__ JSON blob, not the rendered DOM — extracting them requires parsing the Next.js hydration payload and falling back to JSON-LD <script type="application/ld+json"> when missing
  • Listings disappear — sold or expired ads return 404 within hours of removal; scraping must be tolerant
  • Image URLs come in multiple resolutions (mediumUrl, largeUrl, extraExtraLargeUrl) inside nested arrays (imageUrls and/or pictures) — you have to walk both and pick the highest-resolution variant

This actor solves every one of those: direct internal-API calls via got-scraping with realistic Chrome fingerprints bypass bot detection without needing a browser, the parser normalizes EUR prices and price-type enums, condition flags and seller signals are translated into stable English values while preserving the Dutch originals for display, category-aware logic populates vehicle and property fields automatically, and the pipeline pushes deduplicated records straight to the Apify dataset.


Quick Start

One-Click Run

  1. Open the actor page on Apify Store and click "Try for free"
  2. Type a search term in Query (e.g. iphone 15, bmw 320d, vouwfiets, bank tweezits) or leave it empty and pick a Category ID to browse a whole vertical
  3. Optionally add a Dutch Postcode (e.g. 1012AB Amsterdam) plus a Distance in metres to constrain results to a radius
  4. Hit Start — listings stream into your dataset and can be exported as JSON, CSV, Excel, HTML, XML or RSS straight from the Apify dataset view

API Run (Python)

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("haketa/marktplaats-scraper").call(run_input={
"platform": "marktplaats.nl",
"query": "bmw 320d",
"categoryId": "91", # Auto's
"postcode": "3011AA", # Rotterdam centrum
"distanceMeters": 50000, # 50 km
"minPrice": 500000, # €5,000 (in cents)
"maxPrice": 2000000, # €20,000 (in cents)
"sortBy": "PRICE",
"sortOrder": "INCREASING",
"scrapeDetails": True,
"maxListings": 500,
})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
print(listing["title"], listing["price"], listing["location"], listing["sellerType"])

API Run (Node.js / TypeScript)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('haketa/marktplaats-scraper').call({
platform: 'marktplaats.nl',
query: 'iphone 15',
categoryId: '31', // Telecommunicatie
subcategoryId: '1953', // Mobiele telefoons | Apple iPhone
sortBy: 'SORT_INDEX',
sortOrder: 'DECREASING',
scrapeDetails: true,
maxListings: 300,
requestDelay: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Pulled ${items.length} iPhone 15 listings from Marktplaats.nl`);

API Run (cURL)

curl -X POST "https://api.apify.com/v2/acts/haketa~marktplaats-scraper/runs?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"platform": "marktplaats.nl",
"query": "vouwfiets",
"categoryId": "1655",
"postcode": "1012AB",
"distanceMeters": 25000,
"minPrice": 10000,
"maxPrice": 80000,
"sortBy": "SORT_INDEX",
"sortOrder": "DECREASING",
"scrapeDetails": true,
"maxListings": 200
}'

API Run (Belgian platforms)

# Same actor, different platform — Belgian Flemish 2dehands.be
run = client.actor("haketa/marktplaats-scraper").call(run_input={
"platform": "2dehands.be",
"query": "fiets",
"postcode": "1000", # Brussels
"maxListings": 200,
})
# Belgian French 2ememain.be
run = client.actor("haketa/marktplaats-scraper").call(run_input={
"platform": "2ememain.be",
"query": "voiture",
"postcode": "4000", # Liège
"maxListings": 200,
})

How It Works

Marktplaats and its Belgian sister sites are server-rendered Next.js applications backed by a public-facing JSON search API at /lrp/api/search. This actor goes straight at that endpoint with realistic Chrome fingerprints — no headless browser, no Puppeteer, no Playwright for the search phase. Detail-page enrichment (when enabled) uses a separate lightweight HTML fetch that parses the embedded __NEXT_DATA__ hydration payload.

Source endpointURL patternReturns
Search API (NL)https://www.marktplaats.nl/lrp/api/search?query={Q}&l1CategoryId={C}&postcode={P}&distanceMeters={D}&priceFrom={F}&priceTo={T}&limit=30&offset={O}{ listings: [...], totalResultCount: N }
Search API (BE-NL)https://www.2dehands.be/lrp/api/search?...Same schema
Search API (BE-FR)https://www.2ememain.be/lrp/api/search?...Same schema
Detail pagehttps://www.{platform}/v/...{listingId}.htmlNext.js HTML with __NEXT_DATA__ blob and JSON-LD Product/Offer

Engineering details

  • Direct API enginegot-scraping with Chrome 120-126 fingerprints (nl-NL / nl-BE locales, desktop devices, Windows/macOS) hits the search endpoint without browser overhead, returning JSON in well under a second per page
  • Paginationoffset increments by PAGE_SIZE = 30 per page; the loop stops at MAX_OFFSET = 5000 (the platform's hard cap), at maxListings, when listings is empty, or when no new IDs are added on a page
  • Retry with proxy rotation403/429 responses trigger up to three retries with exponential backoff (3s × attempt) and a fresh Apify proxy URL each round
  • Price normalizationpriceInfo.priceCents is divided by 100 to produce a clean EUR float; the actor never tries to parse the rendered Dutch € 1.499,00 string
  • Price-type enum mapping — the API's uppercase enum (FIXED, BID, FAST_BID, MIN_BID, FREE, ASKING, TRADE, SEE_DESCRIPTION, NEGOTIABLE, ON_REQUEST, RESERVED) plus Dutch display strings (Vaste prijs, Bieden, Gratis, Vraagprijs, Ruilen, Nader overeen te komen) and Belgian-French equivalents (Prix fixe, Faire offre, Gratuit, Prix demandé, Échange) all collapse into a stable English priceType value while the original is preserved as priceTypeOriginal
  • Condition normalization — extracted from the attributes array under key: "condition", then mapped from Dutch (Zo goed als nieuw / Gebruikt / Nieuw / Niet van toepassing) and French (Comme neuf / Utilisé / Neuf) to a clean English enum
  • Seller-type inferenceshowSoi498Label (the EU commercial-trader badge) is checked first; presence flips sellerType from private to business
  • Image walker — both imageUrls and pictures nested arrays are walked, picking extraExtraLargeUrllargeUrlmediumUrlurl in that order so the largest-available image always wins
  • Category-specific attributes — every entry in the listing's attributes array (excluding condition, which is normalized separately) and every verticals entry is flattened into a single attributes object — surfacing vehicle specs, property details, phone specs and any other vertical-specific fields the platform exposes
  • Detail-page enrichment — when scrapeDetails: true, the canonical listing URL is fetched, __NEXT_DATA__ is parsed for the full pageProps.listing blob, and JSON-LD Product/Offer blocks act as a fallback for missing descriptions and images
  • Deduplication — a Set of listingIds prevents the same ad being pushed twice when API pages overlap
  • Multi-platform support — switching platform between marktplaats.nl, 2dehands.be, 2ememain.be automatically swaps the base URL, the proxy locale hint and the price/condition label fallbacks

Input Parameters

{
"platform": "marktplaats.nl",
"query": "iphone 15",
"categoryId": "31",
"subcategoryId": "",
"postcode": "1012AB",
"distanceMeters": 25000,
"minPrice": 10000,
"maxPrice": 80000,
"sortBy": "SORT_INDEX",
"sortOrder": "DECREASING",
"scrapeDetails": false,
"maxListings": 50,
"requestDelay": 500,
"proxyConfiguration": { "useApifyProxy": true }
}

Parameter reference

ParameterTypeDefaultDescription
platformstringmarktplaats.nlWhich Benelux platform to scrape. Choices: marktplaats.nl (Netherlands), 2dehands.be (Belgium Flemish), 2ememain.be (Belgium French). All three share the same backend and schema.
querystringiphoneKeyword search term. Searches across title and description (searchInTitleAndDescription=true). Examples: iphone 15, bmw 320, fiets, bank, vouwfiets. Leave empty to browse a whole category.
categoryIdstringemptyMarktplaats L1 category ID. Leave empty for all categories. Common IDs: 31 (Telecommunicatie), 91 (Auto's), 504 (Computers en Software), 322 (Huis en Inrichting), 621 (Kleding Dames), 728 (Sport en Fitness), 1953 (Watches), 1655 (Fietsen en Brommers), 135 (Huizen en Kamers). See the Category Reference table below.
subcategoryIdstringemptyL2 subcategory ID for a narrower search (e.g. Auto'sBMW). Leave empty for the entire L1 category.
postcodestringemptyDutch or Belgian postcode that becomes the centre of the radius search. Examples: 1012AB (Amsterdam), 3011AA (Rotterdam), 2511DV (Den Haag), 3511AA (Utrecht), 5611AA (Eindhoven), 1000 (Brussels).
distanceMetersinteger0Search radius from the postcode in metres. Only takes effect when postcode is set. Examples: 10000 (10 km), 25000 (25 km), 50000 (50 km), 100000 (100 km). 0 = no radius filter.
minPriceinteger0Minimum price in cents (so 10000 = €100). 0 = no lower bound.
maxPriceinteger0Maximum price in cents (so 100000 = €1,000). 0 = no upper bound.
sortBystringSORT_INDEXSort key: SORT_INDEX (newest first), PRICE (price), OPTIMIZED (Marktplaats relevance ranking).
sortOrderstringDECREASINGDirection: DECREASING or INCREASING. Combine with sortBy: PRICE and INCREASING for cheapest-first.
scrapeDetailsbooleanfalseWhen true, fetch each listing's detail page for the full description and category-specific attribute tables (car specs, property details, etc.). Slower but more complete.
maxListingsinteger50Maximum total listings to scrape. 0 = unlimited. Note: Marktplaats hard-caps results at ~5,000 per query — use category + postcode + price filters to slice large searches into per-segment runs.
requestDelayinteger500Delay between API calls in milliseconds (010000). Higher values are gentler on the platform and reduce the risk of 429 throttling.
proxyConfigurationobjectApify ProxyApify proxy settings. The internal API works without proxy from most IPs, but residential proxies improve reliability for very large runs.

Output Schema

Every record uses the same flat JSON schema so downstream consumers (databases, CRMs, BI tools) can ingest the entire dataset without per-category branching.

Core fields

FieldTypeDescription
listingIdstringMarktplaats listing identifier in m-/numeric form
platformstringSource platform: marktplaats.nl / 2dehands.be / 2ememain.be
titlestringListing title as displayed
pricenumberPrice in EUR (already divided from priceCents) — null for Bieden, Gratis, Vraagprijs listings without an asking number
priceTypestringNormalized: fixed / bidding / free / asking / trade / negotiable / on_request / see_description / reserved
priceTypeOriginalstringOriginal Dutch (or Flemish/French) label: Vaste prijs, Bieden, Gratis, Vraagprijs, Ruilen, Nader overeen te komen, Op aanvraag, Zie omschrijving, Gereserveerd
currencystringAlways EUR
conditionstringNormalized: new / like_new / used / not_applicable
conditionOriginalstringOriginal Dutch (or French): Nieuw / Zo goed als nieuw / Gebruikt / Niet van toepassing / Neuf / Comme neuf / Utilisé
categorystringL1 category name (e.g. Auto's, Telecommunicatie, Huis en Inrichting)
subcategorystringL2 subcategory name (e.g. BMW, Mobiele telefoons, Banken)

Seller fields

FieldTypeDescription
sellerNamestringSeller display name
sellerIdstringMarktplaats internal seller ID
sellerTypestringprivate (particulier) / business (zakelijk, SOI-498 trade badge present)

Location / recency fields

FieldTypeDescription
locationstringCity or district name (e.g. Amsterdam, Rotterdam-Zuid, Antwerpen)
datestringISO timestamp of when the listing was posted/refreshed

Content fields

FieldTypeDescription
descriptionstringPartial from search API; full when scrapeDetails: true
attributesobjectCategory-specific attribute key/value pairs (vehicle specs, property details, phone specs, etc.) — null when none surfaced
imagesarray<string>Largest-available image URLs from the listing gallery
shippingAvailablebooleantrue when the seller supports Marktplaats verzendservice

Metadata fields

FieldTypeDescription
urlstringFull canonical listing URL on the source platform
searchQuerystringThe keyword used to find this listing
searchCategorystringThe category ID used in the search
scrapedAtstringISO-8601 timestamp of extraction

Example: Used iPhone listing (Amsterdam, particulier)

{
"listingId": "m2098765432",
"platform": "marktplaats.nl",
"title": "Apple iPhone 15 Pro 256GB Natural Titanium",
"price": 899.00,
"priceType": "fixed",
"priceTypeOriginal": "Vaste prijs",
"currency": "EUR",
"condition": "like_new",
"conditionOriginal": "Zo goed als nieuw",
"category": "Telecommunicatie",
"subcategory": "Mobiele telefoons | Apple iPhone",
"sellerName": "Jeroen V.",
"sellerId": "48275621",
"sellerType": "private",
"location": "Amsterdam",
"date": "2026-05-14T09:42:00.000Z",
"description": "Nette iPhone 15 Pro 256GB, sinds december 2024 in bezit, altijd met hoesje en screenprotector gebruikt. Doos en originele kabel aanwezig. Accu 98%. Geen krasjes.",
"attributes": {
"merk": "Apple",
"model": "iPhone 15 Pro",
"opslag": "256 GB",
"kleur": "Natural Titanium",
"garantie": "Ja, nog 7 maanden Apple-garantie"
},
"images": [
"https://images.marktplaats.com/api/v1/listing-mp-p/images/9a/9aabc.../?rule=ecg_mp_eps$_84.jpg",
"https://images.marktplaats.com/api/v1/listing-mp-p/images/9a/9aabd.../?rule=ecg_mp_eps$_84.jpg"
],
"shippingAvailable": true,
"url": "https://www.marktplaats.nl/v/telecommunicatie/mobiele-telefoons-apple-iphone/m2098765432-apple-iphone-15-pro-256gb-natural-titanium",
"searchQuery": "iphone 15",
"searchCategory": "31",
"scrapedAt": "2026-05-16T20:00:00.000Z"
}

Example: Used BMW (Eindhoven, zakelijk dealer)

{
"listingId": "m1987654321",
"platform": "marktplaats.nl",
"title": "BMW 320d Touring Sport Line | Pano | LED | Trekhaak",
"price": 18950.00,
"priceType": "fixed",
"priceTypeOriginal": "Vaste prijs",
"currency": "EUR",
"condition": "used",
"conditionOriginal": "Gebruikt",
"category": "Auto's",
"subcategory": "BMW",
"sellerName": "Autobedrijf Van der Berg B.V.",
"sellerId": "11223344",
"sellerType": "business",
"location": "Eindhoven",
"date": "2026-05-15T11:15:00.000Z",
"description": "BMW 320d Touring Sport Line uit 2019. NL auto, 1 eigenaar, dealer onderhouden, NAP. Panoramadak, LED-koplampen, trekhaak, navigatie professional. Inruil mogelijk.",
"attributes": {
"bouwjaar": "2019",
"kilometerstand": "98.450 km",
"brandstof": "Diesel",
"transmissie": "Automaat",
"carrosserie": "Stationwagon",
"vermogen": "190 pk",
"kleur": "Mineraalgrijs metallic",
"btw_marge": "Marge",
"apk": "Tot 03-2027"
},
"images": [
"https://images.marktplaats.com/api/v1/listing-mp-p/images/aa/.../?rule=ecg_mp_eps$_84.jpg"
],
"shippingAvailable": false,
"url": "https://www.marktplaats.nl/v/autos/bmw/m1987654321-bmw-320d-touring-sport-line-pano-led-trekhaak",
"searchQuery": "bmw 320d",
"searchCategory": "91",
"scrapedAt": "2026-05-16T20:00:00.000Z"
}

Price-Type Reference

priceTypepriceTypeOriginal (NL)French (2ememain.be)Meaning
fixedVaste prijsPrix fixeSeller's listed price is firm
biddingBiedenFaire offreBuyers submit bids; no fixed price
freeGratisGratuitItem is free — typically furniture, building leftovers
askingVraagprijsPrix demandéAsking price — small negotiation expected
tradeRuilenÉchangeSeller wants to swap, not sell
negotiableNader overeen te komenOpen to discussion, no number given
on_requestOp aanvraagPrice disclosed on contact only (common for B2B)
see_descriptionZie omschrijvingPrice details inside the description body
reservedGereserveerdReserved for another buyer; still listed

Condition Reference

conditionconditionOriginal (NL)French (2ememain.be)Meaning
newNieuwNeufBrand-new, often still sealed
like_newZo goed als nieuwComme neufUsed briefly, no wear
usedGebruiktUtiliséNormal second-hand condition
not_applicableNiet van toepassingCategory where condition is irrelevant (services, real estate)
categoryIdDutch L1 categoryEnglishNotes
91Auto'sCarsLargest used-car marketplace in NL
92Auto-onderdelenCar partsMechanic and DIY supply chain
1655Fietsen en BrommersBikes & mopedsBicycles dominate Dutch traffic
135Huizen en KamersHouses & roomsSales + rentals, includes vakantiehuizen
322Huis en InrichtingHome & furnishingSofas, tables, lamps, decoration
31TelecommunicatieTelecomPhones, smartwatches, accessories
504Computers en SoftwareComputers & softwareLaptops, desktops, components
322-1133Witgoed en ApparatuurWhite goodsWashers, dryers, fridges
1525Audio, Tv en FotoAudio, TV & photoCameras, hi-fi, televisions
1953Sieraden, Tassen en UiterlijkJewellery, bags, beautyWatches, designer bags
621KledingDames Clothing — women'sApparel, shoes, accessories
728Sport en FitnessSport & fitnessBikes, gym, outdoor gear
1099Kinderen en Baby'sKids & babiesStrollers, toys, clothing
1100Dieren en ToebehorenAnimals & accessoriesPet listings (regulated separately)
367Antiek en KunstAntiques & artCollectibles, paintings
2017Tickets en KaartjesTicketsEvents, concerts, public transport
380BoekenBooksSecond-hand books
356VakantieHolidaysVakantiehuizen, last-minute deals
33Werk en PersoneelJobs & staffVacancies and CVs
34Diensten en VakmensenServices & tradesPlumbers, painters, cleaning

Use Cases

Price benchmarking & dynamic pricing

Pricing analysts, e-commerce operators and reseller platforms use Marktplaats data to anchor their pricing to the live Dutch second-hand market:

  • Pull the median asking price for any model + condition combination (iPhone 15 Pro 256GB like_new) refreshed daily
  • Track price decay curves — how fast does a new iPhone or PlayStation lose value on the Dutch market?
  • Compare zakelijk-dealer pricing vs particulier pricing on the same SKU to size the dealer margin
  • Build city-level price heatmaps (Amsterdam vs Groningen vs Eindhoven) for the same product

Used-car arbitrage & dealer intelligence

Independent dealers, leasing companies and auto-fintech startups use Marktplaats's Auto's (categoryId 91) and Auto-onderdelen (92) verticals to:

  • Identify undervalued private-party listings (particulier, Vaste prijs < market median) for buy-and-flip
  • Track every BMW 3-series, Volkswagen Golf, Tesla Model 3 listed in the past 24 hours across NL
  • Pull kilometerstand, bouwjaar, brandstof, transmissie, APK attributes for full vehicle history records
  • Monitor competing dealers' inventory and price changes in real time
  • Build BPM-tax and import calculators with live NL pricing benchmarks
  • Spot trends: EV vs ICE listing volume by month, Tesla Model Y average price over time

Real estate & rental comps (Benelux)

Property analytics teams, agents and PropTech startups use Marktplaats's Huizen en Kamers category as a complementary signal to Funda and Pararius:

  • Pull every rental listing in Amsterdam, Utrecht, Rotterdam, Den Haag with the huurprijs attribute
  • Compare Marktplaats kamer-te-huur prices against student-housing supply
  • Detect new vakantiehuis listings in coastal NL (Zandvoort, Scheveningen, Texel) within hours
  • Track the long-tail of for-sale-by-owner (particulier) listings that bypass MLS-style portals
  • Cross-reference rental prices across Dutch postcodes for rental-yield analysis

Reseller & dropshipping market intel

Amazon FBA sellers, bol.com merchants, and dropshippers researching the NL/BE market use the actor to:

  • Discover hot product categories by tracking listing volume and median price over time
  • Identify white-space opportunities — high search demand on Google Trends NL but low Marktplaats listing density
  • Source second-hand stock at scale by monitoring Gratis, Bieden and underpriced Vaste prijs listings
  • Benchmark new-product retail pricing against the parallel Marktplaats used market
  • Spot brand-counterfeit risks by sampling listings for premium brands (Stone Island, Moncler, Apple)

Demand-trend & consumer research

Market research firms, FMCG brands and trend agencies use the dataset to:

  • Track week-over-week listing volume per category as a leading indicator of consumer sentiment
  • Identify the most searched-for items by sampling top-of-page OPTIMIZED sort across keywords
  • Build "what Dutch consumers are letting go of" reports — rising listings of treadmills, espresso machines, gaming consoles
  • Cross-reference with weather and seasonality data (e.g. fietsen sales spikes in March)
  • Power academic studies of second-hand economy growth in the Benelux

Brand monitoring & IP protection

Brands, distributors and IP-protection teams use the actor to:

  • Search for counterfeit listings of premium brands (Louis Vuitton, Nike, Apple, Rolex) for takedown actions
  • Detect grey-market sales of branded goods outside authorized channel
  • Monitor warranty fraud — products listed with claims of garantie that exceed manufacturer terms
  • Track stolen-goods patterns by category and region (high-value bicycles are a perennial NL theme)
  • Build evidence packs of unauthorized seller activity with sellerId, sellerName, listing URL and screenshots

Lead generation for B2B services

Marketing agencies, fintech startups and B2B SaaS vendors use the business seller filter to:

  • Build prospect lists of Dutch zakelijke verkopers (car dealers, electronics shops, fashion resellers, jewellery merchants)
  • Enrich CRM with the seller's category mix, location and listing volume as firmographic signals
  • Identify high-volume dealers as ideal-customer-profile (ICP) targets for inventory-management software
  • Power lookalike audiences for B2B advertising platforms

Insurance, valuation & second-hand market research

Insurers, actuaries and second-hand valuation platforms use Marktplaats as a live price-discovery layer:

  • Anchor home-contents insurance payouts to real second-hand replacement costs
  • Build automotive market-value engines for used-car insurance and finance underwriting
  • Power "what is this worth?" consumer-facing apps with live Marktplaats medians
  • Track depreciation curves for electronics, appliances, bicycles, instruments

Journalism & data reporting

Investigative journalists, public-interest media and data reporters use Marktplaats as a Dutch consumer-market mirror:

  • Cover the rise (or fall) of specific consumer trends — e-bikes, heat pumps, gaming consoles, work-from-home equipment
  • Investigate underground trades or regulated-goods listings (firearms, certain pet breeds, restricted plants)
  • Map second-hand market activity to economic cycles, inflation, energy crises
  • Source citizen-reporter listings for regional reporting

Sample Queries & Recipes

Recipe 1: All used iPhones under €700 in the Randstad

{
"platform": "marktplaats.nl",
"query": "iphone",
"categoryId": "31",
"postcode": "1012AB",
"distanceMeters": 60000,
"maxPrice": 70000,
"sortBy": "PRICE",
"sortOrder": "INCREASING",
"maxListings": 500
}

Recipe 2: Cheapest BMW 3-series across NL — full vehicle specs

{
"platform": "marktplaats.nl",
"query": "bmw 320",
"categoryId": "91",
"sortBy": "PRICE",
"sortOrder": "INCREASING",
"scrapeDetails": true,
"maxListings": 1000
}

Recipe 3: Free items in Amsterdam — Gratis listings only

{
"platform": "marktplaats.nl",
"query": "",
"postcode": "1012AB",
"distanceMeters": 20000,
"maxPrice": 1,
"maxListings": 200
}

(Use maxPrice: 1 to capture Gratis items where priceCents is 0 or 1.)

Recipe 4: All zakelijke (business) sellers in the Telecom category

Run the actor with categoryId: "31" and filter sellerType === "business" downstream:

business_dealers = [r for r in records if r["sellerType"] == "business"]

Recipe 5: Rental rooms (kamers te huur) in Utrecht student belt

{
"platform": "marktplaats.nl",
"query": "kamer huur",
"categoryId": "135",
"postcode": "3511AA",
"distanceMeters": 15000,
"minPrice": 30000,
"maxPrice": 100000,
"sortBy": "SORT_INDEX",
"maxListings": 300
}

Recipe 6: Vouwfietsen (folding bikes) in the Belgian Flemish region

{
"platform": "2dehands.be",
"query": "vouwfiets",
"categoryId": "1655",
"postcode": "2000",
"distanceMeters": 50000,
"scrapeDetails": true,
"maxListings": 150
}

Recipe 7: Dropshipping research — every PlayStation 5 listed today

{
"platform": "marktplaats.nl",
"query": "playstation 5",
"categoryId": "504",
"sortBy": "SORT_INDEX",
"sortOrder": "DECREASING",
"maxListings": 500
}

Then in Python:

from datetime import datetime, timezone, timedelta
today = datetime.now(timezone.utc).date()
todays = [r for r in records if datetime.fromisoformat(r["date"].replace("Z","+00:00")).date() == today]

Integration Examples

Google Sheets (via Apify Integration)

  1. Schedule the actor to run daily at 08:00 CET with your favourite keyword + category combination
  2. Add the "Export to Google Sheets" Apify integration to the schedule
  3. Get a fresh Marktplaats CSV in your Sheet every morning — ready for pivot tables and conditional formatting

Make.com / Zapier / n8n

Use the Apify connector available on all major automation platforms. Trigger downstream workflows on:

  • New listings (latest run minus previous run) matching a watch-list query
  • Price drops (compare today's price vs yesterday's by listingId)
  • New zakelijk dealer accounts entering a category
  • Specific keyword hits (e.g. trigger Slack/Telegram alert on any Rolex Submariner listing under €5,000)

Power BI / Tableau / Looker / Metabase

Connect the Apify REST API as a data source, refresh on schedule, and build dashboards covering:

  • Median price by category and city, week over week
  • Listing-volume heat maps across Dutch provinces
  • Sankey diagrams of category → subcategory → condition → price
  • Time-series of new vs business listings per vertical

Postgres / Snowflake / BigQuery

Use the Apify webhook integration to POST run results directly to your data-warehouse ingestion endpoint after every scheduled run. Recommended table schema:

CREATE TABLE marktplaats_listings (
listing_id TEXT PRIMARY KEY,
platform TEXT,
title TEXT,
price_eur NUMERIC(12,2),
price_type TEXT,
condition TEXT,
category TEXT,
subcategory TEXT,
seller_name TEXT,
seller_id TEXT,
seller_type TEXT,
location TEXT,
date TIMESTAMPTZ,
shipping_available BOOLEAN,
attributes JSONB,
images TEXT[],
url TEXT,
scraped_at TIMESTAMPTZ
);
CREATE INDEX ON marktplaats_listings (category, subcategory);
CREATE INDEX ON marktplaats_listings (seller_id);
CREATE INDEX ON marktplaats_listings (date);
CREATE INDEX ON marktplaats_listings USING GIN (attributes);

Salesforce / HubSpot CRM enrichment

Schedule the actor with a business-only category sweep, then upsert into Salesforce Accounts keyed on sellerId. Trigger Workflow Tasks when seller listing-volume crosses thresholds (e.g. "Dealer added 20+ new car listings this week — sales rep follow-up").

Webhooks & alerting

Use Apify webhook events to fire HTTP POSTs on every run completion. Combine with a small Lambda/Cloud Function to:

  • Push new matching listings to Slack, Telegram or Discord watch channels
  • Email subscribers when their saved-search criteria match
  • Update internal price-alert tables in real time

Major Dutch & Belgian Markets at a Glance

Metro areaCountryPopulationMarktplaats significance
AmsterdamNL1.2M (metro 2.5M)Largest concentration of listings — premium electronics, fashion, cars, bikes
RotterdamNL660K (metro 1.5M)Port-city character — heavy on tools, machinery, vehicles, imports
Den Haag (The Hague)NL560KGovernment and expat hub — international diplomats relocating drive churn
UtrechtNL365KCentrally located student city — strong rental kamer-te-huur volume
EindhovenNL240KTech and Philips region — high electronics and component listing activity
GroningenNL235KNorthern student city — bicycle and furniture market
TilburgNL225KBrabant industrial belt — strong cars and tools verticals
AlmereNL220KFast-growing Flevoland city — heavy family-goods volume
BredaNL185KBrabant — vacation property and second-hand sport gear
NijmegenNL180KUniversity city — high bicycle and student-furniture turnover
AntwerpenBE (Flemish)530KMain Flemish hub for 2dehands.be
GentBE (Flemish)265KFlemish student/cultural city
BrusselsBE (bilingual)1.2MCross-listed on both 2dehands.be and 2ememain.be
LiègeBE (French)195KMain Walloon hub for 2ememain.be
CharleroiBE (French)200KWalloon industrial city — heavy vehicles and tools market

Cost & Performance

MetricValue
EngineDirect internal JSON API via got-scraping (no browser)
Runtime (50 listings, no detail enrichment)~10–20 seconds
Runtime (500 listings, no detail enrichment)~60–120 seconds
Runtime (500 listings, scrapeDetails: true)~5–10 minutes (one HTML fetch per listing)
Cost per runPay-per-event — varies with listing count
Pricing modelPay-per-event (transparent per-record pricing)
Data freshnessLive at run time — Marktplaats has no daily snapshot, the API reflects the platform state at the moment of each call
AuthenticationNone required
Proxy requiredApify Proxy enabled by default for resilience; the API accepts unproxied traffic from clean IPs too
ConcurrencySafe to run multiple parallel configurations (different category/postcode slices)
Memory footprint256 MB sufficient; 512 MB recommended for scrapeDetails: true
Hard cap per search~5,000 results (Marktplaats platform limit) — work around with category + postcode + price slicing

  • Public data only — every field returned by this actor is publicly visible to any anonymous visitor of marktplaats.nl, 2dehands.be or 2ememain.be
  • No PII collection beyond what the seller chose to publish — only the display name and seller ID as shown in the listing card
  • No emails or phone numbers — Marktplaats hides direct contact data behind its messaging system; this actor does not attempt to unmask it
  • No login or account data — the actor only reads public listings; it does not authenticate, post, message or otherwise interact with the platform
  • GDPR / EU privacy — sellers post on Marktplaats with the reasonable expectation that their listings are public; aggregating that public data for legitimate business purposes (price benchmarking, market research, fraud detection) is generally permitted, but you remain the data controller and must respect data-subject rights (Articles 15-17 GDPR). Do not store or process personal data beyond what is necessary for your stated purpose, and honour deletion requests
  • Robots & ToS — Marktplaats's robots.txt allows crawling of search pages with reasonable rate limits; the actor's default 500 ms inter-request delay sits well within polite-crawler territory. Always respect the platform's Terms of Service in your specific use case
  • No CAPTCHA bypass that would imply automated account abuse — the actor only fetches anonymous public endpoints

Important: Marktplaats data may not be used for unlawful purposes including identity fraud, stalking, harassment, or unsolicited spam (CAN-SPAM, the Dutch Telecommunicatiewet, EU ePrivacy Directive). The user is responsible for downstream compliance.


Frequently Asked Questions

How fresh is the data?

Live at run time. Marktplaats does not publish a daily snapshot — the internal API reflects the state of the platform at the exact moment of each call. New listings appear in the dataset within seconds of being posted on the site; sold or removed listings vanish on the next run.

How many records will I get?

It depends on your query. Marktplaats hard-caps a single search at ~5,000 results (offset × limit < 5000). A broad search (Auto's in all of NL) hits that cap; a narrow search (bmw 320d in Eindhoven, 20 km radius) might return 50–200. For very large pulls, split your run into segments by category + postcode + price band.

Does this scraper require a login or API key to Marktplaats?

No. The actor calls only public, anonymous endpoints. You only need an Apify account to run it.

Does this work for Belgium too?

Yes. Set platform: "2dehands.be" for Flemish-speaking Belgium or platform: "2ememain.be" for French-speaking Belgium / Wallonia. All three platforms share the backend, so the schema is identical — only the price-type labels and condition values switch language.

Does it support Cloudflare-protected pages?

Marktplaats's internal search API does not sit behind a CAPTCHA, but it does check user-agent and locale headers. The actor uses got-scraping with realistic Chrome 120-126 fingerprints in nl-NL/nl-BE locales, which clears the platform's checks reliably.

Can I filter by price?

Yes — pass minPrice and maxPrice in cents (so €100 = 10000, €1,500 = 150000). For "free items only" set maxPrice: 1.

Can I filter by city?

Yes — use a Dutch or Belgian postcode plus a distanceMeters radius. The actor does not support raw city-name filtering at the API level (Marktplaats expects postcodes), but you can post-filter on the returned location field downstream.

Can I distinguish private sellers from business sellers?

Yes — the actor returns sellerType set to either private (particulier) or business (zakelijk, derived from the EU SOI-498 commercial-trader badge). Filter downstream as needed.

Can I get the seller's email or phone number?

No. Marktplaats hides contact information behind its in-platform messaging system. This actor only returns what is publicly visible on listing cards — sellerName and sellerId. Contacting sellers must be done through Marktplaats itself.

How do I get the full description and category-specific attributes?

Set scrapeDetails: true. The actor will then fetch each listing's detail page, parse the embedded __NEXT_DATA__ JSON and fall back to JSON-LD, returning the full description plus the complete attributes object (vehicle specs, property details, phone specs, etc.). This roughly doubles or triples runtime.

Can I schedule this to run automatically?

Yes — Apify's built-in Scheduler lets you trigger the actor hourly, daily, weekly or on any cron expression. Combine with the webhook or Google Sheets integration for a fully automated pipeline.

Does it work with the Apify free plan?

Yes — full functionality on the free tier. A run of 200 listings without detail enrichment typically uses a few cents of compute.

What output formats are supported?

JSON, CSV, Excel (XLSX), HTML, XML and RSS — directly from the Apify dataset view. The API also supports JSON Lines for streaming consumers.

Why is price sometimes null?

Because the listing uses a priceType other than fixed/asking — i.e. Bieden (bidding), Gratis (free), Ruilen (trade), Nader overeen te komen (negotiable), Op aanvraag (on request) or Zie omschrijving (see description) listings often do not carry a numeric price. The priceType and priceTypeOriginal fields tell you why.

Why is condition sometimes null?

Marktplaats sellers are not required to fill in the condition attribute, and certain categories (services, real estate, jobs) don't expose it. When the attribute is absent the field is null rather than guessed.

Why is my attributes object empty for some listings?

The attribute table varies by category and is partially populated even by the seller. A vintage book listing might only carry taal (language); a car listing typically carries 6–12 attributes. Enable scrapeDetails: true to pull the maximum available set from each listing's detail page.

Does the actor deduplicate?

Yes — a Set of listingIds prevents duplicates across paginated API pages. Across multiple runs you can deduplicate downstream using the listingId field as a primary key.

Can I scrape more than 5,000 results for a single broad query?

Not in a single search. Marktplaats's API hard-caps at ~5,000 results per query. To exceed this, slice your search into segments — for example, by L2 subcategory (l2CategoryId), price band (minPrice + maxPrice), or postcode radius — and merge the resulting datasets.

2dehands.be and 2ememain.be are supported natively via the platform parameter. Vinted, Bol.com and Funda are separate platforms with different APIs — for those, see the dedicated actors in the Related Apify Actors section below.

What if the actor returns zero listings?

Most common causes: the search query yielded no matches (try broader keywords or remove categoryId), the minPrice/maxPrice band is too narrow, the postcode + distance combination is too tight, or Marktplaats's platform-side filters returned no results. Check the actor's run log — the line [API] Total results: N tells you exactly what Marktplaats reported.

How do I report a bug or request a feature?

Open an issue on the Apify Store actor page or contact the developer directly through the Apify Console.


Building a multi-country marketplace dataset? These sibling actors cover other major regional classifieds platforms:


Comparison vs. Alternatives

ApproachSetup timeData freshnessCost (1,000 listings)Cloudflare/locale handlingMulti-platform (NL + BE)
This actor< 1 minuteLive at run time< $1 typicalBuilt-inBuilt-in (NL/BE-NL/BE-FR)
Manual copy-pastehours/dayManualFree + timeNoneEach country manually
Custom Python + requests1–2 weeks devLiveFree + infra + maintenanceDIY (often blocked)DIY per platform
Custom Playwright + proxies2–4 weeks devLiveFree + infra + proxy billManual fingerprintingDIY per platform
Generic SaaS scraperHours to set up per templateLive$100–500+/moOften weak on nl-NL headersEach domain billed separately

Why Pay-Per-Event Pricing?

Most data scrapers either charge a flat monthly subscription (you pay even when idle) or per-Compute-Unit (unpredictable). This actor uses pay-per-event pricing, which means:

  • You only pay when the actor runs and only for the data you receive
  • Charges scale linearly with how many listings you actually consume — no surprise CU bills
  • Transparent, line-item billing inside Apify
  • No monthly minimums, no annual contracts, no seat fees
  • Free to evaluate — sample with maxListings: 20 for pennies before committing to a larger sweep
  • Per-event metering aligns the cost model with the value (one extra listing = one extra event)

Changelog

VersionDateNotes
1.0.02026-05Initial public release — internal JSON API engine, NL + BE-NL + BE-FR multi-platform support, price/condition/seller-type normalization, optional detail-page enrichment with __NEXT_DATA__ parser, Apify Proxy integration, pay-per-event pricing

Keywords

Marktplaats scraper · Marktplaats.nl data · Marktplaats API · Dutch classifieds API · Netherlands marketplace extractor · NL used items data · Marktplaats price scraper · Marktplaats lead generation · Marktplaats car house scraper · Marktplaats listing scraper · marktplaats.nl JSON API · marktplaats car scraper · marktplaats real estate scraper · 2dehands scraper · 2dehands.be data · 2ememain scraper · 2ememain.be Belgium classifieds · Benelux marketplace data · Dutch used car data · Netherlands second hand data · Marktplaats fietsen scraper · Marktplaats huizen kamers data · Marktplaats wonen inrichting scraper · Marktplaats telecom iphone data · Amsterdam classifieds data · Rotterdam classifieds data · Den Haag marketplace data · Utrecht marketplace scraper · Eindhoven classifieds data · Groningen marketplace data · Tilburg marketplace data · Almere classifieds data · Brussels 2dehands data · Antwerp 2dehands scraper · Liège 2ememain scraper · particulier zakelijk seller scraper · Marktplaats verzendservice data · Marktplaats price benchmarking · used car arbitrage Netherlands · NL rental comps scraper · dropshipping research Netherlands · reseller market intel Benelux · Marktplaats brand monitoring · Apify Marktplaats actor · Netherlands C2C marketplace API · Dutch second hand market data · Benelux classifieds extraction · Marktplaats demand trend data


Support

  • Bug reports: Use the Issues tab on the Apify Store actor page
  • Feature requests: Same place — please include your use case and ideally a sample query
  • Direct contact: Through the Apify developer profile

If this actor saves you engineering time, a 5-star rating on the Apify Store helps other Benelux marketplace, e-commerce and analytics teams discover it. Dank je wel! / Merci beaucoup!