# Marktplaats Scraper & API - New Listings to Discord, Telegram (`lukehunter/marktplaats-scraper`) Actor

Marktplaats new listings to Discord, Telegram, Slack or any webhook: a Marktplaats bot for saved searches that sends only ads not seen before. Also scrapes public Marktplaats search listings with price, location, date, category, condition and images. No login.

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

## Pricing

$1.50 / 1,000 listings

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 Scraper - Listings, Prices & New-Ad Alerts

**For resellers, dealers, market analysts and agencies who need Marktplaats listings data in bulk.** Scrape public Marktplaats search results (the Netherlands) and return one flat row per ad - title, asking price, location, date, category, condition and image - or schedule it in new-ad alert mode to catch fresh listings for a saved search as they appear.

Pay per delivered listing: **$0.0015 per listing — 1,000 listings = $1.50.**

Collect public Marktplaats search-result listings without login, cookies, proxies, CAPTCHA solving, or seller-profile crawling. The Actor checks `robots.txt` for every search-page path before fetching it and stops a search honestly when a later page is disallowed, blocked, challenged, or unavailable. Earlier delivered pages remain in the dataset.

### Quick start (1 minute)

1. Open the **Input** tab and enter one or more search terms, e.g. `fiets` (or paste public Marktplaats search-page URLs into `startUrls`).
2. Click **Start**.
3. Export the dataset to CSV, Excel or JSON, or read it through the API.

```json
{
  "searchTerms": [
    "fiets"
  ],
  "maxPagesPerSearch": 1,
  "maxItems": 20
}
```

That prefilled example returns up to 20 listings and costs at most $0.03.

You can also provide public search-page `startUrls`. `maxPagesPerSearch` is 1-10 (default 2); `maxItems` is a hard run-wide cap (default 100, maximum 5000). Turn on `onlyNewSinceLastRun` for scheduled new-ad alerts; `stateStoreName` isolates remembered listing IDs.

### Example output

This row is based on the committed capture fixture; unavailable fields remain `null`.

```json
{
  "id": "a1531721078",
  "url": "https://www.marktplaats.nl/v/fietsen-en-brommers/elektrische-fietsen/a1531721078-herfstdeals-gazelle-orange-c7-bosch-middenmotor-400wh",
  "title": "HERFSTDEALS! | Gazelle Orange C7 | Bosch Middenmotor + 400Wh",
  "price": 1249.99,
  "currency": "EUR",
  "priceType": "FIXED",
  "location": "Soesterberg",
  "date": "Vandaag",
  "category": "Elektrische fietsen",
  "condition": "Zo goed als nieuw",
  "imageUrl": "https://admarkt-cdn.marktplaats.com/api/v1/icas-mp-pro-admarkt/images/13/1362e102-5fdd-4f2f-8d0e-be76d870bb6d?rule=eps_82.JPG",
  "isBusinessSeller": null
}
```

Rows are flat and always include `id`, `url`, `title`, `price`, `currency`, `priceType`, `location`, `date`, `category`, `condition`, `imageUrl`, and `isBusinessSeller`. Fields absent from the captured search page are returned as `null`; the Actor never guesses missing currency, condition, category, price type, or seller type.

### Use cases

1. **Reseller and dealer sourcing:** run saved searches for the second-hand bikes or other stock you buy, then sort by `price`, `location` and `date` to spot under-priced ads worth contacting first.
2. **Market and price analysis:** collect current asking prices for a product keyword, then track median asking price, ad volume and condition mix per category in a spreadsheet or database. These are asking prices, not sold prices.
3. **New-ad monitoring for agencies and teams:** schedule the same search with `onlyNewSinceLastRun: true` and receive only listing IDs not previously delivered for that watch - feed them to Slack, email or a CRM via an Apify webhook.
4. **Availability snapshots:** save bounded search-page snapshots for category, location or product-availability analysis without crawling individual seller profiles.

### Get Marktplaats alerts in Discord, Telegram, Slack, Teams, Google Chat, your phone (ntfy/Pushover) or any app (webhook)

Want a **Marktplaats Discord alert**, a **Marktplaats Telegram bot**, or new listings pushed to Slack, Teams, Google Chat or your phone instead of checking a dataset? Add one or more destinations in the Actor's **Notifications (optional)** section and each run sends the listings it delivered. It is a **monitor that notifies you**: it only reads public Marktplaats search pages and never contacts sellers, buys anything or logs in anywhere, and the messages go only to the places you set up.

