# Kleinanzeigen.de Scraper — German Classifieds Search (`yadroo/kleinanzeigen-de`) Actor

Kleinanzeigen.de (ex eBay Kleinanzeigen) scraper for resellers, dealers and AI agents: search by keyword, 159 categories, 48 German cities with radius, price, private/commercial, offers vs wanted ads, shipping.

- **URL**: https://apify.com/yadroo/kleinanzeigen-de.md
- **Developed by:** [Samat Makatov](https://apify.com/yadroo) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 result items

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Kleinanzeigen.de Scraper — German Classifieds Search

Search results from **kleinanzeigen.de** (formerly eBay Kleinanzeigen), Germany's largest classifieds site. Filter by keyword, any of 159 categories, 48 big cities with radius, price range, private or commercial sellers, offers or wanted ads, shipping, and category attributes. Each ad comes with price type (fixed / VB / free), old price, postcode, posting time, shipping and "Direkt kaufen" flags, and the shop name for commercial sellers. `detail: true` adds the full description, category attributes, coordinates, seller name, seller type, "active since" and all photos.

No proxies, no browser, no API key.

### Use cases

- **Reseller sourcing**: `"iphone 15"` in `handy-telekom`, private sellers, below your buy price, `sinceHours: 2` on an hourly schedule, so you see deals first.
- **Price research for pricing a product**: pull a few hundred ads for a model and take the median `price` of `priceType: "fixed"` ads.
- **Buyer-intent lead generation**: `adType: "wanted"` lists people *looking* for a product or service in your city (e.g. "Nachhilfe", "Wohnung", "Transporter").
- **Dealer & competitor monitoring**: `sellerType: "commercial"` shows which shops sell what, at what price (`shopName`, `shopUrl`).
- **Local market scans**: `category: "wohnung-mieten"` + `location: "Leipzig"` + `radiusKm: 10` gives private rental offers for rental-market analysis.
- **Brand protection / counterfeit checks**: brand keyword + `shippingOnly`, with detail pages for seller names and active-since dates.

### Input

At least a `query` or a `category` is required. All other fields are optional.

| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
| `query` | string | – (prefill `fahrrad`) | Keywords. Can be empty when `category` is set. |
| `category` | string | `k0` | Category id (`216`), code (`c216`), slug (`autos`) or German name. `k0` / empty = all. See **Reference**. |
| `location` | string | – | City from **Reference → Cities** (umlauts optional). Empty = all Germany. |
| `locationSlug` + `locationId` | string | – | Any other place, taken from a kleinanzeigen URL (`/s-bad-toelz/…/k0l7536` → `bad-toelz`, `l7536`). v0.1 inputs. |
| `radiusKm` | integer | – | `5`, `10`, `20`, `30`, `50`, `100`, `150`, `200` (needs a location) |
| `priceFrom` / `priceTo` | integer | – | € |
| `sellerType` | string | `all` | `all`, `private`, `commercial` |
| `adType` | string | `offer` | `offer` (Angebote), `wanted` (Gesuche), `all` |
| `shippingOnly` | boolean | `false` | Only "Versand möglich" |
| `attributes` | object | `{}` | Category attributes from a URL after `+`, e.g. `{"fahrraeder.type_s": "ebike"}`, `{"autos.marke_s": "bmw"}`, `{"global.zustand": "like_new"}` |
| `sort` | string | `newest` | `newest`, `price_asc`, `distance` |
| `sinceHours` | integer | – | Only ads posted in the last N hours |
| `includeTopAds` | boolean | `false` | Keep paid top ads (no date, may ignore filters) |
| `maxItems` | integer | `50` | 1–1250 (25 per page, the site shows at most 50 pages) |
| `maxPages` | integer | `10` | 1–50 |
| `detail` | boolean | `false` | Open each ad page (+1 request, about 3 s each) |
| `dedupe` | boolean | `true` | Drop repeated ids |
| `fields` | string\[] | `[]` | Output only these fields |

Unknown categories, cities, radii or malformed attributes fail immediately with a message listing the valid options, instead of silently searching all of Germany.

### Reference

#### Top-level categories

| Category | id | slug | Popular sub-categories (id slug) |
|---|---|---|---|
| Auto, Rad & Boot | 210 | `auto-rad-boot` | 216 `autos`, 223 `autoteile-reifen`, 211 `boote-bootszubehoer`, 217 `fahrraeder`, 305 `motorraeder-roller`, 306 `motorraeder-roller-teile` |
| Elektronik | 161 | `multimedia-elektronik` | 172 `audio-hifi`, 245 `foto`, 173 `handy-telekom`, 176 `haushaltsgeraete`, 279 `konsolen`, 278 `notebooks`, 228 `pcs`, 175 `tv-video` |
| Haus & Garten | 80 | `haus-garten` | 89 `garten-pflanzen`, 84 `heimwerken`, 88 `wohnzimmer` |
| Immobilien | 195 | `immobilien` | 203 `wohnung-mieten`, 196 `wohnung-kaufen`, 208 `haus-kaufen` |
| Familie, Kind & Baby | 17 | `familie-kind-baby` | 25 `kinderwagen-buggys`, 23 `spielzeug` |
| Mode & Beauty | 153 | `mode-beauty` | 154 `kleidung-damen` |
| Jobs | 102 | `jobs` | |
| Dienstleistungen | 297 | `dienstleistungen` | |
| Haustiere | 130 | `haustiere` | |
| Unterricht & Kurse | 235 | `unterricht-kurse` | |
| Eintrittskarten & Tickets | 231 | `eintrittskarten-tickets` | |
| Freizeit, Hobby & Nachbarschaft | 185 | `freizeit-nachbarschaft` | |
| Musik, Filme & Bücher | 73 | `musik-film-buecher` | |
| Verschenken & Tauschen | 272 | `zu-verschenken-tauschen` | |
| Nachbarschaftshilfe | 400 | `nachbarschaftshilfe` | |

The full tree of 159 categories (id, slug, name, parent) is built in: see [`src/dictionaries.ts`](./src/dictionaries.ts) or [kleinanzeigen.de/s-kategorien.html](https://www.kleinanzeigen.de/s-kategorien.html). Any category id from a URL (`…/c217`) works.

#### Cities (`location`)

| City | id | City | id | City | id |
|---|---|---|---|---|---|
| Berlin | 3331 | Hamburg | 9409 | München | 6411 |
| Köln | 945 | Frankfurt am Main | 4292 | Stuttgart | 9280 |
| Düsseldorf | 2068 | Leipzig | 4233 | Dortmund | 1085 |
| Dresden | 3820 | Hannover | 3155 | Duisburg | 2131 |
| Bochum | 1932 | Wuppertal | 1561 | Bielefeld | 1056 |
| Bonn | 1038 | Mannheim | 7971 | Wiesbaden | 4897 |
| Mönchengladbach | 1957 | Gelsenkirchen | 1000 | Aachen | 1921 |
| Braunschweig | 2448 | Kiel | 663 | Chemnitz | 3869 |
| Halle (Saale) | 2409 | Magdeburg | 2227 | Freiburg im Breisgau | 9354 |
| Krefeld | 1971 | Mainz | 5315 | Lübeck | 409 |
| Oberhausen | 1281 | Kassel | 4922 | Hagen | 2009 |
| Potsdam | 7958 | Saarbrücken | 382 | Ludwigshafen am Rhein | 5381 |
| Oldenburg | 3108 | Osnabrück | 3117 | Leverkusen | 1989 |
| Darmstadt | 4888 | Würzburg | 7667 | Ingolstadt | 7586 |
| Ulm | 9339 | Wolfsburg | 3071 | Göttingen | 3130 |
| Heilbronn | 9228 | Pforzheim | 9260 | Offenbach am Main | 4353 |

Essen, Bremen, Nürnberg, Münster, Karlsruhe, Augsburg, Erfurt, Rostock, Hamm, Heidelberg and Regensburg aren't built in yet (their ids couldn't be collected because of rate limits). Use `locationSlug` + `locationId` from a kleinanzeigen URL, e.g. open `kleinanzeigen.de/s-essen/k0` and copy the `l…` number.

### Examples

**Reseller alert: private iPhone 15 offers in Munich (+20 km), €200–700, last 2 hours**

```json
{ "query": "iphone 15", "category": "handy-telekom", "location": "München", "radiusKm": 20, "sellerType": "private", "priceFrom": 200, "priceTo": 700, "sinceHours": 2, "maxItems": 50 }
```

**Price research: e-bikes across Germany, cheapest first**

```json
{ "query": "e-bike", "category": "fahrraeder", "attributes": { "fahrraeder.type_s": "ebike" }, "sort": "price_asc", "maxItems": 250, "fields": ["title", "price", "priceType", "postcode", "url"] }
```

**Buyer-intent leads: people looking for a flat in Leipzig**

```json
{ "query": "", "category": "wohnung-mieten", "location": "Leipzig", "adType": "wanted", "maxItems": 100 }
```

**Competitor monitoring: commercial bike shops in Berlin with detail pages**

```json
{ "query": "gravel", "category": "fahrraeder", "location": "Berlin", "sellerType": "commercial", "detail": true, "maxItems": 30 }
```

### Output

Example item (run 2 above, `detail: true`, trimmed):

```json
{
  "id": "3511155909",
  "url": "https://www.kleinanzeigen.de/s-anzeige/iphone-15-pro-256gb-titan-schwarz-top-zustand/3511155909-173-16355",
  "title": "iPhone 15 Pro 256GB Titan Schwarz - Top Zustand",
  "description": "Ich verkaufe mein gepflegtes iPhone 15 Pro mit 256 GB Speicher…",
  "price": 630,
  "priceType": "negotiable",
  "priceText": "630 € VB",
  "oldPrice": null,
  "currency": "EUR",
  "postcode": "80799",
  "locationName": "Maxvorstadt",
  "publishedAt": "2026-09-13T08:35:00.000Z",
  "dateText": "Heute, 10:35",
  "shipping": true,
  "directBuy": true,
  "isTopAd": false,
  "sellerType": "private",
  "image": "https://img.kleinanzeigen.de/api/v1/prod-ads/images/98/9828193c-…?rule=$_59.AUTO",
  "imagesCount": 16,
  "query": "iphone 15",
  "fetchedAt": "2026-09-13T08:40:38.626Z",
  "category": "Handy & Telefon",
  "localityFull": "80799 München - Maxvorstadt",
  "latitude": 48.1510227,
  "longitude": 11.5757012,
  "attributes": { "Art": "Apple", "Farbe": "Schwarz", "Gerät & Zubehör": "Gerät", "Zustand": "Sehr Gut" },
  "detailFetched": true
}
```

| Field | Description |
|---|---|
| `id`, `url`, `title`, `description` | Ad id (stable), ad URL, title, teaser |
| `price`, `priceType`, `priceText`, `oldPrice`, `currency` | `fixed`, `negotiable` (VB), `free` (Zu verschenken), `on_request`; `oldPrice` when reduced |
| `postcode`, `locationName`, `location` | From the result card |
| `publishedAt`, `dateText` | ISO time (Europe/Berlin converted to UTC); older ads have a date only |
| `shipping`, `directBuy` | "Versand möglich", "Direkt kaufen" |
| `isTopAd`, `sellerType`, `shopName`, `shopUrl` | Commercial PRO shops are detected on the card |
| `image`, `imagesCount`, `query`, `searchTotal`, `searchUrl`, `fetchedAt` | |
| `titleFull`, `status`, `descriptionFull`, `category`, `localityFull`, `postedDate`, `latitude`, `longitude`, `attributes`, `features`, `sellerName`, `sellerTypeDetail`, `sellerActiveSince`, `sellerBadges`, `posterId`, `photos`, `detailFetched`, `detailError` | `detail: true` only |

### Use it from code / agents

**Apify API (curl)**

```bash
curl -X POST "https://api.apify.com/v2/acts/yadroo~kleinanzeigen-de/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"query":"playstation 5","location":"Hamburg","sellerType":"private","priceTo":350}'
```

**JavaScript (`apify-client`)**

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/kleinanzeigen-de').call({ query: 'thinkpad', category: 'notebooks', sort: 'price_asc', maxItems: 100 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**Python (`apify-client`)**

```python
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/kleinanzeigen-de").call(run_input={"query": "sofa", "location": "Köln", "adType": "offer", "maxItems": 50})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

**AI agents (MCP)**: connect `https://mcp.apify.com?actors=yadroo/kleinanzeigen-de` to Claude, Cursor or any MCP client.

### Pricing

Pay per event: **$0.005 per run start + $0.002 per ad** in the dataset.

- 50 ads (default): $0.105
- Hourly alert returning about 10 new ads: about $0.025 per run
- 250-ad price study: $0.505

`detail: true` doesn't change the price but is slow, about 3 s per ad.

### Limits & FAQ

- **Rate limits are strict.** kleinanzeigen.de temporarily blocks IP ranges after bursts of requests ("IP-Bereich vorübergehend gesperrt"). The actor waits 2.5–4 s between pages and detail pages, waits 45 s and retries once on a block, then:
  - on a search page with nothing collected yet, the run fails with a clear error (you aren't charged for items);
  - later in pagination, it stops and keeps the ads already collected;
  - on detail pages, the remaining ads stay list-only with `detailError`.
- **Keep scheduled runs small**: frequent runs with `maxPages` 1–3 and `sinceHours` work better than one huge run.
- **Pagination cap**: the site shows at most 50 pages (1 250 ads) per search. Split big searches by category or city.
- **Dates**: cards show "Heute/Gestern, HH:MM" for recent ads and a date for older ones. Date-only ads get midnight Berlin time.
- **Not included**: phone numbers and messaging (behind login on kleinanzeigen.de), and view counters (loaded by JavaScript).
- **Roadmap**: more built-in cities, attribute dictionaries per category (car make, bike type, clothing size).

***

Made by **Yadroo**. Sibling actors: [Willhaben.at (Austria)](https://apify.com/yadroo/willhaben-at) · [Otodom.pl (Poland)](https://apify.com/yadroo/otodom-pl) · [Marktplaats.nl](https://apify.com/yadroo/marktplaats-nl) · [AutoScout24 cars](https://apify.com/yadroo/autoscout24-cars) · [Rightmove UK](https://apify.com/yadroo/rightmove-uk) · [Krisha.kz](https://apify.com/yadroo/krisha-kz)

# Actor input Schema

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

Keyword(s), e.g. "e-bike", "iphone 15 pro", "3 zimmer wohnung". May be empty when a category is set (browse a whole category).

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

Category id, "c<id>" code, slug or German name. "k0" or empty = all categories. Top level: Auto, Rad & Boot = 210 (auto-rad-boot); Elektronik = 161 (multimedia-elektronik); Haus & Garten = 80 (haus-garten); Jobs = 102 (jobs); Nachbarschaftshilfe = 400 (nachbarschaftshilfe); Dienstleistungen = 297 (dienstleistungen); Familie, Kind & Baby = 17 (familie-kind-baby); Haustiere = 130 (haustiere); Mode & Beauty = 153 (mode-beauty); Unterricht & Kurse = 235 (unterricht-kurse); Eintrittskarten & Tickets = 231 (eintrittskarten-tickets); Freizeit, Hobby & Nachbarschaft = 185 (freizeit-nachbarschaft); Immobilien = 195 (immobilien); Musik, Filme & Bücher = 73 (musik-film-buecher); Verschenken & Tauschen = 272 (zu-verschenken-tauschen). Popular sub-categories: autos 216, fahrraeder 217, handy-telekom 173, notebooks 278, konsolen 279, wohnung-mieten 203, wohnung-kaufen 196, haus-kaufen 208, kleidung-damen 154. All 159 ids: README → Reference.

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

German city name from the built-in list (Berlin, Hamburg, München, Köln, Frankfurt am Main, Stuttgart, Düsseldorf, Leipzig, Dortmund, Dresden, Hannover, Bonn, Mannheim, Kiel, Mainz, Potsdam… — README → Reference). For any other place use locationId + locationSlug. Empty = all Germany.

## `locationSlug` (type: `string`):

URL slug of the place, e.g. "berlin", "bad-toelz" (v0.1 input). Use together with locationId for places not in the built-in list.

## `locationId` (type: `string`):

Number after "l" in a kleinanzeigen URL, e.g. l3331 for Berlin, l6411 München, l9409 Hamburg.

## `radiusKm` (type: `integer`):

Search around the location: 5, 10, 20, 30, 50, 100, 150 or 200 km. Needs a location.

## `priceFrom` (type: `integer`):

No description

## `priceTo` (type: `integer`):

No description

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

Private or commercial sellers.

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

Offers = items for sale/rent; wanted = people looking to buy/rent (buyer-intent leads).

## `shippingOnly` (type: `boolean`):

Only ads with "Versand möglich".

## `attributes` (type: `object`):

Category-specific filters copied from a kleinanzeigen URL after "+", e.g. {"fahrraeder.type\_s": "ebike"}, {"fahrraeder.art\_s": "damen"}, {"autos.marke\_s": "bmw"}, {"global.zustand": "like\_new"}. Requires category.

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

Sort order supported by the site.

## `sinceHours` (type: `integer`):

Only ads posted in the last N hours (from "Heute/Gestern, HH:MM" and dates on the cards). With newest sort pagination stops at the first page that is entirely older.

## `includeTopAds` (type: `boolean`):

Keep paid top ads (they carry no date and may not match filters).

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

Stop after this many ads (25 per page, kleinanzeigen shows max 50 pages).

## `maxPages` (type: `integer`):

Safety cap. kleinanzeigen.de rate-limits aggressively — keep this low for scheduled runs.

## `detail` (type: `boolean`):

+1 request per ad (~3 s each): full description, category attributes (Art, Typ, Zustand, Wohnfläche, Kilometerstand…), features, coordinates, seller name, private/commercial, active since, badges, all photos. If kleinanzeigen blocks the IP the remaining items stay list-only with detailError.

## `dedupe` (type: `boolean`):

Drop repeated ad ids.

## `fields` (type: `array`):

Keep only these fields, e.g. \["id","title","price","postcode","publishedAt","url"]. Empty = all.

## Actor input object example

```json
{
  "query": "fahrrad",
  "category": "k0",
  "sellerType": "all",
  "adType": "offer",
  "shippingOnly": false,
  "attributes": {},
  "sort": "newest",
  "includeTopAds": false,
  "maxItems": 50,
  "maxPages": 10,
  "detail": false,
  "dedupe": true,
  "fields": []
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `overview` (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": "fahrrad",
    "attributes": {},
    "fields": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("yadroo/kleinanzeigen-de").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": "fahrrad",
    "attributes": {},
    "fields": [],
}

# Run the Actor and wait for it to finish
run = client.actor("yadroo/kleinanzeigen-de").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 '{
  "query": "fahrrad",
  "attributes": {},
  "fields": []
}' |
apify call yadroo/kleinanzeigen-de --silent --output-dataset

```

## MCP server setup

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

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/aLbJhc7ELB56hsfjr/builds/VrfNi7l5nzVipgWXT/openapi.json
