# Kleinanzeigen Scraper & API - eBay Kleinanzeigen Ads & Prices (`rel8ble/kleinanzeigen-scraper`) Actor

Kleinanzeigen scraper and API (formerly eBay Kleinanzeigen): search Kleinanzeigen.de ads by keyword, category, city or postcode + radius, price and seller type. One result = one ad: title, price, VB, place, date, seller type, shop, photos, URL. Details included, no start fee. $0.35 per 1,000.

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

## Pricing

$0.35 / 1,000 results

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Kleinanzeigen Scraper & API - eBay Kleinanzeigen Ads & Prices

**Kleinanzeigen scraper** and unofficial **Kleinanzeigen API** (formerly **eBay Kleinanzeigen**): search Germany's biggest classifieds marketplace by keyword, category, city or postcode + radius, price, private or commercial seller, offers or wanted ads, and export the ads to JSON, CSV or Excel. Use it as a **Kleinanzeigen price tracker**, for **second-hand market prices in Germany**, resale and flipping research, dealer monitoring and new-ad alerts.

- **What goes in:** search keywords, categories, German places (city, district or postcode) with a radius, price range, seller type, sort order, or Kleinanzeigen result / ad URLs.
- **What comes out:** one row per ad: title, price, price type (fixed / VB / free), old price, postcode, place, state, date, category, seller type (private / commercial), shop name and link for businesses, shipping, "Direkt kaufen", photos and URL. Optional: full description, all attributes (Zustand, Art, Typ, Größe ...), offer or wanted, shipping cost, approximate map position, seller badges.
- **Typical cost:** $0.35 per 1,000 ads, details included, no start fee: the cheapest Kleinanzeigen scraper on the Store. A 20-ad check costs under 1 cent.
- **When to use it:** pricing a used item before you sell or buy, tracking what a model sells for in your region, finding underpriced listings, watching a competitor's shop, feeding German second-hand prices to an AI agent.

It reads the public result pages over plain HTTP, with **no headless browser** and no login, 25 ads per request. Kleinanzeigen shows at most 1,250 ads per search; deep search splits bigger searches automatically: in our tests "dyson v11" across Germany returned all 1,436 ads the site counted, and "lego" in Berlin returned 22,751 of 24,520 (93%; the rest are mostly ads with no price, see Limits). Unofficial: not affiliated with or endorsed by Kleinanzeigen.

### Sample output

Real rows from the prefilled cloud run (search `fahrrad`, all of Germany, 20 ads, 28 Oct 2026):

| title | priceText | place | posted | seller | shop |
|---|---|---|---|---|---|
| Husqvarna MC2 E-Bike, 221km, neuwertig | 1.900 € | 79790 Küssaberg | 2026-10-22 | private | - |
| Rennrad zu verkaufen | 900 € VB | 96129 Strullendorf | 2026-10-28 | private | - |
| AXESS SANDEE MTB | 315 € | 85757 Karlsfeld | 2026-10-28 | private | - |
| Santa Cruz Nomad 5 C XL | 2.500 € VB | 30519 Döhren-Wülfel | 2026-10-28 | private | - |
| ✨SUPER-ANGEBOTE Gebrauchte Rennräder Gravel Trekking ab 500€ | VB | 80686 Laim | 2026-10-07 | commercial | Bicycle-REpublic | The land of 2nd hand bikes |

Every row also carries the numeric `price`, `priceType` (fixed / negotiable / free), state, category, shipping and "Direkt kaufen" flags, photo links and the ad URL.

### Use cases

- **Price research**: see what a model really sells for in Germany, or within 30 km of your city, before you buy or sell.
- **Resale and flipping**: catch underpriced ads with a scheduled `newest` search and a price ceiling.
- **New-ad alerts**: hourly runs into Telegram, Slack or e-mail through Make, Zapier or n8n.
- **Dealer and competitor monitoring**: commercial sellers come with shop name, shop page and, with details, their website and number of ads online.
- **Market research**: supply and asking prices by category, state and city.
- **AI agents**: "used e-bikes under 1,500 € within 30 km of München" maps straight onto the input fields.

### Pricing