| Channel | Fill in | What you get |
|---|---|---|
| Discord | `discordWebhookUrl` | One card per listing, 10 per message |
| Telegram | `telegramBotToken` + `telegramChatId` | Up to 10 listings per message, one line each |
| Slack | `slackWebhookUrl` | Block Kit message, up to 10 listings per message |
| Mattermost, Rocket.Chat | `slackCompatibleWebhookUrl` | Slack-style incoming webhook: a Markdown list (these apps do not render Slack Block Kit) |
| Microsoft Teams | `teamsWebhookUrl` | Adaptive Card from a Teams Workflows webhook, up to 10 listings per card |
| Google Chat | `googleChatWebhookUrl` | Card in a space, up to 10 listings per message |
| ntfy (phone push, no account) | `ntfyTopic` (optional `ntfyServer`, `ntfyToken`) | A push per listing, up to 10, then one "...and N more" |
| Pushover (phone push) | `pushoverUserKey` + `pushoverAppToken` | A push per listing, up to 10, then one "...and N more" |
| Any app: Zapier, Make, n8n, Pipedream, IFTTT, Home Assistant | `webhookUrl` | One JSON POST per run with the delivered rows |

Fill in as many as you like; each channel works on its own and a failing one never stops the others.

#### Setup, channel by channel

- **Discord (1 minute):** Server Settings → Integrations → Webhooks → New Webhook → pick the channel → **Copy Webhook URL**.
- **Telegram (2 minutes):** chat with **@BotFather**, send `/newbot`, paste the token into `telegramBotToken`. Add the bot to the chat or channel (administrator for a channel; for a chat with yourself press **Start** on the bot). `telegramChatId` is a numeric id (`123456789`, or `-1001234567890` for a group or channel) or a public `@channelusername`.
- **Slack:** at api.slack.com/apps create an app (**From scratch**) → **Incoming Webhooks** → switch it on → **Add New Webhook to Workspace** → pick the channel → copy the `https://hooks.slack.com/services/...` URL.
- **Mattermost or Rocket.Chat:** create an **incoming webhook** in the app and paste its public `https://` URL into `slackCompatibleWebhookUrl`. Localhost, private IP addresses and `.local` / `.internal` names are rejected.
- **Microsoft Teams:** in the channel open **... → Workflows** → **Post to a channel when a webhook request is received** → finish the wizard and copy the URL (a host ending in `.logic.azure.com` or `.powerplatform.com`). The old "Office 365 connector" webhooks are retired and not supported.
- **Google Chat:** in the space open **Apps & integrations → Webhooks → Add webhook**, name it and copy the `https://chat.googleapis.com/v1/spaces/...` URL (needs a Google Workspace account that allows webhooks).
- **ntfy (free, no account):** install the ntfy app (or open ntfy.sh), subscribe to a topic with a long random name, and put the same name in `ntfyTopic`. Anyone who knows the topic can read it, so make it unguessable. Own server or a protected topic: set `ntfyServer` (public `https://` address) and `ntfyToken`.
- **Pushover:** copy your user key from pushover.net into `pushoverUserKey`, create an application at pushover.net/apps/build and put its API token in `pushoverAppToken`. Pushover itself is a separate paid app after its trial: check their pricing.
- **Any app (webhook):** paste the catch-hook URL from Zapier, Make, n8n, Pipedream, IFTTT or Home Assistant into `webhookUrl`. It must be a public `https://` address.

#### The recipe: a Marktplaats new-listing alert in five steps

1. Set your search in `searchTerms` (for example `racefiets`) or paste a Marktplaats search URL into `startUrls`.
2. Turn on `onlyNewSinceLastRun`, so only listings not delivered before are sent.
3. Add your destination(s) from the table above.
4. Run it once. The first run is the baseline and sends what is currently listed (up to `maxNotifications`).
5. Create a **Schedule** (for example every few hours). From then on you only hear about listings it has not delivered before for that search.

```json
{
  "searchTerms": [
    "racefiets"
  ],
  "onlyNewSinceLastRun": true,
  "maxItems": 100,
  "ntfyTopic": "your-long-random-topic-name",
  "maxNotifications": 25
}
```

#### The generic webhook (`webhookUrl`)

Each run sends **one POST per 100 delivered rows** (so usually one) with this body, followed by whatever your tool does with it:

