# Kleinanzeigen Scraper (`lergassy/kleinanzeigen-scraper`) Actor

Scrape Kleinanzeigen.de listings by keyword, location, category or any search URL: title, price as a number, VB / Festpreis / zu verschenken, postcode and coordinates, posting date, full description, attributes, seller type and photos. Export JSON/CSV, use the API, schedule new-ads feeds.

- **URL**: https://apify.com/lergassy/kleinanzeigen-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** E-commerce, Real estate, Lead generation
- **Stats:** 6 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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?

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

### What is Kleinanzeigen Scraper?

**Kleinanzeigen Scraper** extracts listings from [kleinanzeigen.de](https://www.kleinanzeigen.de) — Germany's biggest classifieds site, formerly eBay Kleinanzeigen. Type a keyword and a city, pick a category, or paste any Kleinanzeigen search URL, and get every ad as a clean row: title, **price as a number**, price type (VB / Festpreis / zu verschenken), postcode, city and coordinates, posting date, full description, all attributes (Zustand, Wohnfläche, Kilometerstand…), seller type and name, and all photos.

- **Any search works** — keywords, location + radius, category, price range, private or commercial sellers, offers or wanted ads, or a URL copied from the site with all its filters.
- **Full ad pages included** — description, attributes, features, seller box and photo gallery are part of the base price, not an add-on.
- **Clean numbers** — `"1.280 € VB"` becomes `price: 1280`, `priceType: "negotiable"`; dates become ISO.
- **Fast and cheap** — 30 listings with full ad pages in about 5 seconds; no login, no cookies, no browser.
- **Monitoring mode** — schedule it and get only ads you have not seen yet.

### What data can it extract?

| Field | Example | Notes |
|---|---|---|
| `title`, `url`, `id` | Apple iPhone 15, 128 GB, blau | Anzeigen-ID and link |
| `adType` | offer | offer (Angebot) or wanted (Gesuch) |
| `price`, `priceText`, `priceType` | 450, "450 € VB", negotiable | fixed / negotiable / free / swap / on-request |
| `oldPrice` | 500 | when the seller lowered the price |
| `location`, `zip`, `city`, `district`, `region` | 12105, Berlin, Tempelhof, Berlin | from the ad page |
| `latitude`, `longitude`, `street` | 52.452, 13.369 | street only when the seller publishes it |
| `postedAt` | 2026-10-22T16:49:00+02:00 | date + time for today/yesterday, date otherwise |
| `description` | full text, line breaks kept | |
| `attributes` | `{"Zustand": "Sehr Gut", "Wohnfläche": "70 m²"}` | every attribute of the category |
| `features` | \["Einbauküche", "Balkon"] | Ausstattung checklist (flats, cars) |
| `highlights` | \["148.667 km", "EZ 10/2015"] | key facts from the result list |
| `categoryId`, `categoryPath` | 173, \["Elektronik", "Smartphones"] | |
| `sellerType`, `sellerName`, `sellerShopUrl` | private, O.T | PRO shop link for dealers |
| `seller` | memberSince, rating, badges, activeAds, userId, profileUrl, phone | phone only for commercial sellers that show it in full |
| `images`, `imageCount` | large photo URLs | |
| `shippingAvailable`, `shippingText`, `buyNowAvailable` | false, "Nur Abholung" | |
| `isTopAd`, `hasVideo` | true | paid top placements are flagged |
| `searchQuery`, `searchUrl`, `position`, `scrapedAt` | | where and when the row was found |

### How much does it cost to scrape Kleinanzeigen?

Pay per result, nothing else: **$0.00105 per listing** on the Free plan (about **950 listings per $1**), $0.00095 on Bronze, $0.00085 on Silver and $0.00075 on Gold and above. There is no start fee and the full ad page is included. Rows that explain an empty search, an unknown location or a deleted ad are free.

On Apify's free plan you get $5 of credit every month — enough for roughly **4,700 Kleinanzeigen listings** with full details. Set **Max cost per run** and the Actor stops cleanly at your budget, with every written row paid for.

### How to scrape Kleinanzeigen

1. Click **Try for free** and open the Input tab.
2. Enter one or more **search keywords** (e.g. `iphone 15`) and a **location** (`Berlin`, `München`, `10115`) — or paste Kleinanzeigen URLs.
3. Optionally pick a category, a radius, a price range, a seller type or the ad type (offers by default, wanted ads, or both).
4. Set **Max listings per search** and click **Start**.
5. Download the results as JSON, CSV, Excel or HTML, or read them through the API.

### ⬇️ Input

```json
{
    "searchQueries": ["iphone 15"],
    "location": "Berlin",
    "radius": 10,
    "category": "Smartphones",
    "minPrice": 200,
    "maxPrice": 600,
    "sellerType": "private",
    "adType": "offers",
    "maxItems": 100,
    "includeDetails": true
}
```

Or start from URLs copied from the site — every filter in the URL is kept:

```json
{
    "startUrls": [{ "url": "https://www.kleinanzeigen.de/s-wohnung-mieten/berlin/c203l3331" }],
    "maxItems": 200
}
```

`category` takes a German name (`Mietwohnungen`, `Autos`, `Fahrräder & Zubehör`), a common English name (`apartments for rent`, `cars`, `bikes`, `phones`) or the numeric id from a category URL (`…/c216` → `216`). Category + location without a keyword lists everything in that category.

### ⬆️ Output

A real row (description and photos shortened):

```json
{
    "type": "listing",
    "id": "3548712567",
    "url": "https://www.kleinanzeigen.de/s-anzeige/tausche-iphone-15-pro-black-128-gb-gegen-iphone-17-pro/3548712567-173-3408",
    "title": "Tausche iPhone 15 Pro Black 128 GB gegen iPhone 17 Pro",
    "price": 1,
    "priceText": "1 € VB",
    "priceType": "negotiable",
    "currency": "EUR",
    "location": "12105 Berlin - Tempelhof",
    "zip": "12105",
    "city": "Berlin",
    "district": "Tempelhof",
    "region": "Berlin",
    "latitude": 52.45217514038086,
    "longitude": 13.369030952453613,
    "postedAt": "2026-10-22T16:49:00+02:00",
    "description": "Ich biete mein iPhone 15 Pro in Black mit 128 GB Speicher zum Tausch gegen ein iPhone 17 Pro in neuwertigem Zustand an.\nZustand und Details:\n* Gekauft im Januar…",
    "attributes": { "Marke": "Apple", "Modell": "iPhone 15 Pro", "Farbe": "Schwarz", "Speicher (GB)": "128 GB", "Zustand": "Sehr Gut", "Akkuzustand": "Neu (100%)" },
    "categoryId": 173,
    "categoryPath": ["Elektronik", "Smartphones"],
    "sellerType": "private",
    "sellerName": "O.T",
    "seller": { "name": "O.T", "type": "private", "memberSince": "2024-05-26", "rating": "TOP Zufriedenheit", "activeAds": 6, "userId": "141190013", "profileUrl": "https://www.kleinanzeigen.de/s-bestandsliste.html?userId=141190013" },
    "images": ["https://img.kleinanzeigen.de/api/v1/prod-ads/images/52/52153862-732e-44f5-b1c7-4c1d7731740d?rule=$_59.AUTO"],
    "imageCount": 8,
    "shippingAvailable": false,
    "shippingText": "Nur Abholung",
    "searchQuery": "iphone 15",
    "searchUrl": "https://www.kleinanzeigen.de/s-berlin/iphone-15/k0l3331",
    "position": 3,
    "scrapedAt": "2026-10-22T15:04:59.030Z"
}
```

A flat for rent carries its own attributes, e.g. `"Wohnfläche": "55,25 m²"`, `"Warmmiete": "1.713 €"`, `"Kaution / Genoss.-Anteile": "4.475 €"` and `features: ["Terrasse", "Einbauküche", "Aufzug", "Keller"]`. Empty fields are left out of a row instead of being `null`.

### Use cases

#### Resellers and price research

Track what used iPhones, bikes or furniture really sell for in each city. `price` is a number, so averages and price-per-model charts take one formula.

#### Real estate

Collect every flat for rent or sale in a city with Wohnfläche, Zimmer, Warmmiete, Kaution, address and coordinates — and tell private landlords from agencies with `sellerType`.

#### Car dealers

Watch the Autos category with Kilometerstand, Erstzulassung, Leistung and Ausstattung, filter by price and by private sellers only.

#### Lead generation

List commercial sellers (`sellerType: commercial`) with shop links, member-since dates and the business phone where the site shows it.

#### AI agents and automations

One call, a list of keywords, a predictable JSON schema. The Actor works through the Apify MCP server, so Claude, ChatGPT or any agent can search Kleinanzeigen on demand.

### Integrations

- **API** — start runs and read datasets over the [Apify API](https://docs.apify.com/api/v2); clients for **Python** (`apify-client`) and **JavaScript** (`apify-client`).
- **No-code** — Make, n8n, Zapier, Google Sheets, Slack, webhooks.
- **Schedules** — run hourly or daily; with **Only new listings** set, each run delivers only ads you have not received before.
- **MCP** — use the Actor as a tool through `mcp.apify.com`.

### Migrating from another Kleinanzeigen scraper?

| Other scrapers | This Actor |
|---|---|
| `startUrls`, `searchUrl` | `startUrls` |
| `searchQueries`, `searchKeywords` | `searchQueries` |
| `location`, `searchLocations` | `location` |
| `radiusKm`, `searchRadius`, `radius` | `radius` |
| `category`, `searchCategoryId`, `categories` | `category` |
| `minPrice` / `maxPrice` | `minPrice` / `maxPrice` |
| `sellerType`, `posterType` | `sellerType` (`any`, `private`, `commercial`) |
| `offerType`, `adType` | `adType` (`offers`, `wanted`, `all`) |
| `maxItems`, `maxResults`, `maxResultsPerSearch` | `maxItems` (per search) |
| `includeListingDetails` | `includeDetails` (on by default, no extra charge) |
| `monitoringMode`, `monitorMode` | `onlyNewRowsStore` |

### Troubleshooting

- **A free row says the location was not found** — use a German city, district or a 5-digit postcode, e.g. `Berlin`, `Köln`, `80331`.
- **Fewer listings than on the site** — Kleinanzeigen itself shows at most 1,250 ads (50 pages) per search. Split a big search by category, location, radius or price range.
- **A row has `detailsUnavailable: true`** — the ad page could not be opened; the row still has the result-list data.
- **An ad link returns a free "no longer online" row** — the ad was sold, deleted or expired.

### ❓ FAQ

#### Is it legal to scrape Kleinanzeigen?

The Actor reads only public pages that anyone can open without an account. Personal data such as names and phone numbers is protected by the GDPR — collect it only with a legitimate reason and handle it accordingly. If unsure, consult a lawyer.

#### Do I need a Kleinanzeigen account or proxies?

No. The Actor needs no login. It connects directly and switches to German residential addresses by itself only for pages the site refuses.

#### Does it get "Gesuch" (wanted) ads and top ads?

By default you get offers only. Set **Ad type** to `wanted` for Gesuche (people looking to buy — useful for resellers) or `all` for both; every row says which it is in `adType`. Paid top ads are included and flagged with `isTopAd`.

#### How fresh is the data?

Every run reads the live site. Results are sorted newest first, as on Kleinanzeigen.

#### Can I get only new ads every day?

Yes — set **Only new listings — memory name** and schedule the Actor. Ads delivered before are skipped and not charged.

### Your feedback

Something missing or wrong? Open an issue on the Actor's **Issues** tab — we read and fix them quickly.

### You might also like

| Actor | What it does |
|---|---|
| [MercadoLibre Products Scraper](https://apify.com/lergassy/mercadolibre-products-scraper) | Products, prices and sellers from MercadoLibre |
| [Shopee Scraper](https://apify.com/lergassy/shopee-scraper) | Shopee products, prices and shops |
| [Airbnb Listings Scraper](https://apify.com/lergassy/airbnb-listings-scraper) | Airbnb stays with prices, ratings and locations |

# Actor input Schema

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

Give this or <code>startUrls</code>. One or more keywords, searched one after another on Kleinanzeigen — the same words you would type into the search box, e.g. <code>iphone 15</code>, <code>e-bike</code>, <code>2 zimmer wohnung</code>. Combine with <b>Location</b>, <b>Category</b>, price and seller filters below.

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

German city, district or 5-digit postcode the keyword searches are limited to, e.g. <code>Berlin</code>, <code>München</code>, <code>10115</code>. Leave empty to search all of Germany. Used with keywords or a category (start URLs already carry their own location).

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

Also include listings up to this many kilometres around the location. Kleinanzeigen allows 5, 10, 20, 30, 50, 100, 150 or 200 km — other numbers are rounded to the nearest. Leave empty for the location itself.

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

Limit the search to one Kleinanzeigen category: German name (<code>Fahrräder & Zubehör</code>, <code>Mietwohnungen</code>, <code>Autos</code>), a common English name (<code>bikes</code>, <code>apartments for rent</code>, <code>cars</code>, <code>phones</code>) or the numeric id from a category URL (<code>…/c216</code> → <code>216</code>). Works alone too: category + location lists everything in it.

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

Give this or <code>searchQueries</code>. Search, category or ad links copied from kleinanzeigen.de — every filter you set on the site (category, location, radius, price, condition, sorting) is kept, e.g. <code>https://www.kleinanzeigen.de/s-wohnung-mieten/berlin/c203l3331</code>. Ad links (<code>/s-anzeige/…</code>) return that one ad.

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

Only listings priced at least this many euros. Applied by Kleinanzeigen itself and checked again on every row. Works with keywords and start URLs.

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

Only listings priced at most this many euros. Applied by Kleinanzeigen itself and checked again on every row.

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

<b>Private</b> = private individuals only (Privat), <b>Commercial</b> = dealers, agencies and shops only (Gewerblich), <b>Any</b> = both.

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

<b>Offers</b> (default) = items for sale or rent (Angebote). <b>Wanted</b> = people looking to buy (Gesuche, e.g. "Suche iPhone"). <b>All</b> = both. A start URL that already contains <code>anzeige:angebote</code> or <code>anzeige:gesuche</code> keeps its own choice.

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

Maximum listings to return for each keyword or start URL. Kleinanzeigen itself shows at most 1,250 listings (50 pages) per search — split big searches by category, location or price to get more.

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

On (default): each listing also gets the full description, all attributes (e.g. Wohnfläche, Kilometerstand, Zustand), features, seller name / type / member since / rating, all photos, coordinates and shipping info. Included in the price. Off: only what the result list shows (title, price, location, date, snippet, first photo) — about 3× faster.

## `onlyNewRowsStore` (type: `string`):

Give this run a name — <code>my-berlin-flats</code> — and the Actor remembers every listing it delivered under that name. Every later run with the same name writes and charges <b>only listings you have not received before</b>. Schedule the Actor (e.g. hourly) to get a feed of new ads. Leave empty to get everything found, every time.

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

How many ad pages are opened at the same time. The default is fast and polite; lower it if you see errors.

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

Leave empty: the Actor connects directly and switches to German residential addresses by itself only for pages Kleinanzeigen refuses. Set a proxy here only if you must use your own.

## Actor input object example

```json
{
  "searchQueries": [
    "iphone 15"
  ],
  "location": "Berlin",
  "sellerType": "any",
  "adType": "offers",
  "maxItems": 30,
  "includeDetails": true,
  "maxConcurrency": 8
}
```

# Actor output Schema

## `listings` (type: `string`):

One row per Kleinanzeigen ad: title, price as a number, price type, location with postcode and coordinates, posting date, description, attributes, seller and photos. Free notice rows explain empty searches.

## `runSummary` (type: `string`):

Counters for the run: searches, pages, listings, ad pages opened, duplicates skipped, filtered rows and connection statistics.

# 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": [
        "iphone 15"
    ],
    "location": "Berlin",
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/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": ["iphone 15"],
    "location": "Berlin",
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/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": [
    "iphone 15"
  ],
  "location": "Berlin",
  "maxItems": 30
}' |
apify call lergassy/kleinanzeigen-scraper --silent --output-dataset

```

## MCP server setup

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