**$0.35 per 1,000 ads** (pay per result; you pay only for ads saved to the dataset). Ad details are included at the same price. Other Kleinanzeigen scrapers on the Store (October 2026): memo23 $1.50 + $0.005 per run, beatanalytics $1.50, igolaizola $1.00 + $0.01 per run + $1.00 for details, fatihtahta $0.99, blackfalcondata $0.40 + $0.005 per run, unfenced-group $0.39 ($0.99 with details).

| You scrape | You pay |
|---|---|
| 100 ads | $0.035 |
| 1,000 ads | $0.35 |
| 10,000 ads | $3.50 |
| 100,000 ads | $35.00 |

No start fee. The Apify free plan's $5 monthly credit covers about 14,000 ads. The prefilled input (`fahrrad`, 20 ads) costs $0.007 and took about 9 seconds in a cloud test. You're never charged for failed or blocked requests, retries, duplicates, or ad URLs that no longer exist. If you set a maximum cost per run, the scraper stops cleanly when it reaches it.

#### Why this one

- **Cheapest Kleinanzeigen scraper on the Store**: $0.35 per 1,000 with details included and no start fee, under a quarter of the $1.50 the most-used ones charge.
- **Ad details at the same price**: description, attributes (Zustand, Art, Typ ...), shipping cost, map position and seller badges.
- **Deep search past the 1,250-ad limit**: all 1,436 "dyson v11" ads in Germany in one test run.
- **The site's own filters**: city or postcode + radius, price, private / commercial, offers / wanted, or a pasted search URL.
- **No personal data**: no names, phone numbers or e-mails of private sellers.

### FAQ

**Does it need a Kleinanzeigen account or a browser?**
No. It reads public result and ad pages over HTTPS, the same pages any visitor sees.

**How do I use the filters from the Kleinanzeigen website?**
Set the filters on kleinanzeigen.de, copy the URL from the address bar and paste it into `startUrls`. Keyword, category, place and radius, price, private / commercial, offers / wanted, sort and category-specific filters (type, size, condition, brand ...) are all kept from the URL.

**How do I find a category id?**
Open the category on kleinanzeigen.de; the id is the number after `c` at the end of the URL, e.g. `217` in `/s-fahrraeder/c217`. You can also type the German category name (`Fahrräder & Zubehör`). Every row has its `categoryId`.

**How do I track new ads for a search?**
Schedule the actor with `sort: "newest"` and a `maxItems` that covers what appears between two runs (for example 50 every hour), and keep the `id`s you have already seen.

**What about personal data?**
Many sellers are private people, so the actor collects no names, phone numbers or e-mail addresses, and no user id for private sellers: only `sellerType: "private"`. For commercial sellers (businesses) it adds the public shop name, shop page, user id and website. E-mail addresses and phone numbers that sellers type into descriptions are replaced with `[email removed]` / `[phone removed]`. Map positions are rounded to about 1 km.

**Is it legal to scrape Kleinanzeigen?**
This actor collects publicly available ad information without logging in. You're responsible for using the data in line with Kleinanzeigen's terms and applicable law (including GDPR). This isn't legal advice; if you're unsure, check with a lawyer.

**How does it avoid blocks?**
It sends normal browser-like requests through Apify Proxy at a polite pace, rotates sessions and IPs when a request is refused (up to 8 retries), and retries stubborn requests through a German residential IP (at most 50 per run). In our cloud tests about 70% of requests from shared datacenter IPs were first refused ("IP-Bereich vorübergehend gesperrt", IP range temporarily blocked); retries on other IPs got every page, 2 of 40 requests needed a residential IP, and the 3-search test run cost under a cent in platform usage.

**What happens if I run it with no input?**
It does a demo search for "fahrrad" (20 ads) instead of failing.

### How to use

1. Type one or more **search keywords** (`e-bike`, `iphone 13`, `ikea kallax`). Optionally add **categories** (`217` = Fahrräder & Zubehör) and **places** (`Berlin`, `80331`) with a radius.
2. Or paste **Kleinanzeigen URLs**: set the filters on kleinanzeigen.de, copy the address bar, paste it into `startUrls`. Ad URLs work too.
3. Click **Start**. Ads are saved as they come in; download them as JSON, CSV or Excel, or read them through the Apify API.
4. For a price tracker or new-ad alerts, schedule the actor (for example every hour with `sort: "newest"` and `maxItems: 50`) and deduplicate on `id`.

### Input

