# AutoScout24 Scraper: Car Prices, Price Drops & Market Stats (`datasmithlab/autoscout24-scraper`) Actor

Export AutoScout24 car listings from 8 EU countries by make and model, past the 4,000-result limit: price, mileage, year, fuel, gearbox, power, price rating, dealer. Track new cars, price drops and removed ads; get median prices by model and year.

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

## Pricing

from $0.36 / 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

## AutoScout24 Scraper: Car Prices, Price Drops & Market Stats

Export car listings from [AutoScout24](https://www.autoscout24.de) by **make and model** in **8 EU countries** (Germany, Austria, Italy, France, Netherlands, Belgium, Spain, Luxembourg). Every row comes with price, mileage, first registration, fuel, gearbox, power in kW and hp, engine size, consumption, CO₂, **AutoScout24's price rating** (top / good / fair price...), condition, city and the dealer.

AutoScout24 shows at most **4,000 cars per search** (200 pages). Type `volkswagen/golf` and the Actor checks the count. If there are more, it reads the search **in price bands**, so you get the whole market instead of the first 4,000.

Two things you won't get from a plain scraper:

- **Monitoring.** Schedule it and every later run returns only what changed: `NEW` cars, `PRICE_DROP` and `PRICE_UP` with the old price and the % change, and `REMOVED` ads. Unchanged cars are not returned and **not charged**.
- **Market summary by model and year.** One row per country, make, model and first-registration year: listings, median and quartile price, median mileage, median hp, **price per 1,000 km**, dealer share and the share AutoScout24 rates as a good or top price. Ready for residual-value and pricing work.

No login, no browser. Phone numbers, contact-person names and private sellers' identities are **not** collected. Only search result pages are read; individual ad pages are never opened.

### What you get

- **Price.** `price: 18990` (EUR), `priceLabel` (`top-price`, `good-price`, `fair-price`, `somewhat-expensive`...), `previousPriceOnSite` when AutoScout24 shows a crossed-out old price.
- **The car.** `make`, `model`, `modelVariant`, `version`, `title`, `mileageKm`, `firstRegistration` (`2019-06`), `year`, `condition` (`used`, `new`, `demo`...), `fuel`, `transmission`, `powerKw`, `powerHp`, `engineCcm`, `fuelConsumption`, `co2Emission`, `isDamaged`.
- **Where.** `country`, `zip`, `city`.
- **Seller.** `sellerType` (`Dealer` / `Private`). For dealers: `dealerName`, `dealerId`, `dealerStreet`, `dealerRating`, `dealerRatingCount`, `dealerUrl`.
- `url` of the ad, `imageUrl`, `photoCount`.
- **Reports** in the run's key-value store: `SEARCHES` (one line per search and price band: cars available, pages read, status), `MARKET_SUMMARY` and `HEALTH`.

### How to search

| You want | Set |
|---|---|
| All BMW 3 Series in Germany | **Make / model** `bmw/3er` |
| A whole make | `audi` |
| The same model in Austria and Italy too | **Countries** `Germany`, `Austria`, `Italy` |
| Diesel automatics from 2018, under 100,000 km, under €25,000 | **Fuel** `Diesel`, **Gearbox** `Automatic`, **First registration from** `2018`, **Mileage to** `100000`, **Price to** `25000` |
| Only dealers (or only private sellers) | **Seller** |
| A daily new-car / price-drop feed | **Only new or changed listings** on, schedule the Actor daily |
| Median prices per model year | **Market summary by model and year** on |
| A search you already have open | paste it in **AutoScout24 search URLs** |

The make/model is written as in AutoScout24 links (`https://www.autoscout24.de/lst/`**`mercedes-benz/c-klasse`**). Unknown makes or models are reported in `SEARCHES` and are not charged.

### Output example

```json
{
  "recordType": "listing",
  "id": "autoscout24:657ea487-75f9-46a8-a28e-51ac463d30fd",
  "title": "BMW 3er d Touring",
  "make": "BMW",
  "model": "3er",
  "modelVariant": "320",
  "price": 10999,
  "currency": "EUR",
  "priceLabel": "top-price",
  "mileageKm": 155932,
  "firstRegistration": "2016-06",
  "year": 2016,
  "condition": "used",
  "fuel": "Diesel",
  "transmission": "Automatik",
  "powerKw": 140,
  "powerHp": 190,
  "engineCcm": 1995,
  "country": "DE",
  "zip": "36043",
  "city": "Fulda",
  "sellerType": "Dealer",
  "dealerName": "Autodeal24 / KFZ Vermittlungsagentur",
  "url": "https://www.autoscout24.de/angebote/bmw-3er-...-657ea487-75f9-46a8-a28e-51ac463d30fd"
}
```

In monitoring mode rows also carry `changeType`, `previousPrice`, `priceChange`, `priceChangePct` and `firstSeenAt`.

Market summary row:

```json
{
  "recordType": "marketSummary",
  "country": "AT", "make": "Volkswagen", "model": "Golf", "year": 2018,
  "listings": 28, "medianPrice": 13995, "p25Price": 11990, "p75Price": 17567.5,
  "minPrice": 7999, "maxPrice": 19990, "medianMileageKm": 154800, "medianPowerHp": 116,
  "medianPricePer1000Km": 91.21, "dealerShare": 0.3929, "goodPriceShare": 0.3214, "priceDropOnSiteCount": 0
}
```

### Pricing

Pay per event: a small start fee, then per listing row and per market summary row. Filtered-out cars and, in monitoring mode, unchanged cars are free. Set **Max listings** to cap the cost.

### Good to know

- **Cars without a price** ("price on request") are not included when a search is split into price bands. `HEALTH.splitCoverage` shows how much of the original count the bands covered.
- **REMOVED** is only reported when every search was read completely in this run and the previous one, and never when more than half of the remembered cars vanish at once (that is far more likely a site change than a real sell-out).
- Requests go out without a proxy. If AutoScout24 blocks them, the Actor retries through a residential proxy (at most 3 new IPs) and then stops and says so. It never tries to solve captchas.
- Use the same settings for scheduled runs: monitoring memory is kept per set of searches and filters.

### FAQ

**Why not every field from the ad page (equipment list, description)?** AutoScout24's robots.txt does not allow automated access to ad pages, so the Actor only reads search results. You still get the `url` of each ad.

**Other countries' websites?** All 8 markets are searched through autoscout24.de with AutoScout24's own country filter, so model names are the German ones (`3er`, `c-klasse`, `golf`).

**Is this affiliated with AutoScout24?** No. It reads public search pages at a polite pace and identifies itself honestly.

# Actor input Schema

## `searches` (type: `array`):

One per line, as in AutoScout24 links: 'bmw/3er', 'volkswagen/golf', 'mercedes-benz/c-klasse', or just a make ('audi'). 'BMW 3er' also works (first word = make). Searches above AutoScout24's 4,000-result limit are split by price automatically.

## `countries` (type: `array`):

Each make/model is searched once per country. Default: Germany.

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

Or paste autoscout24.de search pages such as https://www.autoscout24.de/lst/bmw/3er?fregfrom=2018. Price, year, mileage, power, fuel, gearbox, seller, condition, body and country settings in the URL are kept; other settings are ignored.

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

Stop after this many listing rows (you pay per row). Market summary rows are not counted.

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

Leave empty for no limit.

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

Leave empty for no limit.

## `yearFrom` (type: `integer`):

e.g. 2018.

## `yearTo` (type: `integer`):

e.g. 2022.

## `mileageFrom` (type: `integer`):

Leave empty for no limit.

## `mileageTo` (type: `integer`):

Leave empty for no limit.

## `powerFromKw` (type: `integer`):

1 kW = 1.36 hp.

## `powerToKw` (type: `integer`):

Leave empty for no limit.

## `fuel` (type: `array`):

Leave empty for all.

## `transmission` (type: `array`):

Leave empty for all.

## `condition` (type: `array`):

Leave empty for all.

## `bodyType` (type: `array`):

Leave empty for all.

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

Private sellers are listed without name or phone.

## `onlyNewOrChanged` (type: `boolean`):

For scheduled runs: each run returns only cars that are NEW, had a PRICE_DROP or PRICE_UP since the last run with the same settings, and (when every search was read completely) REMOVED cars. The first run returns everything as NEW. Unchanged cars are not returned and not charged.

## `marketSummary` (type: `boolean`):

Add one row per country, make, model and first-registration year: listings, median and quartile price, median mileage, median power, price per 1,000 km, dealer share, share rated good/top price and cars with a price drop. Uses every matching car, also unchanged ones in monitoring mode.

## `splitByPrice` (type: `boolean`):

AutoScout24 shows at most 4,000 cars per search (200 pages). When a search has more, it is read in price bands so you get all of them. Cars without a listed price are not included in price bands. Turn off to read only the first 4,000.

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

Requests go out without a proxy first. Only if AutoScout24 blocks them is this proxy used (at most 3 new IPs, then the run stops and reports it).

## Actor input object example

```json
{
  "searches": [
    "bmw/3er"
  ],
  "maxItems": 200,
  "sellerType": "all",
  "onlyNewOrChanged": false,
  "marketSummary": false,
  "splitByPrice": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DE"
  }
}
```

# Actor output Schema

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

Listings table (JSON/CSV/Excel export).

## `marketSummary` (type: `string`):

One row per country, make, model and year (when enabled).

## `allFields` (type: `string`):

Every field, including consumption, dealer rating and photo.

## `searches` (type: `string`):

For each search and price band: listings available, pages read, status.

## `health` (type: `string`):

Empty-field ratios, proxy use, failed searches, split coverage.

# 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 = {
    "searches": [
        "bmw/3er"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datasmithlab/autoscout24-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 = { "searches": ["bmw/3er"] }

# Run the Actor and wait for it to finish
run = client.actor("datasmithlab/autoscout24-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 '{
  "searches": [
    "bmw/3er"
  ]
}' |
apify call datasmithlab/autoscout24-scraper --silent --output-dataset

```

## MCP server setup

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