# Marktplaats Scraper (`solidcode/marktplaats-scraper`) Actor

\[💰 $1.0 / 1K] Scrape Marktplaats listings at scale.

- **URL**: https://apify.com/solidcode/marktplaats-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Developer tools, Automation, E-commerce
- **Features:** Limited permissions
- **Stats:** 31 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## Marktplaats Scraper

Extract complete listing data from Marktplaats — the Netherlands' largest classifieds marketplace with millions of active listings across cars, electronics, furniture, clothing, real estate, jobs, and more. Search by keyword or paste any Marktplaats URL to collect prices, seller details, images, location, and 30+ structured fields per listing.

### Why This Scraper?

- **Netherlands' #1 classifieds site** — access millions of listings across every major category from cars and property to toys and collectibles
- **Search by keyword or URL** — enter plain search terms like "iPhone 15" or paste any Marktplaats search/category URL you already filtered in your browser
- **Rich listing data** — price and price type, item condition, category and parent category, seller profile, city plus exact latitude/longitude, every listing image, and the collection-or-shipping option
- **Price filtering built in** — set a minimum and/or maximum price in euros to skip irrelevant listings immediately
- **Sort by what matters** — newest first, lowest price, highest price, or most relevant
- **Vehicle details extracted** — brand, model, year, mileage, fuel type, transmission, and colour for car listings
- **No compute charges** — you only pay per result returned

### Use Cases

**Market Research & Price Monitoring**

- Track market prices for a product category over time
- Compare asking prices across sellers for the same model
- Spot pricing anomalies and arbitrage opportunities
- Monitor how quickly certain items sell and at what price

**Lead Generation & Sales**

- Find private sellers of goods you want to buy in bulk
- Identify businesses selling on Marktplaats for B2B outreach
- Build targeted contact lists of sellers in a specific region or category

**Competitive Intelligence**

- Monitor competitor listings and pricing on Marktplaats
- Track inventory levels and stock changes of known sellers
- Analyse listing frequency and seasonal trends

**Inventory & Data Enrichment**

- Populate internal databases with used-goods market data
- Enrich product catalogues with real-world resale valuations
- Build price-comparison tools for second-hand marketplaces

**Research & Journalism**

- Study the Dutch second-hand goods market at scale
- Analyse regional supply and demand patterns
- Investigate pricing practices or category-level trends

### Getting Started

#### Keyword Search

The simplest way to start — just enter what you are looking for:

```json
{
    "searchQueries": ["iPhone 15 Pro", "laptop gaming"],
    "maxResults": 100
}
```

#### Search with Price Range

Narrow results to a specific budget:

```json
{
    "searchQueries": ["racefiets"],
    "minPrice": 200,
    "maxPrice": 800,
    "sortBy": "price_asc",
    "maxResults": 200
}
```

#### Category or Search URL

Keyword search URLs work exactly as they read. Category URLs need the two category numbers on the end, which is what pins the run to the BMW car category instead of everything on the site matching the word "bmw":

```json
{
    "searchUrls": [
        "https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91&l2CategoryId=96",
        "https://www.marktplaats.nl/q/gaming+laptop/"
    ],
    "maxResults": 500
}
```

#### Combined: URLs and Queries Together

Mix both input types — results from all sources are combined:

```json
{
    "searchUrls": ["https://www.marktplaats.nl/l/antiek-en-kunst/?l1CategoryId=1"],
    "searchQueries": ["vintage lamp", "retro klok"],
    "minPrice": 50,
    "sortBy": "date_down",
    "maxResults": 1000
}
```

