# Kleinanzeigen Scraper — German Classifieds (`blackfalcondata/kleinanzeigen-scraper`) Actor

Scrape classified listings from Kleinanzeigen.de — prices, locations, images, descriptions, and seller contacts including phone and email. Filter by keyword, category and location; incremental runs return only new listings.

- **URL**: https://apify.com/blackfalcondata/kleinanzeigen-scraper.md
- **Developed by:** [Black Falcon Data](https://apify.com/blackfalcondata) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.35 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

### What does Kleinanzeigen Scraper do?

Kleinanzeigen Scraper extracts structured classified listings from [kleinanzeigen.de](https://www.kleinanzeigen.de) — Germany's largest classifieds marketplace — capturing titles, prices, locations, images, full descriptions, and seller contacts (phone and email) across electronics, furniture, fashion, vehicles, real estate, jobs, and more.

Search by keyword (or many keywords at once), category, location and radius, price, condition, listing type, or seller type — or paste search-result URLs straight from your browser. Turn on detail enrichment to add the full description (text, HTML, or Markdown), the image gallery, the category path, per-listing attributes, and the seller box; optionally fetch each seller's public profile or resolve a contact phone number.

### How to use this actor

- 👉 **Register for a free Apify account** — no credit card required.
- 🎉 Just click **[Sign up free on Apify →](https://console.apify.com/sign-up?fpr=1h3gvi&fp_sid=ctarich)** and complete a quick signup.
- 💰 A free Apify account includes $5 in monthly credits — enough to test this actor.
- ⏳ Scrape during the free trial, with no commitment or upfront payment required.

### Key features

<!-- KEY_FEATURES:START -->
- **🔗 Paste-mode** — paste any Kleinanzeigen.de URL straight from your browser — single-listing pages, search results, or category pages. Every filter you set in your browser (location, price range, condition, and per-category attributes such as fuel type, mileage, or colour) is preserved exactly as-is.
- **🎯 Batch searches** — run multiple search variants in one job — shared dedup, single dataset for compare/diff downstream.
- **🔔 Notifications** — telegram / Slack / Discord / WhatsApp / webhook alerts on each run. Combine with incremental to ping only when prices or inventory actually move.
- **📋 Detail enrichment** — two-stage scraping — list first, then enrich each listing with the full detail-page payload. One input toggle controls the depth.
- **📧 Email + phone extraction** — best-effort regex extraction of contact emails and phone numbers from descriptions — emitted as `extractedEmails[]` and `extractedPhones[]` on every record.
- **📦 Compact mode** — light payload with core fields only — comparable rows across listings without HTML or metadata overhead. Perfect for pricing dashboards.
- **✂️ Description truncation** — cap description length with `descriptionMaxLength` to control LLM prompt cost and dataset size — set 0 for full descriptions, or any char-limit to trim.
- **🔌 MCP connectors** — export your results into Notion via Apify's MCP connectors — a clean run-summary page, no glue code. Opt-in via the App connector field; deterministic field-mapping, no AI. Built on Apify's connector framework, so more destinations open up as their catalog grows.
- **♻️ Incremental mode** — daily runs emit only listings that are new or whose price/condition changed since last run. Perfect for inventory-diff dashboards and competitive pricing alerts. Saves 80–95% on recurring monitoring.
<!-- KEY_FEATURES:END -->

### What data can you extract from kleinanzeigen.de?

Each result is a structured listing record. Core fields: `listingId`, `title`, `description`, `descriptionHtml`, `descriptionMarkdown`, `price`, `priceText`, `priceType`, `currency`, `category`, `categoryPath`, `location`, `zipCode`, `latitude`, `longitude`, `thumbnail`, `images`, `imageCount`, `seller` (a nested object), `sellerName`, `postedText`, `postedAt`, `url`, `attributes` (the raw German label→value bag from the listing's detail table), `scrapedAt`, `source`, `changeType`.

Generic attribute promotion surfaces typed columns from any category's detail table where present — e.g. `brand`, `model`, `color`, `size`, `material`, `gender`, `subType`, plus dimension fields (`depth`, `height`, `width`, `length`). Vehicle and property listings expose their detail attributes through the same `attributes` map.

Each listing carries a nested `seller` object from the detail page — seller name, account type (private or business), shop/pro flags, member-since date, and the public profile URL. With **Include Seller Profile** on, it is enriched with extra public-profile fields (total active listings and ratings, where the seller's page shows them). With **Include Phone Number** on, the listing's contact phone is resolved where the seller published one. `postedText` is the posted-time label as shown on the site; `postedAt` is its normalized ISO-8601 form when that label resolves to an absolute date.

Default behaviour: null and empty values are dropped from each row so output stays compact for LLM pipelines (`omitNulls: true`). Set it to `false` if you need a stable schema where every row carries every documented field.

Pick a single description representation with **Description format** (`all` keeps every variant; `text` / `html` / `markdown` keep just one) to slim output.


### Input

The main inputs are a search keyword, an optional location filter, and a result limit. Additional filters and options are available in the input schema.

Key parameters:

- **`query`** — Single keyword or phrase (e.g. 'iPhone', 'sofa', 'Fahrrad'). For multiple searches in one run, use the `queries` array below.
- **`startUrls`** — Paste one or more Kleinanzeigen.de search-result URLs. Build the filters you want in your browser, copy the URL, and paste here. Each URL is paginated; results are merged and deduplicated. Takes precedence over `query`, `queries`, and all filter inputs. The legacy `searchUrls` field name is still accepted for backward compatibility. (default: `[]`)
- **`location`** — City name or postal code to search within (e.g. 'Berlin', 'München', '10115'). Leave blank to search all of Germany.
- **`priceMax`** — Maximum price filter. 0 = no limit. (default: `0`)
- **`includeDetails`** — Fetch the full listing page for each result to add description, images, category path, attributes, and more. Produces richer output but takes longer. (default: `true`)
- **`includeSellerProfile`** — Fetch extra detail for each unique seller to add reputation badges and the seller's active-ads count. Adds one request per unique seller (a small per-seller charge applies) and increases run time. (default: `false`)
- **`incremental`** — Only return new or changed listings since the last run. State is saved between runs and scoped per query and category. (default: `false`)
- **`compact`** — Return only the most essential fields (for AI-agent and MCP workflows). (default: `false`)
- ...and 38 more parameters

### Input examples

**Keyword search in a city** — Single keyword scoped to a city, with full detail enrichment.

→ Listing records with description, images, category path, attributes, and the seller box.

```json
{
  "query": "iPhone",
  "location": "Berlin",
  "maxResults": 50,
  "includeDetails": true
}
````

**Filter cars by brand, fuel, and mileage** — Narrow a category with per-listing attribute filters. Keys and values come from the site's own filter options — the easiest way to discover them is to set the filters in your browser and paste the search-result URL into Start URLs.

→ Diesel BMW listings up to 100,000 km and €25,000, with detail enrichment.

```json
{
  "category": "autos",
  "attributeFilters": {
    "autos.marke": "bmw",
    "autos.fuel": "diesel",
    "autos.km": "0,100000"
  },
  "priceMax": 25000,
  "maxResults": 100,
  "includeDetails": true
}
```

**Multiple keywords in one run** — Several searches in one invocation; results merge and dedupe by listing ID.

→ Merged, cross-query-deduped records across all keywords.

```json
{
  "queries": [
    "laptop",
    "iPad",
    "AirPods"
  ],
  "category": "elektronik",
  "maxResults": 300,
  "maxResultsPerQuery": 100
}
```

**Paste Kleinanzeigen URLs (paste-mode)** — Build the filters you want in your browser on kleinanzeigen.de, copy each search-result URL, and paste them here.

→ All listings from the pasted search-result pages, merged into one dataset.

```json
{
  "startUrls": [
    "https://www.kleinanzeigen.de/s-fahrrad/k0c217l3331",
    "https://www.kleinanzeigen.de/s-preis:0:300/playstation/k0c161"
  ],
  "maxResults": 200,
  "maxResultsPerQuery": 100
}
```

**New-listings monitor (incremental)** — Track new listings on a schedule; only new or changed listings are emitted.

→ Only new or changed listings since the previous run with this stateKey.

```json
{
  "query": "sofa",
  "sellerType": "gewerblich",
  "incremental": true,
  "stateKey": "kleinanzeigen-sofa-business",
  "maxResults": 500
}
```

### Output

Each run produces a dataset of structured listing records. Results can be downloaded as JSON, CSV, or Excel from the Dataset tab in Apify Console.

### Example listing record

```json
{
  "listingId": "3446804582",
  "title": "Guess iPhone 17 Hülle Glitzer Pink Neu OVP",
  "url": "https://www.kleinanzeigen.de/s-anzeige/guess-iphone-17-huelle-glitzer-pink-neu-ovp/3446804582-173-3421",
  "price": 17,
  "priceText": "17 €",
  "currency": "EUR",
  "thumbnail": "https://img.kleinanzeigen.de/api/v1/prod-ads/images/8f/8fc21359-d116-4ba3-9777-08a8191414db?rule=$_2.AUTO",
  "location": "Steglitz",
  "postedText": "Heute, 18:53",
  "latitude": 52.44995,
  "longitude": 13.32851,
  "attributes": {
    "Art": "Weitere Handys & Telefone",
    "Versand": "ab 0,00",
    "Farbe": "Pink",
    "Gerät & Zubehör": "Zubehör",
    "Zustand": "Neu"
  },
  "seller": {
    "name": "Yvonne",
    "type": "privat",
    "isShop": false,
    "isPro": false,
    "activeSince": "2025-09-16T23:19:03.000+0200",
    "userId": "154762085",
    "badges": [
      "TOP Zufriedenheit",
      "Sehr freundlich",
      "Sehr zuverlässig"
    ],
    "adsOnline": 32,
    "profileUrl": "https://www.kleinanzeigen.de/s-bestandsliste.html?userId=154762085"
  },
  "contentHash": "d3e512f2d454ba0ca70c18af4b20091a5e1f2e74e1bece7aaa9cc560460d1637",
  "scrapedAt": "2026-06-29T16:55:50.275Z",
  "description": "Ich biete hier eine brandneue Guess Handyhülle für das iPhone 17 an. Die Hülle kommt in einem wunderschönen Pink mit Glitzer-Finish, das deinem Handy einen glamourösen Look verleiht. Sie ist noch orig...",
  "descriptionHtml": "Ich biete hier eine brandneue Guess Handyhülle für das iPhone 17 an. Die Hülle kommt in einem wunderschönen Pink mit Glitzer-Finish, das deinem Handy einen glamourösen Look verleiht. Sie ist noch orig...",
  "descriptionMarkdown": "Ich biete hier eine brandneue Guess Handyhülle für das iPhone 17 an. Die Hülle kommt in einem wunderschönen Pink mit Glitzer-Finish, das deinem Handy einen glamourösen Look verleiht. Sie ist noch orig...",
  "imageUrls": [
    "https://img.kleinanzeigen.de/api/v1/prod-ads/images/8f/8fc21359-d116-4ba3-9777-08a8191414db?rule=$_57.JPG",
    "https://img.kleinanzeigen.de/api/v1/prod-ads/images/7d/7d3aa3a7-2dd1-4b69-9de8-e8a3629f018c?rule=$_57.JPG",
    "https://img.kleinanzeigen.de/api/v1/prod-ads/images/2e/2eb531f9-d848-4605-906b-8c3186d928a0?rule=$_57.JPG",
    "https://img.kleinanzeigen.de/api/v1/prod-ads/images/20/20f0a5d8-7dfb-4616-ad61-cadb20165234?rule=$_57.JPG",
    "https://img.kleinanzeigen.de/api/v1/prod-ads/images/0a/0a86728d-63d1-4e36-9c86-5f8628a0a889?rule=$_57.JPG",
    "... 1 more items"
  ],
  "imageUrl": "https://img.kleinanzeigen.de/api/v1/prod-ads/images/8f/8fc21359-d116-4ba3-9777-08a8191414db?rule=$_57.JPG",
  "imageCount": 6,
  "categoryPath": "Handy & Telefon",
  "category": "Handy & Telefon",
  "zipCode": "12167",
  "priceType": "Festpreis",
  "shippingAvailable": true,
  "sellerName": "Yvonne",
  "sellerId": 154762085,
  "portalUrl": "https://www.kleinanzeigen.de/s-anzeige/guess-iphone-17-huelle-glitzer-pink-neu-ovp/3446804582-173-3421"
}
```

### Incremental fields

When incremental mode is on, each record also carries:

- `changeType` — one of `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED`, `EXPIRED`. Default output covers `NEW` / `UPDATED` / `REAPPEARED`; set `emitUnchanged: true` or `emitExpired: true` to opt into the others.
- `isRepost`, `repostOfId`, `repostDetectedAt` — populated when a new listing matches the tracked content of a previously expired one. Set `skipReposts: true` to drop detected reposts from the output.

### How to scrape kleinanzeigen.de

1. Go to [Kleinanzeigen Scraper](https://apify.com/blackfalcondata/kleinanzeigen-scraper?fpr=1h3gvi) in Apify Console.
2. Enter a search keyword and optional location filter.
3. Set `maxResults` to control how many results you need.
4. Enable `includeDetails` if you need full descriptions.
5. Click **Start** and wait for the run to finish.
6. Export the dataset as JSON, CSV, or Excel.

### Use cases

- Marketplace deal hunting — combine category, location, and price filters with incremental mode to catch new electronics, furniture, or sport-gear listings under your budget the moment they go live.
- Reseller and dropship sourcing — monitor a keyword or category for fresh inventory and pull structured price, condition, and image data for repricing.
- Price and supply monitoring — track how asking prices and listing volume for a product or category shift over time across Germany.
- Regional supply analysis — use structured `zipCode` and `latitude`/`longitude` to map where supply concentrates by category.
- Lead generation — filter `sellerType: "gewerblich"` to surface business sellers, optionally enriching with seller profile and contact phone where published.
- Feed AI agents, MCP tools, and automated pipelines using compact mode with description truncation to keep payloads light for LLM context windows.

### How much does it cost to scrape kleinanzeigen.de?

Kleinanzeigen Scraper uses [pay-per-event](https://docs.apify.com/platform/actors/paid-actors/pay-per-event) pricing. You pay a small fee when the run starts and then for each result that is actually produced.

- **Run start:** $0.005 per run
- **Per listing (primary event):** $0.00135

You are billed only for the events your run actually triggers. Prices below are the Free plan tier.

| Event | Price (Free tier) | Charged when |
|---|---|---|
| Actor Start | $0.005 (one-time) | Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). |
| Result (primary) | $0.00135 | Single result in the default dataset. |
| Seller Enrichment | $0.002 | Charged once per unique seller when 'Include seller profile' is enabled, for the extra fetch that adds seller reputation badges and the seller's active-ads count. |

Example costs (primary event only — other events above add cost when they fire):

- 10 results: **$0.019**
- 25 results: **$0.039**
- 100 results: **$0.14**
- 200 results: **$0.28**
- 500 results: **$0.68**

#### Example: recurring monitoring savings

These examples compare full re-scrapes with incremental runs at different churn rates. Churn is the share of listings that are new or whose tracked content changed since the previous run. Actual churn depends on your query breadth, source activity, and polling frequency — the scenarios below are examples, not predictions.

Example setup: 100 results per run, daily polling (30 runs/month). Event-pricing examples scale linearly with result count.

Numbers below are for the primary **Result** event. Other events (**Seller Enrichment**) are billed separately when they fire.

| Churn rate | Full re-scrape run cost | Incremental run cost | Savings vs full re-scrape | Monthly cost after baseline |
|---|---:|---:|---:|---:|
| 5% — stable niche query | $0.14 | $0.01 | $0.13 (92%) | $0.35 |
| 15% — moderate broad query | $0.14 | $0.03 | $0.11 (82%) | $0.76 |
| 30% — high-volume aggregator | $0.14 | $0.05 | $0.09 (68%) | $1.36 |

Full re-scrape monthly cost at daily polling: $4.20. First month with incremental costs $0.48 / $0.87 / $1.46 for the 5% / 15% / 30% scenarios because the first run builds baseline state at full cost before incremental savings apply.

Platform usage (compute and proxies) is billed separately by Apify based on actual consumption. Incremental runs consume less on result processing, though fixed per-run overhead stays the same.

### FAQ

#### How many results can I get from kleinanzeigen.de?

The number of results depends on the search query and available listings on kleinanzeigen.de. Use the `maxResults` parameter to control how many results are returned per run.

#### Does Kleinanzeigen Scraper support recurring monitoring?

Yes. Enable incremental mode to only receive new or changed listings on subsequent runs. This is ideal for scheduled monitoring where you want to track changes over time without re-processing the full dataset.

#### Can I integrate Kleinanzeigen Scraper with other apps?

Yes. Kleinanzeigen Scraper works with Apify's [integrations](https://apify.com/integrations?fpr=1h3gvi) to connect with tools like Zapier, Make, Google Sheets, Slack, and more. You can also use webhooks to trigger actions when a run completes.

#### Can I use Kleinanzeigen Scraper with the Apify API?

Yes. You can start runs, manage inputs, and retrieve results programmatically through the [Apify API](https://docs.apify.com/api/v2). Client libraries are available for JavaScript, Python, and other languages.

#### Can I use Kleinanzeigen Scraper through an MCP Server?

Yes. Apify provides an [MCP Server](https://apify.com/apify/actors-mcp-server?fpr=1h3gvi) that lets AI assistants and agents call this actor directly. Use compact mode, `descriptionMaxLength`, a single `descriptionFormat`, and `excludeEmptyFields` to keep payloads manageable for LLM context windows.

#### Is it legal to scrape kleinanzeigen.de?

This actor extracts publicly available data from kleinanzeigen.de. Web scraping of public information is generally considered legal, but you should always review the target site's terms of service and ensure your use case complies with applicable laws and regulations, including GDPR where relevant.

#### Your feedback

If you have questions, need a feature, or found a bug, please [open an issue](https://apify.com/blackfalcondata/kleinanzeigen-scraper/issues?fpr=1h3gvi) on the actor's page in Apify Console. Your feedback helps us improve.

### You might also like

- [🚗 mobile.de \[$1/1K💰\] Fast Scraper · Finance · Dealer GPS](https://apify.com/blackfalcondata/mobile-de-scraper?fpr=1h3gvi) — Scrape mobile.de — Germany's largest car marketplace (1.4M+ listings) at $1 / 1,000 results. Full.
- [AutoScout24 Scraper — European Car Listings with Dealer Data](https://apify.com/blackfalcondata/autoscout24-scraper?fpr=1h3gvi) — Scrape autoscout24.com — Europe's largest used-car marketplace with 770K+ listings across 8.
- [Autotrader AU \[$0.9💰\] Car & Caravan Scraper 🇦🇺](https://apify.com/blackfalcondata/autotrader-au-scraper?fpr=1h3gvi) — Scrape autotrader.com.au car & caravan listings — advertised + previous price with a computed.
- [Autotrader Canada Scraper — Car & Truck Listings + Dealers](https://apify.com/blackfalcondata/autotrader-ca-scraper?fpr=1h3gvi) — Scrape autotrader.ca — Canada's largest car marketplace. Get structured make/model/year/price.
- [Autotrader UK \[$0.75💰/1K\] - Car Scraper, Full Detail](https://apify.com/blackfalcondata/autotrader-uk-scraper?fpr=1h3gvi) — Scrape UK car listings from Auto Trader by make, model, price, year, mileage, fuel, and body type..
- [Bilbasen Scraper - Denmark’s Car Marketplace](https://apify.com/blackfalcondata/bilbasen-scraper?fpr=1h3gvi) — Scrape bilbasen.dk, Denmark’s largest car marketplace, with full vehicle specs, seller contacts,.
- [Bilka Scraper - Danish Grocery Products & Prices](https://apify.com/blackfalcondata/bilka-scraper?fpr=1h3gvi) — Scrape Bilka (Salling Group), Denmark's largest hypermarket chain. Get the full product catalog.
- [Coches.net Scraper — Used Cars, Vans & Motorbikes in Spain](https://apify.com/blackfalcondata/coches-scraper?fpr=1h3gvi) — Coches.net Scraper — scrape car, van, motorhome, classic & motorcycle listings from Spain's largest.

### Getting started with Apify

New to Apify? [Create a free account with $5 credit](https://console.apify.com/sign-up?fpr=1h3gvi\&fp_sid=ctarich) — no credit card required.

1. Sign up — $5 platform credit included
2. Open this actor and configure your input
3. Click **Start** — export results as JSON, CSV, or Excel

Need more later? [See Apify pricing](https://apify.com/pricing?fpr=1h3gvi).

# Actor input Schema

## `query` (type: `string`):

Single keyword or phrase (e.g. 'iPhone', 'sofa', 'Fahrrad'). For multiple searches in one run, use the `queries` array below.

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

Run multiple keyword searches in one go — e.g. `["laptop", "iPad", "AirPods"]`. Results from all searches are merged and deduplicated by listing ID. Filters below (category, location, price, etc.) apply to all queries. Takes precedence over the single `query` field.

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

Paste one or more Kleinanzeigen.de search-result URLs. Build the filters you want in your browser, copy the URL, and paste here. Each URL is paginated; results are merged and deduplicated. Takes precedence over `query`, `queries`, and all filter inputs. The legacy `searchUrls` field name is still accepted for backward compatibility.

## `watchSellerIds` (type: `array`):

Track specific sellers by their numeric seller ID — paste the IDs (or full seller-inventory URLs) and the run returns each seller's current listings. Takes precedence over search term, queries, and Start URLs. Combine with ♻️ Incremental Mode to get only a seller's new or changed listings each run.

## `maxResultsPerQuery` (type: `integer`):

Cap per individual search when running multiple queries via `queries`. 0 = use the global Max Results for every query. Useful for balanced sampling across diverse searches.

## `category` (type: `string`):

Filter by Kleinanzeigen category.

## `location` (type: `string`):

City name or postal code to search within (e.g. 'Berlin', 'München', '10115'). Leave blank to search all of Germany.

## `radius` (type: `integer`):

Proximity radius around the specified location in kilometres. Requires Location to be set. 0 = exact city match. Kleinanzeigen uses preset steps (5, 10, 20, 30, 50, 100, 150, 200 km) and snaps to the nearest.

## `condition` (type: `string`):

Filter by item condition.

## `sellerType` (type: `string`):

Filter by seller type.

## `shipping` (type: `string`):

Filter by shipping availability.

## `adType` (type: `string`):

Listing type: offers for sale, or wanted ads.

## `priceMin` (type: `integer`):

Minimum price filter.

## `priceMax` (type: `integer`):

Maximum price filter. 0 = no limit.

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

Sort order for results.

## `whatAnd` (type: `array`):

Keep only listings whose title (and description, when 📄 Enrichment is on) contains EVERY word listed here. Accent- and case-insensitive. Example: \["carbon", "rennrad"] keeps only carbon road bikes. Applied after fetching, so the returned count may be lower than Max Results.

## `whatExclude` (type: `array`):

Drop listings whose title (and description, when 📄 Enrichment is on) contains ANY of these words. Accent- and case-insensitive. Example: \["defekt", "bastler"] removes broken / for-parts listings. Applied after fetching, so the returned count may be lower than Max Results.

## `postedWithin` (type: `string`):

Keep only listings posted within this time window. 'Any time' applies no date filter. Applied after fetching, so the returned count may be lower than Max Results.

## `attributeFilters` (type: `object`):

Advanced per-category attribute filters — narrow a search by the same options the listing site itself offers (brand, fuel type, mileage, rooms, size, and so on). The easiest way to filter: set the options you want in your browser on the site, copy the search-result URL, and paste it into 🔗 Start URLs — every filter is captured automatically. To set them here instead, provide a map of `"category.attribute": "value"`. Values are the site's own lowercase tokens (e.g. `diesel`, not `Diesel`); comma-separate to match any of several (OR); use `min,max` for numeric ranges (either side optional). Requires the matching 📁 Category to be set. Examples — cars: `{ "autos.marke": "bmw", "autos.fuel": "diesel", "autos.km": "0,100000" }`; apartment rental: `{ "wohnung_mieten.zimmer": "2,", "wohnung_mieten.qm": "50," }`. Unrecognized values are sent as-is and may simply not narrow results.

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

Maximum total listings to return across all searches. 0 = unlimited.

## `incremental` (type: `boolean`):

Only return new or changed listings since the last run. State is saved between runs and scoped per query and category.

## `stateKey` (type: `string`):

Custom key for incremental state storage. Defaults to a key derived from your search query and category. Use to share state across runs with minor input variations.

## `emitUnchanged` (type: `boolean`):

In ♻️ Incremental Mode, also output listings that haven't changed since the last run (normally skipped). Off by default.

## `emitExpired` (type: `boolean`):

In ♻️ Incremental Mode, output a stub row (changeType=EXPIRED) for listings that were present in a previous run but are now gone. On by default.

## `skipReposts` (type: `boolean`):

In ♻️ Incremental Mode, suppress listings that look like a re-post of a previously expired one (same title, price, and location under a new ID). Off by default.

## `includeDetails` (type: `boolean`):

Fetch the full listing page for each result to add description, images, category path, attributes, and more. Produces richer output but takes longer.

## `includeSellerProfile` (type: `boolean`):

Fetch extra detail for each unique seller to add reputation badges and the seller's active-ads count. Adds one request per unique seller (a small per-seller charge applies) and increases run time.

## `includePhone` (type: `boolean`):

Resolve and include the seller's contact phone number for each listing. Requires an additional request per listing.

## `descriptionMaxLength` (type: `integer`):

Truncate listing descriptions to N characters. 0 = no truncation.

## `descriptionFormat` (type: `string`):

Pick a single description representation. `all` keeps every variant; `text` / `html` / `markdown` drops the others.

## `compact` (type: `boolean`):

Return only the most essential fields (for AI-agent and MCP workflows).

## `omitNulls` (type: `boolean`):

Drop null, empty string, empty array, and empty object fields from each output row. Reduces dataset size and removes noise for LLM pipelines. Keeps `false` and `0` as valid values. Default on — disable if you need a fixed schema where every row has every documented field.

## `excludeEmptyFields` (type: `boolean`):

Drop null, empty-string, and empty-array fields from each record before push. Smaller payloads for AI agents and dashboards.

## `telegramToken` (type: `string`):

Telegram bot token (from @BotFather). Required for Telegram notifications.

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

Telegram chat or channel ID (e.g. "-100123456789"). Required when telegramToken is set.

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

Discord incoming webhook URL. Server Settings → Integrations → Webhooks → New Webhook.

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

Slack incoming webhook URL. api.slack.com/messaging/webhooks.

## `whatsappPhoneNumberId` (type: `string`):

Your WhatsApp Business phone-number ID (numeric, from Meta dashboard). Required when whatsappAccessToken is set.

## `whatsappAccessToken` (type: `string`):

WhatsApp Cloud API permanent access token (System User token from Meta Business). Recipient must have messaged the business number within the last 24 h.

## `whatsappTo` (type: `string`):

Recipient phone in E.164 format without + (e.g. "436641234567"). Recipient must have messaged your business number within the last 24 h.

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

Receives a JSON POST with {metadata, items} after each run. Works with n8n, Make, Zapier, and custom backends.

## `webhookHeaders` (type: `object`):

Optional JSON object of custom headers (e.g. {"Authorization":"Bearer ..."}).

## `notificationLimit` (type: `integer`):

Maximum number of listings included in each notification message (1–20).

## `notifyOnlyChanges` (type: `boolean`):

When Incremental Mode is on, only send notifications for NEW and UPDATED listings. Has no effect outside incremental mode.

## `appConnector` (type: `string`):

Optional. Pick a connected app under Settings → API & Integrations to receive your results. Notion is supported today; other connectors are best-effort as Apify expands its catalog.

## `mcpIssueTeam` (type: `string`):

Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one.

## Actor input object example

```json
{
  "query": "iPhone",
  "queries": [],
  "startUrls": [],
  "watchSellerIds": [],
  "maxResultsPerQuery": 0,
  "category": "all",
  "radius": 0,
  "condition": "all",
  "sellerType": "all",
  "shipping": "all",
  "adType": "angebote",
  "priceMin": 0,
  "priceMax": 0,
  "sortBy": "newest",
  "whatAnd": [],
  "whatExclude": [],
  "postedWithin": "all",
  "attributeFilters": {
    "autos.marke": "bmw",
    "autos.fuel": "diesel",
    "autos.km": "0,100000"
  },
  "maxResults": 5,
  "incremental": false,
  "emitUnchanged": false,
  "emitExpired": true,
  "skipReposts": false,
  "includeDetails": true,
  "includeSellerProfile": false,
  "includePhone": false,
  "descriptionMaxLength": 0,
  "descriptionFormat": "all",
  "compact": false,
  "omitNulls": true,
  "excludeEmptyFields": false,
  "notificationLimit": 5,
  "notifyOnlyChanges": false
}
```

# Actor output Schema

## `results` (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 = {
    "query": "iPhone",
    "maxResults": 5,
    "includeDetails": false,
    "descriptionFormat": "all",
    "excludeEmptyFields": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("blackfalcondata/kleinanzeigen-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 = {
    "query": "iPhone",
    "maxResults": 5,
    "includeDetails": False,
    "descriptionFormat": "all",
    "excludeEmptyFields": False,
}

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

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

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

```

## CLI example

```bash
echo '{
  "query": "iPhone",
  "maxResults": 5,
  "includeDetails": false,
  "descriptionFormat": "all",
  "excludeEmptyFields": false
}' |
apify call blackfalcondata/kleinanzeigen-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=blackfalcondata/kleinanzeigen-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Kleinanzeigen Scraper — German Classifieds",
        "description": "Scrape classified listings from Kleinanzeigen.de — prices, locations, images, descriptions, and seller contacts including phone and email. Filter by keyword, category and location; incremental runs return only new listings.",
        "version": "0.1",
        "x-build-id": "LkYGq1ItqlQEDYc2K"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/blackfalcondata~kleinanzeigen-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-blackfalcondata-kleinanzeigen-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/blackfalcondata~kleinanzeigen-scraper/runs": {
            "post": {
                "operationId": "runs-sync-blackfalcondata-kleinanzeigen-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/blackfalcondata~kleinanzeigen-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-blackfalcondata-kleinanzeigen-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "query": {
                        "title": "🔍 Search Term",
                        "type": "string",
                        "description": "Single keyword or phrase (e.g. 'iPhone', 'sofa', 'Fahrrad'). For multiple searches in one run, use the `queries` array below."
                    },
                    "queries": {
                        "title": "🔎 Multiple Search Terms",
                        "type": "array",
                        "description": "Run multiple keyword searches in one go — e.g. `[\"laptop\", \"iPad\", \"AirPods\"]`. Results from all searches are merged and deduplicated by listing ID. Filters below (category, location, price, etc.) apply to all queries. Takes precedence over the single `query` field.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "🔗 Start URLs (paste-mode)",
                        "type": "array",
                        "description": "Paste one or more Kleinanzeigen.de search-result URLs. Build the filters you want in your browser, copy the URL, and paste here. Each URL is paginated; results are merged and deduplicated. Takes precedence over `query`, `queries`, and all filter inputs. The legacy `searchUrls` field name is still accepted for backward compatibility.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "watchSellerIds": {
                        "title": "👁️ Seller Watchlist",
                        "type": "array",
                        "description": "Track specific sellers by their numeric seller ID — paste the IDs (or full seller-inventory URLs) and the run returns each seller's current listings. Takes precedence over search term, queries, and Start URLs. Combine with ♻️ Incremental Mode to get only a seller's new or changed listings each run.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResultsPerQuery": {
                        "title": "📊 Max Results Per Query",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Cap per individual search when running multiple queries via `queries`. 0 = use the global Max Results for every query. Useful for balanced sampling across diverse searches.",
                        "default": 0
                    },
                    "category": {
                        "title": "📁 Category",
                        "enum": [
                            "all",
                            "autos",
                            "elektronik",
                            "mietwohnungen",
                            "haus_garten",
                            "jobs",
                            "familie_kind_baby",
                            "mode_beauty",
                            "eintrittskarten_tickets"
                        ],
                        "type": "string",
                        "description": "Filter by Kleinanzeigen category.",
                        "default": "all"
                    },
                    "location": {
                        "title": "📍 Location",
                        "type": "string",
                        "description": "City name or postal code to search within (e.g. 'Berlin', 'München', '10115'). Leave blank to search all of Germany."
                    },
                    "radius": {
                        "title": "📏 Search Radius (km)",
                        "minimum": 0,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Proximity radius around the specified location in kilometres. Requires Location to be set. 0 = exact city match. Kleinanzeigen uses preset steps (5, 10, 20, 30, 50, 100, 150, 200 km) and snaps to the nearest.",
                        "default": 0
                    },
                    "condition": {
                        "title": "✨ Condition",
                        "enum": [
                            "all",
                            "neu",
                            "sehr_gut",
                            "gut",
                            "in_ordnung",
                            "defekt"
                        ],
                        "type": "string",
                        "description": "Filter by item condition.",
                        "default": "all"
                    },
                    "sellerType": {
                        "title": "👤 Seller Type",
                        "enum": [
                            "all",
                            "privat",
                            "gewerblich"
                        ],
                        "type": "string",
                        "description": "Filter by seller type.",
                        "default": "all"
                    },
                    "shipping": {
                        "title": "📦 Shipping",
                        "enum": [
                            "all",
                            "ja",
                            "nein"
                        ],
                        "type": "string",
                        "description": "Filter by shipping availability.",
                        "default": "all"
                    },
                    "adType": {
                        "title": "📋 Listing Type",
                        "enum": [
                            "angebote",
                            "gesuche"
                        ],
                        "type": "string",
                        "description": "Listing type: offers for sale, or wanted ads.",
                        "default": "angebote"
                    },
                    "priceMin": {
                        "title": "💰 Min Price (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Minimum price filter.",
                        "default": 0
                    },
                    "priceMax": {
                        "title": "💰 Max Price (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum price filter. 0 = no limit.",
                        "default": 0
                    },
                    "sortBy": {
                        "title": "🔀 Sort By",
                        "enum": [
                            "newest",
                            "price_asc",
                            "price_desc"
                        ],
                        "type": "string",
                        "description": "Sort order for results.",
                        "default": "newest"
                    },
                    "whatAnd": {
                        "title": "🧩 Must Include All Words",
                        "type": "array",
                        "description": "Keep only listings whose title (and description, when 📄 Enrichment is on) contains EVERY word listed here. Accent- and case-insensitive. Example: [\"carbon\", \"rennrad\"] keeps only carbon road bikes. Applied after fetching, so the returned count may be lower than Max Results.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "whatExclude": {
                        "title": "🚫 Exclude Words",
                        "type": "array",
                        "description": "Drop listings whose title (and description, when 📄 Enrichment is on) contains ANY of these words. Accent- and case-insensitive. Example: [\"defekt\", \"bastler\"] removes broken / for-parts listings. Applied after fetching, so the returned count may be lower than Max Results.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "postedWithin": {
                        "title": "🕒 Posted Within",
                        "enum": [
                            "all",
                            "today",
                            "week",
                            "month"
                        ],
                        "type": "string",
                        "description": "Keep only listings posted within this time window. 'Any time' applies no date filter. Applied after fetching, so the returned count may be lower than Max Results.",
                        "default": "all"
                    },
                    "attributeFilters": {
                        "title": "🎛️ Attribute Filters",
                        "type": "object",
                        "description": "Advanced per-category attribute filters — narrow a search by the same options the listing site itself offers (brand, fuel type, mileage, rooms, size, and so on). The easiest way to filter: set the options you want in your browser on the site, copy the search-result URL, and paste it into 🔗 Start URLs — every filter is captured automatically. To set them here instead, provide a map of `\"category.attribute\": \"value\"`. Values are the site's own lowercase tokens (e.g. `diesel`, not `Diesel`); comma-separate to match any of several (OR); use `min,max` for numeric ranges (either side optional). Requires the matching 📁 Category to be set. Examples — cars: `{ \"autos.marke\": \"bmw\", \"autos.fuel\": \"diesel\", \"autos.km\": \"0,100000\" }`; apartment rental: `{ \"wohnung_mieten.zimmer\": \"2,\", \"wohnung_mieten.qm\": \"50,\" }`. Unrecognized values are sent as-is and may simply not narrow results.",
                        "default": {}
                    },
                    "maxResults": {
                        "title": "💯 Max Results",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum total listings to return across all searches. 0 = unlimited.",
                        "default": 25
                    },
                    "incremental": {
                        "title": "♻️ Incremental Mode",
                        "type": "boolean",
                        "description": "Only return new or changed listings since the last run. State is saved between runs and scoped per query and category.",
                        "default": false
                    },
                    "stateKey": {
                        "title": "🔑 State Key",
                        "type": "string",
                        "description": "Custom key for incremental state storage. Defaults to a key derived from your search query and category. Use to share state across runs with minor input variations."
                    },
                    "emitUnchanged": {
                        "title": "📤 Emit Unchanged Listings",
                        "type": "boolean",
                        "description": "In ♻️ Incremental Mode, also output listings that haven't changed since the last run (normally skipped). Off by default.",
                        "default": false
                    },
                    "emitExpired": {
                        "title": "🗑️ Emit Expired Listings",
                        "type": "boolean",
                        "description": "In ♻️ Incremental Mode, output a stub row (changeType=EXPIRED) for listings that were present in a previous run but are now gone. On by default.",
                        "default": true
                    },
                    "skipReposts": {
                        "title": "🔁 Skip Reposts",
                        "type": "boolean",
                        "description": "In ♻️ Incremental Mode, suppress listings that look like a re-post of a previously expired one (same title, price, and location under a new ID). Off by default.",
                        "default": false
                    },
                    "includeDetails": {
                        "title": "📋 Include Full Listing Details",
                        "type": "boolean",
                        "description": "Fetch the full listing page for each result to add description, images, category path, attributes, and more. Produces richer output but takes longer.",
                        "default": true
                    },
                    "includeSellerProfile": {
                        "title": "👤 Include Seller Profile",
                        "type": "boolean",
                        "description": "Fetch extra detail for each unique seller to add reputation badges and the seller's active-ads count. Adds one request per unique seller (a small per-seller charge applies) and increases run time.",
                        "default": false
                    },
                    "includePhone": {
                        "title": "📞 Include Phone Number",
                        "type": "boolean",
                        "description": "Resolve and include the seller's contact phone number for each listing. Requires an additional request per listing.",
                        "default": false
                    },
                    "descriptionMaxLength": {
                        "title": "✂️ Description Max Length",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Truncate listing descriptions to N characters. 0 = no truncation.",
                        "default": 0
                    },
                    "descriptionFormat": {
                        "title": "Description format",
                        "enum": [
                            "all",
                            "text",
                            "html",
                            "markdown"
                        ],
                        "type": "string",
                        "description": "Pick a single description representation. `all` keeps every variant; `text` / `html` / `markdown` drops the others.",
                        "default": "all"
                    },
                    "compact": {
                        "title": "📦 Compact Output",
                        "type": "boolean",
                        "description": "Return only the most essential fields (for AI-agent and MCP workflows).",
                        "default": false
                    },
                    "omitNulls": {
                        "title": "🧹 Omit Null / Empty Fields",
                        "type": "boolean",
                        "description": "Drop null, empty string, empty array, and empty object fields from each output row. Reduces dataset size and removes noise for LLM pipelines. Keeps `false` and `0` as valid values. Default on — disable if you need a fixed schema where every row has every documented field.",
                        "default": true
                    },
                    "excludeEmptyFields": {
                        "title": "Exclude empty fields from output",
                        "type": "boolean",
                        "description": "Drop null, empty-string, and empty-array fields from each record before push. Smaller payloads for AI agents and dashboards.",
                        "default": false
                    },
                    "telegramToken": {
                        "title": "🔑 Telegram Bot Token",
                        "type": "string",
                        "description": "Telegram bot token (from @BotFather). Required for Telegram notifications."
                    },
                    "telegramChatId": {
                        "title": "💬 Telegram Chat ID",
                        "type": "string",
                        "description": "Telegram chat or channel ID (e.g. \"-100123456789\"). Required when telegramToken is set."
                    },
                    "discordWebhookUrl": {
                        "title": "🎮 Discord Webhook URL",
                        "type": "string",
                        "description": "Discord incoming webhook URL. Server Settings → Integrations → Webhooks → New Webhook."
                    },
                    "slackWebhookUrl": {
                        "title": "💼 Slack Webhook URL",
                        "type": "string",
                        "description": "Slack incoming webhook URL. api.slack.com/messaging/webhooks."
                    },
                    "whatsappPhoneNumberId": {
                        "title": "📞 WhatsApp Phone Number ID",
                        "type": "string",
                        "description": "Your WhatsApp Business phone-number ID (numeric, from Meta dashboard). Required when whatsappAccessToken is set."
                    },
                    "whatsappAccessToken": {
                        "title": "📱 WhatsApp Access Token",
                        "type": "string",
                        "description": "WhatsApp Cloud API permanent access token (System User token from Meta Business). Recipient must have messaged the business number within the last 24 h."
                    },
                    "whatsappTo": {
                        "title": "📲 WhatsApp Recipient",
                        "type": "string",
                        "description": "Recipient phone in E.164 format without + (e.g. \"436641234567\"). Recipient must have messaged your business number within the last 24 h."
                    },
                    "webhookUrl": {
                        "title": "🪝 Generic Webhook URL",
                        "type": "string",
                        "description": "Receives a JSON POST with {metadata, items} after each run. Works with n8n, Make, Zapier, and custom backends."
                    },
                    "webhookHeaders": {
                        "title": "📋 Webhook Headers",
                        "type": "object",
                        "description": "Optional JSON object of custom headers (e.g. {\"Authorization\":\"Bearer ...\"})."
                    },
                    "notificationLimit": {
                        "title": "📊 Max Listings Per Notification",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of listings included in each notification message (1–20).",
                        "default": 5
                    },
                    "notifyOnlyChanges": {
                        "title": "🔄 Notify Only New/Updated",
                        "type": "boolean",
                        "description": "When Incremental Mode is on, only send notifications for NEW and UPDATED listings. Has no effect outside incremental mode.",
                        "default": false
                    },
                    "appConnector": {
                        "title": "Send results to Notion (or another connected app)",
                        "type": "string",
                        "description": "Optional. Pick a connected app under Settings → API & Integrations to receive your results. Notion is supported today; other connectors are best-effort as Apify expands its catalog."
                    },
                    "mcpIssueTeam": {
                        "title": "Issue tracker team",
                        "type": "string",
                        "description": "Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