All fields are optional. An empty input runs a 20-ad demo search for "fahrrad".

| Field | Default | What it does |
|---|---|---|
| `searchQueries` | - | Keywords as typed into the Kleinanzeigen search box, one per line. |
| `categories` | all | Category ids or German names: `217` / `Fahrräder & Zubehör`, `161` Elektronik, `173` Handy & Telekom, `80` Haus & Garten, `216` Autos ... |
| `locations` | all Germany | City, district or 5-digit postcode (`München`, `Hamburg-Altona`, `50667`), resolved with the site's place lookup. |
| `radiusKm` | - | Radius around each place: 5, 10, 20, 30, 50, 100, 150 or 200 km. |
| `priceMin`, `priceMax` | - | Price range in whole euros. `0`-`0` = free items only. |
| `sellerType` | `any` | `any`, `private` or `commercial`. |
| `adType` | `offer` | `offer` (for sale), `wanted` ("Gesuche") or `any`. |
| `buyNowOnly` | false | Only ads with "Direkt kaufen". |
| `shipping` | `any` | `any`, `yes` (seller ships) or `no` (pick-up only). |
| `sort` | `newest` | `newest`, `price_asc`, `price_desc`. |
| `startUrls` | - | Kleinanzeigen result URLs (all filters in the URL are kept, including attribute filters like `+fahrraeder.type_s:ebike`) and ad URLs. |
| `maxItems` | 100 | Ads per search (keyword x category x place). `0` = all of them. |
| `deepSearch` | true | Goes past the 1,250-ad limit per search by splitting into states, sub-categories and price bands. |
| `includeDetails` | false | Opens each ad for description, attributes, condition, shipping cost, map area and seller badges. Same price, slower. |

Example: private e-bike offers within 20 km of Munich, 500-2,000 EUR, cheapest first (this exact input returned 100 ads in 2.7 s in our test; the site counted 506 matches):

```json
{
    "searchQueries": ["e-bike"],
    "categories": ["217"],
    "locations": ["München"],
    "radiusKm": 20,
    "priceMin": 500,
    "priceMax": 2000,
    "sellerType": "private",
    "sort": "price_asc",
    "maxItems": 100
}
```

Several searches at once (each keyword in each place):

```json
{
    "searchQueries": ["playstation 5", "nintendo switch"],
    "locations": ["Berlin", "Hamburg", "Köln"],
    "maxItems": 50
}
```

Straight from URLs copied from the browser:

```json
{
    "startUrls": [
        "https://www.kleinanzeigen.de/s-fahrraeder/berlin/sortierung:preis/anbieter:privat/preis:10:100/fahrrad/k0c217l3331r10",
        "https://www.kleinanzeigen.de/s-anzeige:gesuche/sofa/k0",
        "https://www.kleinanzeigen.de/s-anzeige/garmin-varia-rtl516-ruecklicht-radar/3543804064-217-7414"
    ],
    "maxItems": 100
}
```

### Output

One dataset item per ad. This one is from a real run on 17 Oct 2026, search "e-bike" in category 217 with `includeDetails: true` (photo list shortened):