### Input Reference

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchUrls` | string\[] | `[]` | Marktplaats keyword search URLs (`/q/...`), or category URLs with their category numbers appended (`?l1CategoryId=91&l2CategoryId=96`). A category URL without those numbers is searched by its last word instead, and the run log says so |
| `searchQueries` | string\[] | `[]` | Plain-text search terms (e.g. "iPhone 15 Pro") |
| `maxResults` | integer | `100` | Total listings to collect, shared evenly across every URL and query you enter. Set to `0` for no limit |
| `sortBy` | string | `"date_down"` (Newest First) | Sort order: `date_down` (Newest First), `price_asc` (Price: Low to High), `price_desc` (Price: High to Low), or `relevance` (Most Relevant) |
| `minPrice` | integer | — | Only include listings priced at or above this amount in euros |
| `maxPrice` | integer | — | Only include listings priced at or below this amount in euros |
| `includeSponsored` | boolean | `true` | Marktplaats mixes paid webshop advertisements into its results (typically around 1 in 5). Leave on to receive them as the site shows them, or turn off to collect only genuine listings the search matched |

### Output

Each listing is saved as one row in your dataset. Here is a representative example:

```json
{
    "listingId": "m2134567890",
    "title": "BMW 3 Serie 320i Executive — 2018, lage km",
    "url": "https://www.marktplaats.nl/v/auto-s/bmw/m2134567890-bmw-3-serie-320i-executive",
    "description": "Nette BMW 3 serie, goed onderhouden, nap, 2 sleutels aanwezig...",
    "price": 18950.00,
    "priceType": "FIXED",
    "currency": "EUR",
    "condition": "Gebruikt",
    "categoryId": 96,
    "categoryName": "BMW",
    "parentCategoryName": "Auto's",
    "imageUrls": [
        "https://images.marktplaats.com/api/v1/listing-mp-p/images/ab/ab123456-0000-0000-0000-000000000000?rule=ecg_mp_eps$_84.jpg"
    ],
    "postedAt": "Vandaag",
    "sellerName": "AutoDeal Rotterdam",
    "sellerId": "55123456",
    "sellerUrl": "https://www.marktplaats.nl/s/55123456",
    "sellerType": "BUSINESS",
    "sellerCity": "Rotterdam",
    "sellerRegion": "NL",
    "sellerLat": 51.9225,
    "sellerLon": 4.4792,
    "shippingMethod": "Ophalen",
    "isFreeAd": false,
    "isSponsored": false,
    "isPromoted": true,
    "urgencyFeatureActive": false,
    "vehicleBrand": "BMW",
    "vehicleModel": "3 Serie",
    "vehicleYear": 2018,
    "vehicleMileage": 87000,
    "vehicleFuelType": "Benzine",
    "vehicleTransmission": "Automaat",
    "vehicleColor": "Zwart",
    "attributes": {
        "model": "3 Serie",
        "constructionYear": "2018",
        "mileage": "87000",
        "fuel": "Benzine",
        "transmission": "Automaat",
        "color": "Zwart",
        "condition": "Gebruikt",
        "body": "Sedan",
        "energyLabel": "B"
    },
    "searchQuery": "https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91&l2CategoryId=96"
}
```

#### Field Reference

##### Core Listing Fields

| Field | Type | Description |
|-------|------|-------------|
| `listingId` | string | Unique Marktplaats listing identifier |
| `title` | string | Listing title as shown on Marktplaats |
| `url` | string | Direct URL to the listing page |
| `description` | string | Listing description text |
| `price` | number | Asking price in euros. Null when Marktplaats publishes no asking price, which is every auction-style ad (`FAST_BID`) plus `FREE` and `SEE_DESCRIPTION` listings |
| `priceType` | string | How the price is offered: `FIXED` (asking price), `MIN_BID` (open to offers), `FAST_BID` (auction), `SEE_DESCRIPTION`, `FREE` |
| `currency` | string | Always `"EUR"` |
| `condition` | string | Item condition in Dutch: `Nieuw`, `Nieuw zonder verpakking`, `Zo goed als nieuw`, `Gebruikt`, `Gedragen`, `Refurbished`, `Niet werkend`. Blank when the seller did not state one |
| `categoryId` | integer | Marktplaats internal category ID |
| `categoryName` | string | Category name as Marktplaats labels it (e.g. `BMW`, `Mobiele telefoons \| Apple iPhone`) |
| `parentCategoryName` | string | Top-level category name (e.g. `Auto's`, `Telecommunicatie`) |
| `imageUrls` | string\[] | All listing image URLs |
| `postedAt` | string | When the listing was posted (Dutch localised: "Vandaag", "Gisteren", or a date) |
| `searchQuery` | string | The search query or URL that produced this result |