```json
{
  "source": "apify",
  "actor": "marktplaats-scraper",
  "runId": "HG7ML7M8z78YcAPEB",
  "count": 2,
  "total": 2,
  "part": 1,
  "parts": 1,
  "items": [ { "...": "the full dataset rows" } ]
}
```

`count` is the number of rows in this POST, `total` the number in the run, and `part` / `parts` number the POSTs when a run delivers more than 100 rows. `maxNotifications` does not cap the webhook. Your endpoint should answer with a 2xx status; redirects are not followed and a failure is reported in the run status, never retried in a loop.

#### What to expect

- **What a message contains:** title, price and currency, location, condition, category, whether the seller is a business or private (never a name), the listed date and a thumbnail, plus the link and the search term it matched.
- **Only delivered listings are sent.** A run that finds nothing new sends nothing, so there is no "no new listings" spam. Rows the run could not deliver (for example because your spending limit was reached) are not sent.
- **`maxNotifications` (default 25, max 100)** caps how many listings go to chat and phone channels per run (the webhook is not capped). The rest are still in the dataset and the status message says so. ntfy and Pushover send at most 10 individual pushes, then one "...and N more" summary.
- **Cost: notifications are free.** You pay only for delivered listings at the usual price, exactly as without alerts. There is no extra charge for any channel.
- **Failures never fail the run.** A deleted webhook or an unreachable service leaves the run successful and the dataset complete, and the status message says what happened, for example `Notified: Discord 12, Slack 12, ntfy 10 (+summary). Teams failed (HTTP 404) - check the webhook URL.` The logs show the channel name and HTTP status only, never a URL or token.
- **Your URLs, tokens and ntfy topic are stored as secret inputs.** Anyone holding a webhook URL can post to that channel, so treat it like a password.
- **The dataset is unchanged.** The output rows are identical whether or not you set a destination; the run's status message just gains a short note such as `Notified: Discord 12, ntfy 10 (+summary).`
- **It is a monitor that notifies you.** It never contacts sellers, buys anything or logs in to Marktplaats, and the messages go only to the destinations you set up.

### Pricing

**Pricing: $0.0015 per delivered listing.** Event: `listing`. Rows skipped by robots rules, blocks, duplicate alert history, or failures are not charged.

Notifications to Discord, Telegram, Slack, Teams, Google Chat, ntfy, Pushover and webhooks are free: you pay only for delivered listings, never for messages sent.

### Fixture coverage

search-p1: 30 unique rows; search-p2: 34 unique rows. The parser uses only the page structures captured in `test/fixtures/`.

### Limitations and responsible use

This Actor reads only public search-result data represented by the captured page fixtures. It does not log in, use proxies, rotate user agents, accept cookies to bypass access controls, solve CAPTCHAs, or crawl seller profiles/phone numbers. Search-page layout changes can require a parser update. Block/challenge responses are reported, not bypassed.

### Use it from your code, Make, Zapier or n8n

Built for automated pipelines: small runs, stable field names, one row per item, and you pay only for rows actually delivered.

**One API call that runs the Actor and returns the data** (replace `$APIFY_TOKEN` with your token from Apify Console → Settings → Integrations):

```bash
curl -s -X POST "https://api.apify.com/v2/acts/lukehunter~marktplaats-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"searchTerms": ["fiets"], "maxPagesPerSearch": 1, "maxItems": 20}'
```