```json
{
    "id": "3543827725",
    "url": "https://www.kleinanzeigen.de/s-anzeige/chirp-sign-slim-e-bike-ruecklicht-220-sicht-neu/3543827725-217-6681",
    "title": "Chirp Sign Slim E-Bike Rücklicht – 220° Sicht – Neu",
    "price": 15,
    "priceText": "15 €",
    "priceType": "fixed",
    "oldPrice": null,
    "currency": "EUR",
    "descriptionSnippet": "Verkaufe ein Chirp Sign Slim Rücklicht für E-Bikes.\n\nSchlankes, modernes Design mit guter...",
    "postalCode": "89231",
    "city": "Neu Ulm",
    "state": "Bayern",
    "locationId": "6681",
    "postedAt": "2026-10-17T17:38:08.000Z",
    "postedText": "Heute, 19:38",
    "categoryId": "217",
    "categoryName": "Fahrräder & Zubehör",
    "parentCategoryName": "Auto, Rad & Boot",
    "adType": "offer",
    "sellerType": "private",
    "sellerId": null,
    "shopName": null,
    "shippingAvailable": true,
    "buyNowEnabled": true,
    "tags": ["Direkt kaufen"],
    "imageUrl": "https://img.kleinanzeigen.de/api/v1/prod-ads/images/3a/3a0c2395-2fed-4ffb-8a5c-af7d722c3f33?rule=$_59.AUTO",
    "imageCount": 1,
    "isTopAd": false,
    "searchQuery": "e-bike",
    "position": 4,
    "scrapedAt": "2026-10-17T17:39:30.048Z",
    "description": "Verkaufe ein Chirp Sign Slim Rücklicht für E-Bikes.\n\nSchlankes, modernes Design mit guter Sichtbarkeit.\n\n• 220° Sichtbarkeit\n• StVZO-Zulassung laut Verpackung\n• Schlanke, platzsparende Bauform\n• Für E-Bikes geeignet\n• In Originalverpackung\n\nZustand: Neu und unbenutzt",
    "attributes": { "Art": "Zubehör", "Typ": "Elektrofahrräder", "Zustand": "Neu" },
    "condition": "Neu",
    "categoryPath": ["Auto, Rad & Boot", "Fahrräder & Zubehör"],
    "shippingText": "+ Versand ab 0,99 €",
    "shippingCost": 0.99,
    "pickupOnly": false,
    "postedDate": "2026-10-17",
    "latitude": 48.37,
    "longitude": 10.01,
    "locationText": "89231 Bayern - Neu Ulm",
    "sellerActiveSince": "2019-04-03",
    "sellerBadges": ["TOP Zufriedenheit", "Besonders zuverlässig"],
    "isAvailable": true
}
```

A commercial seller from the same run (shortened). Businesses come with their public shop name, shop page and, with details, their website and number of ads online:

```json
{ "id": "3543321289", "title": "*NEU* SCOTT Patron eRIDE 920 - 750WH E-Fully E-MTB E-Bike", "price": 3199, "priceType": "fixed", "city": "Altshausen", "sellerType": "commercial", "sellerId": "130177959", "shopName": "RV-Bikes", "shopUrl": "https://www.kleinanzeigen.de/pro/rv-bikes", "shopWebsite": "http://www.rv-bikes.de", "sellerAdsOnline": 81, "condition": "Neu" }
```

The dataset has two ready-made views, **Overview** (with photo thumbnails) and **Details**. A `RUN_SUMMARY` record in the key-value store lists, for each search, how many ads were saved, the total the site shows, how many narrower searches deep search ran, why it stopped, and any warnings (for example a place that was not found).

#### Field fill rates (real test runs)

Result-page rows (22,751 rows, "lego" in Berlin, deep search): id, url, title, priceText, priceType, currency, descriptionSnippet, postalCode, city, state, locationId, postedAt, categoryId, categoryName, sellerType, imageUrl, imageCount 100%; price 100% here (96% on a whole-Germany search, where "VB"-only ads are included); oldPrice 21% (only reduced ads have one); shippingAvailable 83%; buyNowEnabled 35%; shopName / shopUrl / sellerId 1% (only commercial sellers have them; 100% of commercial rows).

With `includeDetails` (101 rows: e-bikes, a shop search and wanted sofas in Hamburg): description, attributes, categoryPath, adType, postedDate, latitude / longitude, locationText, sellerActiveSince, isAvailable 100%; shippingText 97%; sellerBadges 89%; condition 80% (categories without a "Zustand" field have none); shopName / shopWebsite / sellerAdsOnline on commercial rows.