##### Seller Fields

| Field | Type | Description |
|-------|------|-------------|
| `sellerName` | string | Seller display name |
| `sellerId` | string | Seller account identifier |
| `sellerUrl` | string | Link to the seller's Marktplaats profile |
| `sellerType` | string | `BUSINESS` for dealers and shops, `PRIVATE` for individuals. Use it to split trade inventory from private ads |
| `sellerCity` | string | Seller's city |
| `sellerRegion` | string | Two-letter country code of the listing: `NL`, `BE`, `DE`, `FR`. Blank when Marktplaats does not publish it |
| `sellerLat` | number | Seller location latitude |
| `sellerLon` | number | Seller location longitude |

##### Delivery, Flags & Vehicle Fields

| Field | Type | Description |
|-------|------|-------------|
| `shippingMethod` | string | How the item changes hands, in Dutch: `Ophalen` (collection only), `Verzenden` (shipping only), `Ophalen of Verzenden` (either) |
| `isFreeAd` | boolean | `true` if the item is offered for free |
| `isSponsored` | boolean | `true` if the row is a paid advertisement Marktplaats placed in the results rather than a listing the search matched. Always present, so you can filter ads out in one step |
| `isPromoted` | boolean | `true` if a genuine matching listing was pushed up the page because its seller paid to feature it |
| `urgencyFeatureActive` | boolean | `true` if the seller has paid for urgency highlighting |
| `vehicleBrand` | string | Vehicle brand for car listings (e.g. `BMW`, `Volkswagen`) |
| `vehicleModel` | string | Vehicle model (cars only) |
| `vehicleYear` | integer | Year of manufacture (cars only) |
| `vehicleMileage` | integer | Odometer reading in kilometres (cars only) |
| `vehicleFuelType` | string | Fuel type in Dutch (e.g. "Benzine", "Diesel") |
| `vehicleTransmission` | string | Gearbox type (e.g. "Automaat", "Handgeschakeld") |
| `vehicleColor` | string | Exterior colour in Dutch. Sparse by nature: only about 3 in 10 car sellers fill it in, so plan on this column being empty most of the time |
| `attributes` | object | Every raw listing attribute as key-value pairs. Category-specific extras such as `body`, `energyLabel`, `storage`, `engineHorsepower`, `driveTrain` and `numberOfSeats` land here |

### Tips for Best Results

#### Getting More Results

- Marktplaats limits access to approximately 5,000 listings per search (167 pages × 30). For broad categories, split into smaller queries with price ranges or more specific keywords to access more of the catalogue.
- Combine `searchUrls` with subcategory URLs for maximum coverage within a category.
- `maxResults` is split evenly across everything you enter, so five queries with a limit of 500 give each query roughly 100 listings, and any query that runs out early hands its leftover share to the others. Listings arrive in batches of 30, so allow at least 30 per search (three queries → set 90 or more) and expect the final count to round up to the nearest full batch.

#### Using URLs from Your Browser

- Keyword search URLs (`marktplaats.nl/q/...`) copy across from your address bar and work exactly as they read.
- Category URLs are the one exception worth knowing: Marktplaats keeps its category numbers out of the address bar, so `marktplaats.nl/l/auto-s/bmw/` on its own is searched as the words "bmw" across the whole site. Add the two category numbers to the end (`?l1CategoryId=91&l2CategoryId=96`) and you get the BMW car category itself. The run log tells you which of the two happened, every time.

#### Dutch Language

- Marktplaats is a Dutch marketplace — search terms in Dutch return more results. For example, use "fiets" instead of "bike", or "bank" instead of "sofa".
- Category slugs in URLs are also in Dutch (e.g. `/l/computers-en-software/laptops/`).

#### Price Filtering

- Use `minPrice` and `maxPrice` to avoid wading through free items or high-end listings you are not interested in. Prices are in whole euros.
- Auction-style ads (`priceType: FAST_BID`) carry no asking price on Marktplaats, so any price range you set filters them out. Leave both fields empty if you want auctions in your export.

#### Sorting Strategy

