# Marktplaats.nl New Listings & Price Alert (Netherlands) (`superslowsloth/marktplaats-listings`) Actor

Newest Marktplaats.nl listings for any search terms, one flat row each: title, price in EUR (null when none is stated), price type, city, seller, listing date, category, photos, attributes, URL. Newest-first or by price, with a price band.

- **URL**: https://apify.com/superslowsloth/marktplaats-listings.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 listing scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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.nl New Listings & Price Alert (Netherlands)

Search [Marktplaats](https://www.marktplaats.nl), the Netherlands' biggest
classifieds site, for one or more terms and get one flat row per listing:
title, price in euros, Marktplaats' price type, city, seller, listing date,
category, photos, attributes and the listing URL. Newest first by default, so
a scheduled run is a new-listing feed; a price band and price sorts make it a
bargain watch.

No account, no login, no browser. One request returns 30 listings.

### Input

| Field | Notes |
|---|---|
| `queries` | One or more search terms, one per line. Required. A listing found by two terms is returned once, under the first. |
| `maxItems` | Listings to read per search term (default 100, up to 5,000). Marktplaats stops serving a search after about 5,000 results (167 pages of 30) however many it reports, so a broader search than that needs a narrower term or a price band. |
| `sort` | `newest` (default), `oldest`, `relevance`, `price-asc`, `price-desc`. |
| `minPrice`, `maxPrice` | Asking-price band in whole euros, inclusive, either end optional. |
| `proxyConfiguration` | Apify proxy by default. |

#### About "newest first"

This is Marktplaats' own *date* sort. It orders by when a listing was last
placed, not strictly when it was first posted: a seller who bumps an old
listing, or pays to promote it, sees it jump back to the top. Row ids are
therefore not monotonic, and a handful of old listings can sit among the new
ones (promoted rows carry `promotion` = `DAGTOPPER`). The actor does not
re-sort; filter on `promotion` or `listed_date` if you only want the fresh
ones.

#### About the price sorts and the price band

- A price band (`minPrice` / `maxPrice`) also **removes listings that state no
  price** ("see description", bid-only), because there is nothing to compare.
  Without a band they are returned, with `price_eur` null.
- `price-asc` starts with the free listings and with bid-only listings that
  state no minimum, so the first rows are not "the cheapest things" in the
  sense of a price; add `minPrice` of 1 to skip them.

### Output

| Field | Notes |
|---|---|
| `query` | The search term that first found this listing. |
| `item_id`, `url` | Marktplaats' id and the absolute listing URL. |
| `title`, `description` | As the seller wrote them. `description` is only the **first ~200 characters** the search response carries, cut mid-word; the full text is on the listing page, which this actor does not open. |
| `price_eur`, `price_type` | See below. |
| `city`, `country_code`, `country`, `latitude`, `longitude` | The approximate place Marktplaats shows. |
| `seller_id`, `seller_name`, `seller_verified` | Marktplaats' numeric seller id, the display name the seller chose, and its "verified" flag. |
| `listed_date_text`, `listed_date` | The day as Marktplaats prints it (`Vandaag`, `Gisteren`, `Eergisteren`, `5 okt 26`) and as an ISO date. |
| `category_id`, `category_path` | Numeric category id, and the path as URL slugs (`fietsen-en-brommers/fietsen-dames-damesfietsen`). The search response carries no category name. |
| `image_urls` | Photo URLs (large rendition). Nothing is downloaded. |
| `attributes` | One object of the attributes shown on the listing (condition, delivery, brand, frame height, ...). The keys depend on the category. |
| `is_advert` | True for a business (advertiser) listing, read from the `a` id prefix (private listings are `m`). Every `a` listing seen carried advertiser tracking data. |
| `promotion` | Marktplaats' promotion flag, `DAGTOPPER` or `NONE`. |
| `reserved` | Marktplaats' "reserved" flag. |

#### The price, honestly

Marktplaats sends a price in cents plus a **price type**, and the cents are `0`
for four different things. The actor keeps the type and only turns a real
amount into a number:

| `price_type` | `price_eur` |
|---|---|
| `FIXED` | The asking price. |
| `MIN_BID` | The **minimum bid** (bidding starts there), or **null** when the seller set no minimum. It is not a price anyone has agreed to. |
| `FAST_BID` | null: a bid-only listing with no amount. |
| `SEE_DESCRIPTION` | null: "see description". The price may well be in the text. |
| `FREE` | `0.0`: the only case where zero is the price. |

Any other type Marktplaats adds is passed through in `price_type`, with
`price_eur` set only if it comes with an amount. In 280 listing records from
seven fetched pages, 147 were FIXED, 62 MIN_BID, 41 SEE_DESCRIPTION, 16 FREE and 14 FAST_BID, so
**roughly 4 in 10 rows have no usable price** - filter on `price_eur` before
averaging anything.

#### Honest nulls

A field Marktplaats did not send is `null`, never `0` or `""`:
`city`, `country_code` and the coordinates are null for the (mostly
advertiser) listings with no place - Marktplaats sends coordinates 0,0 for
those, and 0,0 is not reported as a location. `description` is null when the
listing has none; `seller_verified` and `reserved` are null if the flag is
missing. `listed_date` is null if the date text is in a form not recognised
(`listed_date_text` is still there).

`listed_date` has **day precision only**: Marktplaats gives no time of day.
`Vandaag` and its siblings are resolved against the run date in the
Netherlands.

#### Personal data

Listing text and display names are written by private individuals and can hold
names or contact details. They are carried as Marktplaats publishes them,
because they are the listing; nothing is extracted from them. You are
responsible for handling them under the GDPR if you store them.

### Pricing

Pay per event:

- **$0.002** per run (`actor-start`), charged only after your input is
  validated - a run that fails on bad input costs nothing.
- **$0.0007** per listing row written (`listing-scraped`), i.e. $0.70 per
  1,000 listings.

### How it fetches

It calls the same JSON search API Marktplaats' website uses
(`www.marktplaats.nl/lrp/api/search`), 30 rows per request, with
`Accept: application/json`. Measured 2026-10-09: HTTP 200 from Apify datacenter
and residential exits and from a plain connection. Apify datacenter proxy is
the default.

Things worth knowing, all measured:

- **Rate limit.** After roughly 150 requests in a few minutes from one
  address, Marktplaats' CDN answers `403 Request blocked` for about 12
  minutes. The actor treats 403, 429 and 5xx as a refusal, rotates to a fresh
  proxy address and retries; a very large `maxItems` on many terms is what
  can run into it.
- **Empty deep pages.** On the relevance sort the API sometimes answers a
  valid deep offset with an empty page (at least half of the asks from page 100
  on), identical in shape to a search with no results. The actor tells
  the two apart by position - an empty page before the number of results
  Marktplaats itself reported is retried, not taken as the end. The newest-first
  sort did not show it (48 of 48 asks answered at pages 100 to 166).
- **Result cap.** The API serves at most `maxAllowedPageNumber` pages (167 of
  30 for a large search) and answers beyond it with an empty page; the run
  logs when a term was cut off that way.

# Actor input Schema

## `queries` (type: `array`):

What you would type into Marktplaats' search box, one term per line, in Dutch or any language (for example fiets, bakfiets gazelle or iphone 15 pro). Each term is searched and read separately. A listing that two terms both find is returned once, under the first.

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

Read at most this many listings for each search term. Marktplaats serves 30 per request and stops serving a search after about 5,000 results (167 pages), however many it reports finding.

## `sort` (type: `string`):

The order Marktplaats lists the results in. 'Newest first' is Marktplaats' own date order and is the one for new-listing alerts; a listing the seller bumps or pays to promote can reappear near the top, so the order is by when a listing was last placed, not strictly when it was first posted. The price sorts put listings without a price first.

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

Lowest asking price to return, in whole euros, inclusive. Leave empty for no lower bound. Using a price bound also drops listings that state no price (see-description, bid-only).

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

Highest asking price to return, in whole euros, inclusive. Leave empty for no upper bound. Using a price bound also drops listings that state no price (see-description, bid-only).

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

Apify proxy (automatic datacenter exits) is the default and is what this actor was measured on: Marktplaats' search API answered Apify datacenter and residential exits with HTTP 200 on 2026-10-09. A proxy is what lets a refused request be retried from a fresh address.

## Actor input object example

```json
{
  "queries": [
    "fiets"
  ],
  "maxItems": 100,
  "sort": "newest",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (type: `string`):

No description

# 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 = {
    "queries": [
        "fiets"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/marktplaats-listings").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 = {
    "queries": ["fiets"],
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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

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/CEwMLTurimD2VS6HX/builds/xyclPLo8ghnRjkQzG/openapi.json