### API example

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("rel8ble/kleinanzeigen-scraper").call(run_input={"searchQueries": ["iphone 13"], "locations": ["Berlin"], "radiusKm": 20, "maxItems": 200})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], "|", item["priceText"], "|", item["city"])
```

One HTTP call that runs the actor and returns the rows (curl):

```bash
curl -X POST "https://api.apify.com/v2/acts/rel8ble~kleinanzeigen-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries": ["e-bike"], "categories": ["217"], "sort": "newest", "maxItems": 50}'
```

### Integrations

- **Make, Zapier and n8n**: trigger runs and pass new Kleinanzeigen ads into any workflow (Telegram, Slack or e-mail alerts for new listings under a price).
- **Google Sheets**: send each run's dataset straight into a spreadsheet to track prices over time.
- **Apify API**: start runs and fetch results over REST, or with the JavaScript and Python API clients.
- **Webhooks**: get notified when a run finishes, then pull the new data.
- **MCP for AI agents**: the Apify MCP server (https://mcp.apify.com) lets Claude, ChatGPT, Cursor and other agents call this actor and read German classifieds prices directly. Typical agent call: `{"searchQueries": ["iphone 13"], "locations": ["Berlin"], "maxItems": 20}`, under 2 cents.
- **Schedules**: run it every hour with `sort: "newest"` to catch new ads as they appear.

### Limits

- **Kleinanzeigen shows at most 1,250 ads per search** (50 pages of 25). Deep search (on by default) splits bigger searches by state, then sub-category, then price band, and merges the results. Ads without any price ("VB" only) cannot be reached by a price band, so a search that needs price splitting can miss a few percent of them; the run summary shows the site's total next to what was saved.
- **Big deep searches take time.** Requests are paced to stay polite (about 50-150 pages a minute), so all 870,000 "fahrrad" ads in Germany would take many hours. Narrow with categories and places where you can.
- **Dates.** The result page shows "Heute, 19:11" / "Gestern, 08:05" for recent ads (saved as an exact Berlin-time ISO timestamp) and only a date for older ones. With `includeDetails`, many ads get the exact posting time.
- **Pinned "TOP" ads** appear at the top of each result page, so they can show up in a search slightly outside its order; `isTopAd` marks them.
- **View counts are not included.** The site's only public view counter adds one view each time it is read, which would inflate sellers' numbers.
- **Not included:** seller names, phone numbers and e-mails, chat messages, sold-ad history, member profiles, and anything that needs a Kleinanzeigen login.

### How it works (for developers)

Kleinanzeigen's result pages are server-rendered; the listing data comes as JSON props of an Astro island (`ImpressionTracker`), next to the cards (old price, shop name). Result URLs encode every filter in the path: `/s-<filters>/<keyword>/k0c<category>l<location>r<radius>`, with filter segments like `sortierung:preis`, `anbieter:privat`, `anzeige:gesuche`, `preis:10:100` and `seite:N` for paging. Places are resolved with `/s-ort-empfehlungen.json`. The facet sidebar carries counts per state and sub-category, which deep search uses to split searches above 1,250. Ad pages come in two layouts (the classic one and a newer Astro one, rolled out to part of the traffic); both are parsed into the same fields.

```bash
npm install
npm test                                   # parser tests on saved real pages
APIFY_LOCAL_STORAGE_DIR=./storage node src/main.js   # input in storage/key_value_stores/default/INPUT.json
```

# Actor input Schema

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

Optional. What you would type into the Kleinanzeigen search box, one per line, in German or as product names: "fahrrad", "iphone 13", "ikea kallax", "e-bike", "lego technic". Each keyword is one search (times each category and place). Leave empty to list a whole category or place instead.

## `categories` (type: `array`):

Optional. Kleinanzeigen category ids or German names, one per line: "217" or "Fahrräder & Zubehör", "161" (Elektronik), "173" (Handy & Telekom). The id is the number after "c" in a result URL (/s-fahrraeder/c217). Top-level ids: 210 = Auto, Rad & Boot, 297 = Dienstleistungen, 231 = Eintrittskarten & Tickets, 161 = Elektronik, 17 = Familie, Kind & Baby, 185 = Freizeit, Hobby & Nachbarschaft, 80 = Haus & Garten, 130 = Haustiere, 195 = Immobilien, 102 = Jobs, 153 = Mode & Beauty, 73 = Musik, Filme & Bücher, 400 = Nachbarschaftshilfe, 235 = Unterricht & Kurse, 272 = Verschenken & Tauschen. Several = one search per category. Empty = all categories.

## `locations` (type: `array`):

Optional. German places, one per line: a city ("Berlin", "München"), a district ("Hamburg-Altona") or a 5-digit postcode ("80331"). Resolved with the site's own place lookup; an unknown place is left out and listed in the run summary. A Kleinanzeigen location id like "l3331" also works. Several = one search per place. Empty = all of Germany.

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

Optional, only used with places. Search radius in km around each place: 5, 10, 20, 30, 50, 100, 150, 200 (other numbers are rounded to the nearest of these). Empty or 0 = only the place itself. Rows then carry distanceKm.

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

Optional. Lowest price in whole euros, e.g. 50. Empty = no minimum. Note: ads without a price ("VB" only) are left out by any price filter, as on the website.

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

Optional. Highest price in whole euros, e.g. 300. 0 together with priceMin 0 = only free items ("Zu verschenken"). Empty = no maximum.

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

Optional. "any" (default), "private" (private individuals) or "commercial" (businesses and shops, which come with their shop name and link).

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

Optional. "offer" (default: items for sale), "wanted" (people looking for something, "Gesuche") or "any" (both, as the website shows by default).

## `buyNowOnly` (type: `boolean`):

Optional boolean, default false. true = only ads that can be bought online with Kleinanzeigen's "Direkt kaufen" (buy now).

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

Optional. "any" (default), "yes" (seller ships) or "no" (pick-up only).

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

Optional. "newest" (default, the site's own order; use it on a schedule to catch new ads), "price_asc" or "price_desc".

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

Optional. URLs copied from kleinanzeigen.de, one per line. A result URL ("https://www.kleinanzeigen.de/s-fahrraeder/berlin/preis:100:500/e-bike/k0c217l3331r10", a category or place page, or one with attribute filters like "+fahrraeder.type_s:ebike") is scraped with every filter in it; the filter fields above are not applied to it. An ad URL ("https://www.kleinanzeigen.de/s-anzeige/.../3543804064-217-7414") is looked up directly with full details. Seller and shop pages are not supported.

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

Optional. Maximum ads saved per search (one keyword x category x place, or one URL), integer >= 0. Default 100; 0 = every ad the search has. You pay per ad saved ($0.00035 each), so 1,000 ads = $0.35. Use 10-20 for a quick answer.

## `deepSearch` (type: `boolean`):

Optional boolean, default true. Kleinanzeigen shows at most 1,250 ads per search (50 pages of 25). With deep search on, a bigger search is split automatically by German state, then sub-category, then price band, and the results are merged without duplicates. Only kicks in when maxItems is above 1,250 (or 0). Costs extra requests and time, not extra money per ad.

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

Optional boolean. false (default) = data from the result pages: title, price, price type (VB), old price, place, postcode, date, category, seller type, shop name, shipping, photos, URL; 25 ads per request. true = also open each ad for the full description (contact details masked), all attributes (Zustand, Art, Typ, Größe ...), features, offer/wanted, shipping cost, posting date, approximate map position, all photos, and seller badges / member-since date. Same price per ad, about 1 extra request per ad.

## `maxConcurrency` (type: `integer`):

Optional, advanced. Parallel requests, integer 1-20. Default 5; requests are also paced to stay polite. Leave unset.

## `maxRequestRetries` (type: `integer`):

Optional, advanced. Retries per failed or blocked request, integer 0-20; each retry uses a new session and proxy IP. Default 8. Leave unset.

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

Optional, advanced. Apify Proxy settings object. Default {"useApifyProxy": true} (datacenter proxy). Leave unset.

## `residentialFallback` (type: `boolean`):

Optional, advanced boolean, default true. When a request fails 5 times in a row on the datacenter proxy, it is retried through a German residential IP (capped at 50 requests per run). Leave unset.

## Actor input object example

```json
{
  "searchQueries": [
    "fahrrad"
  ],
  "sellerType": "any",
  "adType": "offer",
  "buyNowOnly": false,
  "shipping": "any",
  "sort": "newest",
  "maxItems": 20,
  "deepSearch": true,
  "includeDetails": false,
  "maxConcurrency": 5,
  "maxRequestRetries": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": true
}
```

# Actor output Schema

## `ads` (type: `string`):

All ads found: title, price, price type (VB / fixed / free), old price, postcode, place, date, category, seller type, shop name for businesses, shipping, photos and URL (plus description, attributes, condition, shipping cost and seller badges when includeDetails is on).

## `summary` (type: `string`):

Per-search counts, the total the site shows for each search, how many narrower searches deep search ran, stop reasons, warnings (unknown places) and anything that failed.

# 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 = {
    "searchQueries": [
        "fahrrad"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/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 = {
    "searchQueries": ["fahrrad"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "fahrrad"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rel8ble/kleinanzeigen-scraper --silent --output-dataset

```

## MCP server setup

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

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

## OpenAPI specification

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