**JavaScript** (`npm i apify-client`):

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('lukehunter~marktplaats-scraper').call({
  "searchTerms": [
    "fiets"
  ],
  "maxPagesPerSearch": 1,
  "maxItems": 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**Python** (`pip install apify-client`):

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('lukehunter~marktplaats-scraper').call(run_input={"searchTerms": ["fiets"], "maxPagesPerSearch": 1, "maxItems": 20})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

**Schedules, webhooks and no-code tools:** save your input as a Task, add a Schedule (e.g. hourly or daily), and attach a webhook or one of the Integrations tab's connectors (Make, Zapier, n8n, Google Sheets, Slack) to push each run's results into your own system.

**Only new items each run:** set `"onlyNewSinceLastRun": true` on a scheduled Task and every run after the first delivers, and charges for, only items it hasn't delivered before for that same input. That makes it a ready-made change feed.

**Reliability:** an automated test runs this Actor's parser against the live site every day, and failures are fixed fast.

**Feedback:** an honest rating on the Store page, good or bad, helps others decide if this Actor fits their needs. Missing a field or found a problem? Open an issue on the Actor page.

### FAQ

#### How much does it cost?

$0.0015 per delivered listing, so 100 listings cost $0.15 and 1,000 cost $1.50. There is no charge for starting a run, and rows skipped because of robots rules, blocks, duplicate alert history or failures are not charged. `maxItems` is a hard cap on the cost of any run.

#### How do I schedule it and get new-ad alerts?

Set `onlyNewSinceLastRun: true`, then click **Schedule** on the run page (or create a schedule under **Schedules** in the Apify Console). The first successful run is a baseline: it delivers and remembers its listings, and you are charged normally for it. Later runs deliver only listing IDs not seen before for that same search, and a run with nothing new succeeds with an empty dataset. Add a webhook for `ACTOR.RUN.SUCCEEDED` under the schedule's **Integrations** to forward new ads to Slack, email, Zapier or Make. Use `stateStoreName` only to isolate or reset a watch's memory.

#### What export formats and integrations are available?

Every run writes a standard Apify dataset, which you can download as JSON, CSV, Excel, XML or HTML, read through the Apify API and client libraries, or send to other tools with webhooks and integrations.

#### What is not collected?

No seller profiles, names, phone numbers or contact details, no login-only data, and no individual ad detail pages (full description and all photos) - only the fields on public search-result cards. Fields missing from a card are returned as `null` and never guessed (for example, `condition` or `category` can be `null` on some ads). Dutch-language listings are returned as published (title, location and condition values are not translated).

#### Do I need proxies or an account?

No. The Actor needs no login, cookies, proxies or CAPTCHA solving. If a page is blocked, challenged or disallowed by `robots.txt`, it reports that honestly and stops that search instead of trying to get around it.

#### Can I get Marktplaats alerts by email?

Not natively. There are two routes. (1) Set `webhookUrl` to a Zapier, Make or n8n catch hook and add an email or Gmail step: the webhook delivers the listings as JSON, so the email can list them. (2) Apify's own run integrations and run notifications can email you when a run finishes, but they only send a link to the run or dataset, not the listings themselves. For instant alerts without building anything, Telegram, ntfy or Pushover reach your phone directly.

#### Can I get Marktplaats alerts in WhatsApp?

Not natively, and we do not use unofficial WhatsApp APIs, which risk getting your number banned. The official route is the WhatsApp Business Platform (Cloud API) with its own business account, message templates and pricing: point `webhookUrl` at a Zapier, Make or n8n flow that calls it. For free phone alerts use Telegram or ntfy instead.

### More from this publisher

- [Vinted Scraper](https://apify.com/lukehunter/vinted-scraper) — Vinted catalog listings and alerts.
- [Vinted Cross-Country Prices](https://apify.com/lukehunter/vinted-cross-country-prices) — compare Vinted item prices across countries.
- [Blocket Scraper](https://apify.com/lukehunter/blocket-scraper) — Blocket classifieds listings and alerts.
- [Kijiji Scraper](https://apify.com/lukehunter/kijiji-scraper) — Kijiji classifieds listings and alerts.

# Actor input Schema

## `searchTerms` (type: `array`):

Search terms for public Marktplaats search pages. Maximum 50 per run.

## `startUrls` (type: `array`):

Public Marktplaats search-result URLs on www.marktplaats.nl. Existing filters are preserved where the captured URL shape supports them.

## `maxPagesPerSearch` (type: `integer`):

1-10 pages per search. A later blocked, failed, or robots-disallowed page stops that search without discarding rows already delivered from earlier pages.

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

Hard cap across the whole run, 1-5000. You are charged $0.0015 per delivered listing.

## `onlyNewSinceLastRun` (type: `boolean`):

When enabled, the first successful run delivers and remembers its listings; later runs skip listing IDs already delivered for the same search. Skipped listings are not charged.

## `stateStoreName` (type: `string`):

Named key-value store used only by new-ad alert mode. Letters, numbers and hyphens only.

## `discordWebhookUrl` (type: `string`):

Post results to a Discord channel. In Discord: Server Settings -> Integrations -> Webhooks -> New Webhook -> choose the channel -> Copy Webhook URL. Looks like https://discord.com/api/webhooks/<id>/<token>. Leave empty to skip Discord.

## `telegramBotToken` (type: `string`):

Post results to Telegram. Create a bot by chatting with @BotFather on Telegram (send /newbot) and paste the token it gives you, e.g. 123456789:AA.... Needs "Telegram chat ID" below. Leave empty to skip Telegram.

## `telegramChatId` (type: `string`):

Where the bot should post: a numeric chat id (e.g. 123456789, or -1001234567890 for a group or channel) or a public @channelusername. The bot must be added to that chat or channel first (as an administrator for a channel), and for a private chat you must press Start on the bot. Needs "Telegram bot token" above.

## `slackWebhookUrl` (type: `string`):

Post results to a Slack channel (Block Kit cards, up to 10 per message). Create an incoming webhook at api.slack.com/apps -> Create New App -> Incoming Webhooks -> Add New Webhook to Workspace. Looks like https://hooks.slack.com/services/T000/B000/XXXX. Leave empty to skip Slack.

## `slackCompatibleWebhookUrl` (type: `string`):

Post results to a Mattermost or Rocket.Chat incoming webhook, which accept Slack-style webhook payloads. Must be a public https:// address (no localhost, private IP or .local/.internal hosts). These apps do not render Slack Block Kit, so they get a plain Markdown list. For real Slack use "Slack webhook URL" above. Leave empty to skip.

## `teamsWebhookUrl` (type: `string`):

Post results to a Teams channel as an Adaptive Card. In Teams: channel -> ... -> Workflows -> "Post to a channel when a webhook request is received" -> copy the URL. The host must end in .logic.azure.com or .powerplatform.com. The retired Office 365 connector webhooks are not supported. Leave empty to skip Teams.

## `googleChatWebhookUrl` (type: `string`):

Post results to a Google Chat space. In the space: Apps & integrations -> Webhooks -> Add webhook -> copy the URL. Looks like https://chat.googleapis.com/v1/spaces/<space>/messages?key=...\&token=.... Leave empty to skip Google Chat.

## `ntfyTopic` (type: `string`):

Get a phone push with no account via ntfy (ntfy.sh). Install the ntfy app, subscribe to a topic name, and enter the same name here. Anyone who knows the topic can read it, so pick a long, unguessable name (letters, numbers, - and \_). At most 10 individual pushes per run, then one "...and N more". Leave empty to skip ntfy.

## `ntfyServer` (type: `string`):

Only used with "ntfy topic". Leave as https://ntfy.sh, or enter the public https:// address of your own ntfy server.

## `ntfyToken` (type: `string`):

Only used with "ntfy topic", for a self-hosted server or a reserved topic that needs a login. An access token from ntfy (starts with tk\_). Leave empty for open topics.

## `pushoverUserKey` (type: `string`):

Get a phone push via Pushover. Your user key is shown on the Pushover dashboard (pushover.net). Needs "Pushover app token" below. At most 10 individual pushes per run, then one "...and N more". Leave empty to skip Pushover.

## `pushoverAppToken` (type: `string`):

The API token of a Pushover application you create at pushover.net/apps/build (name it after this Actor). Needs "Pushover user key" above.

## `webhookUrl` (type: `string`):

POST the delivered rows as JSON to any public https:// URL: {source, actor, runId, count, items}. At most 100 rows per POST; every delivered row is sent regardless of the max-notifications cap. Use it to route results to email, a spreadsheet or any app. Localhost, private IP and .local/.internal addresses are rejected. Leave empty to skip.

## `maxNotifications` (type: `integer`):

Caps how many results are sent to chat and phone channels per run (Discord, Telegram, Slack, Teams, Google Chat, ntfy, Pushover), 1-100, default 25. Extra results are still in the dataset. The generic webhook is not capped. Only used when a destination above is set.

## Actor input object example

```json
{
  "searchTerms": [
    "fiets"
  ],
  "startUrls": [],
  "maxPagesPerSearch": 1,
  "maxItems": 20,
  "onlyNewSinceLastRun": false,
  "stateStoreName": "marktplaats-scraper-seen-items",
  "ntfyServer": "https://ntfy.sh",
  "maxNotifications": 25
}
```

# 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 = {
    "searchTerms": [
        "fiets"
    ],
    "startUrls": [],
    "maxPagesPerSearch": 1,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("lukehunter/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 = {
    "searchTerms": ["fiets"],
    "startUrls": [],
    "maxPagesPerSearch": 1,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("lukehunter/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 '{
  "searchTerms": [
    "fiets"
  ],
  "startUrls": [],
  "maxPagesPerSearch": 1,
  "maxItems": 20
}' |
apify call lukehunter/marktplaats-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lukehunter/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/DZf16SgaExdUYr1go/builds/m6izUCcdzhBTVfZaI/openapi.json