- Use **Newest First** when monitoring new listings as they appear.
- Use **Price: Low to High** to find the best deals at the top of your results.
- Use **Most Relevant** for exploratory keyword searches where you are not sure what to expect.

### Pricing

**From $1.00 per 1,000 results** — no compute charges, you only pay per result returned. Discounts follow your Apify plan tier, and Gold stays at today's $1.00 per 1,000. The tiered prices below take effect on October 25, 2026; until then every tier pays $1.00 per 1,000.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.12 | $0.113 | $0.1065 | $0.10 |
| 1,000 | $1.20 | $1.13 | $1.065 | $1.00 |
| 10,000 | $12.00 | $11.30 | $10.65 | $10.00 |
| 100,000 | $120.00 | $113.00 | $106.50 | $100.00 |

### Integrations

Export your data in JSON, CSV, Excel, XML, or RSS format. Connect to 1,500+ tools via:

- **Zapier** / **Make** / **n8n** — Trigger workflows automatically when new listings appear
- **Google Sheets** — Export results directly to a spreadsheet for analysis
- **Slack** / **Email** — Get notified when new matching listings are found
- **Webhooks** — Push data to your own systems in real time
- **Apify API** — Full programmatic access, schedule runs, and automate data pipelines

### Legal & Ethical Use

This actor is designed for legitimate business intelligence, market research, price monitoring, and lead generation. Users are responsible for complying with applicable laws and Marktplaats's Terms of Service. Do not use collected data for spam, harassment, or any unlawful purpose.

# Actor input Schema

## `searchUrls` (type: `array`):

Paste one or more Marktplaats URLs. Two shapes are read exactly: a keyword search URL such as https://www.marktplaats.nl/q/iphone+15/, and a category URL that carries its category numbers, such as https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91\&l2CategoryId=96. A plain category URL with no category numbers (https://www.marktplaats.nl/l/auto-s/bmw/) cannot be matched to a category, so it is searched as the keyword 'bmw' instead and the run log says so.

## `searchQueries` (type: `array`):

Plain-text search terms — for example 'iPhone 15 Pro' or 'LEGO City set'. The scraper will search Marktplaats and return matching listings.

## `maxResults` (type: `integer`):

Maximum total number of listings to collect. The limit is shared evenly across every URL and query you enter, so each one gets its own share and none is left empty — whatever a search does not use rolls over to the ones still to run. Listings come back in pages of 30, so every search returns at least 30 and the final total can land a little above your limit. Set to 0 for no limit.

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

Choose the order in which listings are collected from Marktplaats.

## `minPrice` (type: `integer`):

Only include listings priced at or above this amount in euros. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Only include listings priced at or below this amount in euros. Leave empty for no maximum.

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

Marktplaats mixes paid advertisements from webshops into its search results (often around 1 in 5 results). Leave this on to receive them just as they appear on the site. Turn it off to collect only genuine listings from the search, and to avoid paying for advertising you did not search for.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91&l2CategoryId=96"
  ],
  "searchQueries": [],
  "maxResults": 100,
  "sortBy": "date_down",
  "includeSponsored": true
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped listings with key fields.

## `details` (type: `string`):

All fields including seller info, delivery option, and vehicle attributes.

# 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 = {
    "searchUrls": [
        "https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91&l2CategoryId=96"
    ],
    "searchQueries": [],
    "maxResults": 100,
    "sortBy": "date_down",
    "includeSponsored": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/marktplaats-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchUrls": ["https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91&l2CategoryId=96"],
    "searchQueries": [],
    "maxResults": 100,
    "sortBy": "date_down",
    "includeSponsored": True,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/marktplaats-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchUrls": [
    "https://www.marktplaats.nl/l/auto-s/bmw/?l1CategoryId=91&l2CategoryId=96"
  ],
  "searchQueries": [],
  "maxResults": 100,
  "sortBy": "date_down",
  "includeSponsored": true
}' |
apify call solidcode/marktplaats-scraper --silent --output-dataset

```

## MCP server setup

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

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/fce94Jv78dPY44URw/builds/Il2th5a7VqX216PA2/openapi.json
