# Kleinanzeigen Scraper - Listings, Prices & Sellers (`sian.agency/kleinanzeigen-scraper`) Actor

Scrape Kleinanzeigen.de listings by keyword, location or URL: price with VB handling, condition, category, seller, photos and full descriptions. Detail pages on demand.

- **URL**: https://apify.com/sian.agency/kleinanzeigen-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.79 / 1,000 listing searches

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Scraper — Listings, Prices & Sellers 🇩🇪

[![Store-SIÁN Agency](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store-eBay Data Scraper](https://img.shields.io/badge/Store-eBay%20Data%20Scraper-E53238)](https://apify.com/sian.agency/ebay-data-scraper?fpr=sian) [![Store-Marktplaats Scraper](https://img.shields.io/badge/Store-Marktplaats%20Scraper-5F1D82)](https://apify.com/sian.agency/marktplaats-scraper?fpr=sian) [![Store-Willhaben Property Scraper](https://img.shields.io/badge/Store-Willhaben%20Property%20Scraper-00AAFF)](https://apify.com/sian.agency/willhaben-property-scraper?fpr=sian)

#### 🎉 Every ad, every price — from $0.90 per 1,000 listings, with VB and giveaway prices parsed properly

##### Kleinanzeigen.de, Germany's biggest classifieds site (the former eBay Kleinanzeigen): cars, bikes, furniture, phones, tickets and everything else

***

### 🔎 What is the Kleinanzeigen Scraper — and when should you use it?

The **Kleinanzeigen Scraper** turns public classified ads from Kleinanzeigen.de, Germany's biggest classifieds site (formerly eBay Kleinanzeigen) into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

**Use it when you need:** ads from a keyword, a city or postcode, or a search URL you paste. Each row carries the title, the asking price and how that price works — fixed, negotiable (VB) or a giveaway (Zu verschenken) — the condition the seller claims, whether they ship or expect collection, the location, the posted date, the seller and the photo. Ask for the ad page too and each row also gets the untruncated description, the whole photo gallery, the condition and every attribute the seller filled in, the category name and the seller's profile.

**Use something else when:** the ad is not on kleinanzeigen.de. Use [eBay Data Scraper](https://apify.com/sian.agency/ebay-data-scraper?fpr=sian) for auction and retail listings on ebay.de with shipping and sold prices, where Kleinanzeigen is largely local and cash-in-hand. Use [Marktplaats Scraper](https://apify.com/sian.agency/marktplaats-scraper?fpr=sian) for the same classifieds pattern for the Netherlands and Belgium. Use [Willhaben Property Scraper](https://apify.com/sian.agency/willhaben-property-scraper?fpr=sian) for the Austrian classifieds market for property.

### 🤖 Use with AI agents

Already connected to the [Apify MCP server](https://mcp.apify.com)? Just ask for this Actor by name: sian.agency/kleinanzeigen-scraper

**Your agent can pay for its own runs.** This Actor is eligible for [agentic payments](https://docs.apify.com/platform/actors/publishing/monetize), so an agent can discover it, run it and settle the bill over [x402](https://www.x402.org/) (USDC on Base) or [Skyfire](https://www.skyfire.xyz/) — without an Apify account or API token of its own. Billing is the same either way: per successful row, never for errors.

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```text
I want listings and prices from Kleinanzeigen using the Apify Actor `sian.agency/kleinanzeigen-scraper`.

Use it when I need: ads from a keyword, a city or postcode, or a search URL you paste. Each row carries the title, the asking price and how that price works — fixed, negotiable (VB) or a giveaway (Zu verschenken) — the condition the seller claims, whether they ship or expect collection, the location, the posted date, the seller and the photo. Ask for the ad page too and each row also gets the untruncated description, the whole photo gallery, the condition and every attribute the seller filled in, the category name and the seller's profile.

Don't use it when: the ad is not on kleinanzeigen.de — use ebay-data-scraper or marktplaats-scraper or willhaben-property-scraper instead.

How to call it: give `keyword` a keyword and `location` a city or postcode, optionally with `radiusKm`. Narrow with `minPrice`, `maxPrice` or `shippingOnly`. `includeDetails` opens each ad's own page for the full text, the whole gallery, condition, category name and the seller's profile, at an extra charge per ad. To pull a seller's live ads, set `operation` to `seller` and pass `sellerIds` (their list URL or the numeric seller ID); to expand ads you already have, set `operation` to `detail` and pass `adUrls` (full addresses or bare ad IDs); to reuse a search you built on the site, paste it into `searchUrls`.

Start with this input:
{
  "operation": "search",
  "keyword": "fahrrad",
  "location": "Berlin",
  "maxPrice": 500,
  "maxResults": 100
}

Ask me what they are looking for and where in Germany — a city, a postcode or the whole country — plus whether they want a price ceiling, then run the Actor and summarise the results as a table.
```

**Things you can ask your agent for:**

- *Find every bicycle under 500 euros in Berlin that can be posted to me, newest first.*
- *Pull this seller's live ads on Kleinanzeigen and show me asking prices with condition.*
- *Track second-hand iPhone prices across Germany daily and tell me which giveaways appeared since yesterday.*

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at [apify.com/sian.agency/kleinanzeigen-scraper.md](https://apify.com/sian.agency/kleinanzeigen-scraper.md).

### 📋 Overview

**Kleinanzeigen is where Germany buys and sells second-hand.** A bicycle search in Berlin alone reads around 35,000 live ads, and the site covers every category from cars to concert tickets. This actor turns any slice of that into rows you can sort, filter and drop into a spreadsheet.

**What you get:**

- ⚡ **From $0.90 per 1,000 listings**: under almost every comparable tool on the Store. There is no key to buy and no proxy bill behind it.
- 🎯 **30+ fields per ad**: asking price with VB and giveaway handling, condition, category, location, posted date, seller and photos.
- 💶 **German price semantics, parsed**: `330 € VB` becomes a negotiable 330, `Zu verschenken` becomes a free ad with price 0 — so your averages and filters behave instead of breaking on German text.
- 📍 **Anywhere in Germany**: a city name, a postcode, a radius around either, or the whole country.
- 🔗 **Paste a URL and it just works**: copy any search or category address from the site and every filter baked into it travels with it.
- 🏪 **A seller's live ads in one run**: hand it a seller URL or ID and get their current stock.
- ✨ **Ad-page enrichment on demand**: the untruncated description, the whole gallery, condition, the category name, the exact posting date and the seller's profile.

***

### ✨ Features

- 🔍 **Keyword search**: any word or phrase, in German or not. German finds more.
- 🌐 **Pasted search URLs**: reuse a search you built on the site, sub-categories and facets included.
- 📍 **Location and radius**: a city, a postcode, and how far around it to look.
- 💶 **Price bands**: min and max in whole euros, applied by the site before it counts results.
- 🚚 **Shipping filter**: only ads that can be posted to you, which turns a local search into a national one.
- 🏪 **Seller listings**: every ad on a seller's public list page, from their URL or numeric ID.
- 📄 **Ad detail by URL or bare ID**: the number in the address is enough, no slug needed.
- 🆕 **Newest-first results**: the shape a monitoring schedule wants.
- 🧾 **Full row transparency**: failed inputs come back as rows explaining what to check, and are never charged.

***

### 🎬 Quick Start

Pick a keyword and a city, set how many ads you want, press Start. There is no account to connect and no key to paste. Results land in a dataset you can export as JSON, CSV or Excel.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~kleinanzeigen-scraper/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"operation":"search","keyword":"fahrrad","location":"Berlin","maxResults":50}'
```

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose what to search

Type a keyword, or paste a search address from the site. Either works on its own.

#### Step 2: Say where and how narrow

A city or postcode, a radius, a price band, shipping only, or nothing at all (which means all of Germany).

#### Step 3: Press Start

Results appear as they arrive. Export as JSON, CSV or Excel, or read them straight off the API.

**That's it. Within about a minute you'll have:**

- Every matching ad with its asking price, and whether that price is fixed, negotiable or a giveaway
- The location and posted date for each one
- The seller behind every ad, ready to expand into their live stock

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|---|---|---|---|
| `operation` | string | No | `search`, `seller` or `detail`. Defaults to `search`. |
| `keyword` | string | No | What to search for. German words find more. |
| `location` | string | No | City name or German postcode. Empty means all of Germany. |
| `searchUrls` | array | No | Search or category addresses copied from the site. |
| `radiusKm` | integer | No | How far around the location to look, 0-200. 0 uses the location's own area. |
| `minPrice` / `maxPrice` | integer | No | Price band in whole euros. 0 means no bound. |
| `shippingOnly` | boolean | No | Only ads that can be posted to you. |
| `adUrls` | array | No | Ad addresses or bare ad IDs, for the `detail` operation. |
| `sellerIds` | array | No | Seller list URLs or numeric seller IDs, for the `seller` operation. |
| `maxResults` | integer | No | Whole-run ad budget. Defaults to 100. |
| `includeDetails` | boolean | No | Open each ad's page for the extra fields. Bills one extra event per ad. |

**Example: a keyword search with filters**

```json
{
  "operation": "search",
  "keyword": "fahrrad",
  "location": "Berlin",
  "maxPrice": 500,
  "shippingOnly": true,
  "maxResults": 100
}
```

**Example: a seller's live ads**

```json
{
  "operation": "seller",
  "sellerIds": ["79594745"]
}
```

**Example: expand ads you already have**

```json
{
  "operation": "detail",
  "adUrls": ["3499520216"]
}
```

***

### 📤 Output

Every row is flat, and all three operations return the same shape, so results merge cleanly. **28 fields**, including:

| Field | Type | Description |
|---|---|---|
| `adId` | string | The site's own ad ID. Stable; this is what you dedupe on. |
| `listingTitle` | string | The ad headline as the seller wrote it. |
| `url` | string | The ad's address on the site. |
| `price` | number | Asking price in euros. `0` for giveaways, empty when the seller named none. |
| `priceText` / `priceType` | string | The price exactly as shown, and `FIXED`, `NEGOTIABLE`, `FREE` or `NONE`. |
| `isNegotiable` | boolean | Whether the ad is marked VB (verhandlungsbasis). |
| `condition` | string | What the seller selected, in German: Neu, Sehr Gut, Gebraucht… Needs enrichment. |
| `categoryName` / `categoryId` | string / number | The category, by name and by the site's own ID. Name needs enrichment. |
| `location` | string | Postcode and district, as the site shows it. |
| `postedLabel` | string | When it went up: `Heute, 08:05` or `31.08.2026`. |
| `shippingAvailable` / `shippingLabel` | boolean / string | Whether they ship, or expect collection. |
| `sellerName` / `sellerUserId` | string | Who is selling. Feed the ID back in for their live stock. |
| `sellerProfileUrl` / `sellerType` | string | Their public list page, and private or commercial. |
| `imageUrl` / `imageUrls` / `imageCount` | string / array / number | The first photo, every photo, and how many. Gallery needs enrichment. |
| `attributes` | object | The category's own fields: Art, Typ, Zustand, Farbe and more. |
| `isTopAd` | boolean | Whether the placement is promoted. |

**Example row (with enrichment on):**

```json
{
  "adId": "3499520216",
  "listingTitle": "Pegasus Damenfahrrad 28 Zoll 50cm Rahmenhöhe",
  "url": "https://www.kleinanzeigen.de/s-anzeige/pegasus-damenfahrrad-28-zoll-50cm-rahmenhoehe/3499520216-217-9632",
  "price": 330,
  "priceText": "330 € VB",
  "priceType": "NEGOTIABLE",
  "isNegotiable": true,
  "condition": "Sehr Gut",
  "categoryName": "Fahrräder & Zubehör",
  "categoryId": 217,
  "location": "10969 Friedrichshain-Kreuzberg - Kreuzberg",
  "postedLabel": "31.08.2026",
  "shippingAvailable": false,
  "shippingLabel": "Nur Abholung",
  "sellerName": "H.A.N",
  "sellerUserId": "129290056",
  "sellerProfileUrl": "https://www.kleinanzeigen.de/s-bestandsliste.html?userId=129290056",
  "sellerType": "private",
  "imageUrl": "https://img.kleinanzeigen.de/api/v1/prod-ads/images/93/93f627a1-2671-4177-bca0-6ab22a747b52?rule=$_59.AUTO",
  "imageCount": 5,
  "attributes": { "Art": "Damen", "Typ": "Cross- & Trekkingräder", "Zustand": "Sehr Gut" },
  "status": "success"
}
```

***

### 💼 Use Cases & Examples

#### 1. Resale sourcing and price arbitrage

**Resellers who need the bottom of a price distribution, not a sample of it.**

**Input:** a keyword, `maxPrice`, `shippingOnly: true`.
**Output:** the cheapest live stock in that niche with photos and the seller behind each one.
**Use:** buy under market and relist. Giveaways (`Zu verschenken`) are free stock for flippers who move fast; they parse to price 0, so they are easy to filter for.

#### 2. Second-hand price research

**Analysts who need a defensible number for what a used thing is worth.**

**Input:** a keyword, a wide price band, `includeDetails: true`.
**Output:** thousands of asking prices with the condition claimed, the exact posting date and the seller's profile.
**Use:** separate a fair price from an optimistic one, at a sample size a manual check could never reach.

#### 3. Flohmarkt and dealer inventory tracking

**Dealers and market analysts watching what the trade is actually asking.**

**Input:** a dealer's seller ID, or a category across a city.
**Output:** their live ads with asking prices and condition, or a whole local market in one sweep.
**Use:** price your own stock against today's market instead of last quarter's guide.

#### 4. New-listing monitoring and alerts

**Buyers hunting something scarce, and traders who want first look.**

**Input:** a narrow search on a daily schedule.
**Output:** results come back newest-first, so each run's top rows are what appeared since the last one.
**Use:** a daily watch on a niche category that costs cents, because you never re-pay for yesterday's ads.

#### 5. Seller and trade lead generation

**Agencies selling to small businesses that advertise here openly.**

**Input:** a trade-heavy category with `includeDetails: true`.
**Output:** commercial sellers flagged by `sellerType`, with their name, public list page and numeric seller ID.
**Use:** build a prospect list of bike shops, furniture dealers or tradespeople with proof they are trading.

***

### 🔗 Integration Examples

#### JavaScript / Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/kleinanzeigen-scraper').call({
  operation: 'search',
  keyword: 'fahrrad',
  location: 'Hamburg',
  maxPrice: 500,
  shippingOnly: true,
  maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/kleinanzeigen-scraper').call(run_input={
    'operation': 'search',
    'keyword': 'fahrrad',
    'location': 'Hamburg',
    'maxPrice': 500,
    'shippingOnly': True,
    'maxResults': 100,
})

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['listingTitle'], item['price'], item['priceType'])
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~kleinanzeigen-scraper/runs?token=YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"operation":"search","keyword":"fahrrad","location":"Hamburg","maxPrice":500}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: a daily schedule.
2. **HTTP Request**: run this actor with your saved search.
3. **Process**: compare the returned `adId` list against yesterday's.
4. **Action**: post the new ads to Slack, or append them to a sheet.

***

### 📊 Performance & Pricing

#### FREE tier (try it now)

- **25 listings per run**, with every feature and every field switched on
- No credit card, no key, no account on the site
- Enough to see the exact shape of the data before you commit

#### PAID tier (production)

- **Unlimited listings per run**: searches page 27 ads at a time and keep going as long as results do
- Charged per listing returned. Failed inputs come back as rows explaining why, and are never charged.

💰 **From $0.90 per 1,000 listings**, falling with your plan tier. Ad-page enrichment is **$2.50 per 1,000** when you switch it on, and nothing when you don't. A seller's live ads bill at the search rate.

🔗 [View current pricing](https://apify.com/sian.agency/kleinanzeigen-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: Do I need an API key, a login or a proxy?**
A: No. Type a keyword and press Start.

**Q: How is a negotiable price handled?**
A: German classifieds mark prices three ways: fixed (`330 €`), negotiable (`330 € VB`) and free (`Zu verschenken`). Every row carries the exact text, a numeric price — 0 for giveaways — a price type of fixed, negotiable or free, and a negotiable flag. Your averages and price filters work on the number; the flavour survives in the text.

**Q: Can I paste a URL instead of filling in filters?**
A: Yes, that is the Search URLs field. The site resolves the address itself, so sub-categories, price bands and any other facet it carries all apply.

**Q: What does "Open each ad's page" add, and what does it cost?**
A: The untruncated description, every photo instead of the first, the condition and all seller-filled attributes, the category name, the exact posting date and the seller's profile with their type. It costs one extra request per ad, billed as one Listing Detail event on top of the listing row.

**Q: Does it return seller phone numbers or email addresses?**
A: No. The site hides phone numbers behind a login and routes messages through its own inbox, so there is nothing to read. You do get the seller's public list page, name, type and numeric ID.

**Q: Why is the price empty on some rows?**
A: The seller did not set one, typically on job ads and services. The price type field says which case it is, and a price band filter excludes them by design.

**Q: Can I get sold prices or price history?**
A: Not from the site. Ads disappear when they sell and there is no public archive. Run this on a schedule and diff your own snapshots, which is how everyone builds that dataset.

**Q: Which site does this cover?**
A: Kleinanzeigen.de — formerly eBay Kleinanzeigen. One site, all of Germany, every category.

***

### 🐛 Troubleshooting

**A search returns "no ads matched"**

- Widen it: drop the price band, clear the shipping filter, or use a bigger radius.
- German words find far more than English ones: `fahrrad`, not `bicycle`.

**A pasted URL comes back with "not a search address"**

- That address is an ad, a seller page or the homepage. Open the results page on the site and copy the address from there.
- Ad addresses belong in **Ad URLs** with the operation set to Listing Detail; the bare ad ID works too.

**A seller comes back with "no live ads"**

- The seller resolved, but their public list page currently shows nothing. Sellers go quiet between batches.
- Shop pages (the branded `/pro/…` addresses) list their ads in the browser only. Search the shop name as a keyword instead.

**A price filter dropped ads you expected to see**

- Setting either bound excludes ads with no fixed price (giveaways, price-on-request) because the site filters on the price field itself.
- Clear the bounds and filter on `price` in your own export instead.

**The condition or category-name column is empty on search rows**

- Those live on the ad's own page. Switch on "Open each ad's page" and they arrive on every row.

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

Kleinanzeigen and eBay Kleinanzeigen are trademarks of their respective owners. This actor is not affiliated with, endorsed by, or sponsored by any of them.

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- For issues or questions, open an issue on the [actor's Issues tab](https://apify.com/sian.agency/kleinanzeigen-scraper/issues)
- Check the [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `operation` (type: `string`):

🎯 **ONE OPERATION PER RUN.** Each returns the same row shape, so results merge cleanly.

🔍 **Listing Search** — a keyword, a city or postcode, and any filter the site offers. 27 ads per page, paged automatically.
📄 **Listing Detail** — ad URLs or bare ad IDs in; back come the full description, whole gallery, condition, category, posting date and seller profile.
🏪 **Seller Listings** — every ad on a seller's public list page, from their seller URL or numeric seller ID.

## `keyword` (type: `string`):

🔑 **WHAT TO SEARCH FOR.** Searches the ad title and body. German words find far more than English ones — 'fahrrad' not 'bicycle', 'smartphone' not 'phone'. 💡 **TIP:** leave this empty and paste a category or filtered search address into 🌐 Search URLs below to sweep a whole section.

## `searchUrls` (type: `array`):

🌐 **PASTE ADDRESSES INSTEAD OF FILLING THE FORM.** Copy any search, category or filtered results address from the site and drop it here. 🧠 **The site resolves each address itself**, so every filter baked into it is honoured — sub-categories, price bands, condition facets, and anything added after this actor shipped. 📥 **BULK EDIT:** paste many, one per line, or upload a .txt file.

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

📍 **WHERE TO LOOK.** A city name or a German postcode — 'Hamburg', '80331', 'Köln-Ehrenfeld'. 🧠 The site resolves the name itself; pair it with 📏 Radius to widen the circle. 💡 **TIP:** empty means all of Germany.

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

📏 **HOW FAR AROUND THE LOCATION TO LOOK**, in kilometres. 0 uses the location's own area; 50 pulls in the whole commuter belt. ⚠️ Needs 📍 Location to do anything.

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

💵 **CHEAPEST ASKING PRICE TO INCLUDE**, in whole euros. 0 means no lower bound. ⚠️ A price band drops ads with no fixed price — giveaways and 'on request' ads — because the site filters on the price field itself.

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

💰 **MOST EXPENSIVE ASKING PRICE TO INCLUDE**, in whole euros. 0 means no upper bound. 💡 **TIP:** narrow bands are how you walk a big category — €0-100, €100-250, €250-500 — and merge.

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

🚚 **ONLY ADS THAT CAN BE POSTED TO YOU.** Sellers who ship can sell to anywhere in Germany, so distance stops mattering. 🤝 Leave it off to include collection-only ads — pair those with a radius for genuinely local stock.

## `adUrls` (type: `array`):

📄 **USED BY THE LISTING DETAIL OPERATION.** Which ads to open. ✅ **SUPPORTED:** the full ad address, or the bare ad ID — the number in the address — on its own. 📥 **BULK EDIT:** paste many, one per line, or upload a .txt file. Every search row this actor returns carries its ad ID, so feeding them back here is copy-paste.

## `sellerIds` (type: `array`):

🏪 **USED BY THE SELLER LISTINGS OPERATION.** Whose ads to pull. ✅ **SUPPORTED:** the seller's list address from any of their ads (kleinanzeigen.de/s-bestandsliste.html?userId=…), or the bare numeric seller ID. 💡 **TIP:** every detail row carries 👤 Seller ID — feed those straight back in here to expand a seller you found in a search.

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

🔢 **HOW MANY ADS TO RETURN**, across everything the run touches. 📦 Searches page 27 ads at a time, so the run finishes on the page that crosses your number. ⚠️ Very broad sweeps (all of Germany, no keyword) are cheaper split into narrower keywords, price bands or city rings.

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

📄 **OPEN EACH AD'S OWN PAGE** for the fields a search result cannot carry: the untruncated description, the complete photo gallery, ✨ the condition and every attribute the seller filled in, 🗂️ the category name, 🕒 the exact posting date and 🔗 the seller's public profile. 💰 **COSTS EXTRA:** one additional request per ad, billed as one Listing Detail event on top of the listing row. Leave it off and you pay for listing rows only.

## Actor input object example

```json
{
  "operation": "search",
  "keyword": "fahrrad",
  "searchUrls": [
    "https://www.kleinanzeigen.de/s-berlin/fahrrad/k0l3331"
  ],
  "location": "Berlin",
  "radiusKm": 0,
  "minPrice": 0,
  "maxPrice": 0,
  "shippingOnly": false,
  "adUrls": [
    "https://www.kleinanzeigen.de/s-anzeige/pegasus-damenfahrrad-28-zoll-50cm-rahmenhoehe/3499520216-217-9632"
  ],
  "sellerIds": [
    "https://www.kleinanzeigen.de/s-bestandsliste.html?userId=79594745"
  ],
  "maxResults": 100,
  "includeDetails": false
}
```

# Actor output Schema

## `kleinanzeigenListings` (type: `string`):

Every listing this run returned.

## `scrapingSummary` (type: `string`):

HTML summary showing successful and failed results with key metrics

# 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 = {
    "operation": "search",
    "keyword": "fahrrad",
    "searchUrls": [],
    "location": "Berlin",
    "radiusKm": 0,
    "minPrice": 0,
    "maxPrice": 0,
    "shippingOnly": false,
    "adUrls": [],
    "sellerIds": [],
    "maxResults": 100,
    "includeDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/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 = {
    "operation": "search",
    "keyword": "fahrrad",
    "searchUrls": [],
    "location": "Berlin",
    "radiusKm": 0,
    "minPrice": 0,
    "maxPrice": 0,
    "shippingOnly": False,
    "adUrls": [],
    "sellerIds": [],
    "maxResults": 100,
    "includeDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/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 '{
  "operation": "search",
  "keyword": "fahrrad",
  "searchUrls": [],
  "location": "Berlin",
  "radiusKm": 0,
  "minPrice": 0,
  "maxPrice": 0,
  "shippingOnly": false,
  "adUrls": [],
  "sellerIds": [],
  "maxResults": 100,
  "includeDetails": false
}' |
apify call sian.agency/kleinanzeigen-scraper --silent --output-dataset

```

## MCP server setup

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