# Mobile.de Car Listings Scraper (`mina_safwat/mobile-de-scraper`) Actor

Scrapes car listings from mobile.de search and listing links: price, price rating, mileage, registration, power, fuel, seller and dealer rating, images and features.

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

## Pricing

from $0.80 / 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.

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 does Mobile.de Car Listings Scraper do?

**Mobile.de Car Listings Scraper** turns any [mobile.de](https://www.mobile.de)
search into a clean table of **vehicle listings**: **price, net price and VAT,
mobile.de's price rating** ("Good price", "Fair price"…), **first registration,
mileage, power in kW and hp, fuel, transmission, body type, colour**, the
**seller** (dealer, business or private), the **dealer's name and star rating**,
city and postcode, and every **photo**. Turn on one switch to add each car's
**equipment list, the seller's description and all specs** from its listing page.

Set your filters on mobile.de as usual, copy the results link and paste it in.
Every filter in the link is used: make, model, price, registration year,
mileage, fuel, location radius, sorting and the rest. Try it with the prefilled
search: click **Start** and the first 20 Porsche Caymans arrive in a few
seconds. Because it runs on the Apify platform, you also get API access,
scheduled runs, integrations (Google Sheets, Make, Zapier, webhooks), run
monitoring and automatic proxy retries.

### Why scrape mobile.de?

- **Car dealers and traders**: watch competitors' stock and prices, and spot
  underpriced cars the moment they are listed.
- **Price analysis and valuation**: collect asking prices with mileage, age and
  power to model what a car is worth, alongside mobile.de's own price rating.
- **Import and export**: find VAT-deductible cars (with the net price) from
  dealers across Europe.
- **Market research**: measure supply by make, model, fuel or region, and track
  how it changes with scheduled runs.
- **Lead lists**: list the dealers selling a brand in an area, with their
  ratings.

### How to scrape mobile.de listings

1. Open [suchen.mobile.de](https://suchen.mobile.de) and search with your
   filters (for example BMW 3 Series, from 2020, up to 50,000 km, within
   100 km of Berlin).
2. Copy the address of the results page. It looks like
   `https://suchen.mobile.de/fahrzeuge/search.html?…`.
3. Paste it into **mobile.de links**. Add more searches or single listing
   links, one per line.
4. Set **Max listings per search**, and turn on **Add features, description
   and full specs** if you need them.
5. Click **Start** and download the results when the run finishes.

### Input

Everything is set on the Input tab. In JSON, the input looks like this:

```json
{
    "startUrls": [
        "https://suchen.mobile.de/fahrzeuge/search.html?isSearchRequest=true&ms=20100%3B19%3B%3B&fr=2018%3A&s=Car&vc=Car",
        "https://suchen.mobile.de/fahrzeuge/details.html?id=455559893"
    ],
    "maxListings": 100,
    "includeDetails": false
}
```

| Field | What it does |
|---|---|
| `startUrls` | Search results links (`…/search.html?…`) and listing links (`…/details.html?id=…` or `…/auto-inserat/…/123456789.html`), or bare listing ids. Links without `https://` and API objects such as `{"url": "…"}` work too. |
| `maxListings` | Stops after this many listings for each search link. Default: 100. Set `0` for everything mobile.de serves, which is at most 2,000 per search. |
| `includeDetails` | Opens each listing found by a search to add `features`, `description` and `specs`. Default: off. Listing links always include them. |

**Labels in your language.** Fuel, transmission, body type, colour and the
price rating come in English by default. Add `&lang=de` (or `fr`, `it`, `es`,
`pl`, `nl`, `ro`, `ru`, `tr`, `cs`…) to a link to get them in that language.

### Output

Each vehicle becomes one row. Here is a real one, with the photo list
shortened:

```json
{
    "id": "44693283251936",
    "url": "https://suchen.mobile.de/auto-inserat/porsche-718-cayman-tallinn/44693283251936.html",
    "title": "Porsche 718 Cayman",
    "make": "Porsche",
    "model": "Cayman",
    "version": "718 Cayman",
    "price": 59000,
    "currency": "EUR",
    "netPrice": 47580.65,
    "vatRate": 24,
    "vatDeductible": true,
    "priceType": "FIXED",
    "priceRating": "GOOD_PRICE",
    "priceRatingLabel": "Good price",
    "firstRegistration": "2018-07",
    "mileageKm": 44600,
    "fuel": "Petrol",
    "powerKw": 220,
    "powerHp": 299,
    "transmission": "Automatic",
    "bodyType": "Sports Car/Coupe",
    "colour": "Yellow",
    "doors": "2/3",
    "seats": 2,
    "engineCcm": 1988,
    "emissionClass": null,
    "previousOwners": null,
    "inspectionDue": "2028-07",
    "sellerType": "dealer",
    "dealerName": "Auto 100 Premium OÜ. Porsche, Bentley and Lamborghini official dealer and service partner",
    "dealerRating": 4.7,
    "dealerRatingCount": 49,
    "city": "Tallinn",
    "postcode": "10614",
    "country": "EE",
    "imageCount": 19,
    "images": [
        "https://img.classistatic.de/api/v1/mo-prod/images/ca/ca64b5f2-a669-4a7e-bf2b-ffd0f0ae947d?rule=mo-1024.jpg",
        "https://img.classistatic.de/api/v1/mo-prod/images/49/49dea599-40fb-444c-9e97-5e924b5a5315?rule=mo-1024.jpg"
    ],
    "createdAt": "2026-09-10T13:54:52+00:00",
    "modifiedAt": "2026-10-13T16:24:02+00:00",
    "scrapedAt": "2026-10-20T14:33:08.912207+00:00"
}
```

With **Add features, description and full specs** on (and for every listing
link), the row also has:

```json
{
    "features": ["ABS", "Adaptive Cruise Control", "Adaptive lighting", "Air suspension", "Alarm system", "Alloy wheels", "…"],
    "description": "Sonderausstattung:\nAnzeigeinstrumente mit farbigem Hintergrund, Außen-/Innenspiegel mit Abblendautomatik und Regensensor, …",
    "specs": {
        "damageCondition": "Used vehicle, Accident-free",
        "modelRange": "982C",
        "trimLine": "Cayman",
        "availability": "Now",
        "envkv.energyConsumption": "6.9 l/100km",
        "…": "…"
    }
}
```

The description is in the language the seller wrote it in.

You can download the dataset in various formats such as JSON, HTML, CSV, or
Excel.

### Data fields

| Field | Type | Description |
|---|---|---|
| `id` | string | mobile.de listing id |
| `url` | string | Listing page |
| `title`, `make`, `model`, `version` | string | Ad title, make, model and the seller's version line |
| `price` | number | Asking price, gross |
| `currency` | string | Currency code, usually `EUR` |
| `netPrice`, `vatRate` | number | Price without VAT and the VAT rate in %, when VAT is deductible; otherwise `null` |
| `vatDeductible` | boolean | Whether the price includes deductible VAT |
| `priceType` | string | `FIXED` or `NEGOTIABLE` |
| `priceRating` | string | mobile.de's rating code: `VERY_GOOD_PRICE`, `GOOD_PRICE`, `REASONABLE_PRICE`, `INCREASED_PRICE`, `HIGH_PRICE` or `NO_RATING` |
| `priceRatingLabel` | string | The same rating as shown on the site, in the link's language |
| `firstRegistration` | string | Month of first registration, `YYYY-MM`; `null` for unregistered new cars |
| `mileageKm` | number | Mileage in km |
| `fuel`, `transmission`, `bodyType`, `colour` | string | As shown on the site, in the link's language |
| `powerKw`, `powerHp` | number | Engine power |
| `doors` | string | Door count as mobile.de groups it, such as `4/5` |
| `seats`, `engineCcm`, `previousOwners` | number | Seats, engine size in cm³ and number of previous owners, when given |
| `emissionClass` | string | Such as `Euro6d`, when given |
| `inspectionDue` | string | Next general inspection (HU), `YYYY-MM`, when given |
| `sellerType` | string | `dealer`, `business` or `private` |
| `dealerName` | string | Dealer or business name; `null` for private sellers |
| `dealerRating`, `dealerRatingCount` | number | Dealer's star rating (out of 5) and number of reviews, when rated |
| `city`, `postcode`, `country` | string | Where the vehicle is |
| `imageCount`, `images` | number, array | Photo count and full-size photo URLs |
| `createdAt`, `modifiedAt` | string | When the ad was created and last changed (ISO 8601, UTC) |
| `features` | array | Equipment list (details only) |
| `description` | string | Seller's description as plain text (details only) |
| `specs` | object | Every spec on the listing page, keyed by mobile.de's spec name (details only) |
| `scrapedAt` | string | When the row was saved (ISO 8601, UTC) |

Fields a seller left empty are `null`. Phone numbers and other contact
details of sellers are not collected.

### How much does it cost to scrape mobile.de?

The Actor uses **pay-per-event** pricing: you pay a small fee per listing
saved, plus a small extra per listing when details are added. See the
**Pricing** tab for the exact prices. Links that return nothing are never saved
as rows, so you are not charged for them. If you set a maximum cost for a run,
the Actor stops cleanly as soon as it is reached.

It is also fast and light on platform usage: it reads mobile.de's own data
service instead of loading web pages, so two full searches (2,363 listings in
all) finished in about 10 seconds, and 300 listings with details in about half
a minute.

### Tips for scraping mobile.de

- **Split big searches.** mobile.de serves at most 2,000 listings per search.
  For more, run several searches with price or registration bands
  (e.g. up to €10,000, €10,000–20,000, …).
- **Sort for monitoring.** Sort the search by "Newest listings first" on
  mobile.de before copying the link, schedule a daily run with a small
  `maxListings`, and you get each day's new cars. Links you copy keep their
  sorting; a link without one gets mobile.de's "Standard sorting".
- **Leave details off** unless you need equipment or descriptions: search rows
  already have price, mileage, power, seller and photos, and runs are several
  times faster without details.
- Each listing is saved only once per run, even when several searches find it.

### FAQ, disclaimers and support

**Which links work?** Search results pages (`…/search.html?…`) for cars,
motorbikes, vans and the other vehicle types, and listing pages. Brand and
model landing pages such as `www.mobile.de/auto/bmw-3er.html` are not searches:
open the search there and copy the results link instead.

**What happens to links that return nothing?** Sold listings, searches with no
results and links that are not mobile.de searches are not saved as rows.
Each one is listed with its reason in the `FAILED_INPUTS` record of the run's
key-value store, and the run's status message gives the counts. A run fails
only when every input failed because mobile.de could not be reached.

**Is it legal to scrape mobile.de?** This Actor collects only listings that
are publicly visible on mobile.de without logging in. It does not collect
seller phone numbers or messages. Listings can still contain personal data
(such as a private seller's town), so you are responsible for making sure your
use complies with mobile.de's terms and with data protection laws such as the
GDPR. If in doubt, ask a lawyer. This Actor is not affiliated with mobile.de.

**Found a problem or need a custom solution?** Open an issue on the
**Issues** tab and we will look into it. Custom scrapers and data feeds are
available on request.

# Actor input Schema

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

Search results links and listing links, one per line. For a search, set your filters on suchen.mobile.de (make, model, price, mileage, registration, fuel, location radius, sorting…) and copy the address of the results page (…/search.html?…); every filter in the link is used. For a single vehicle, paste its listing link (…/details.html?id=… or …/auto-inserat/…/123456789.html) or just its id. Add \&lang=de (or fr, it, es, pl, nl…) to a link for labels in that language; English is the default.

## `maxListings` (type: `integer`):

Stops after this many listings for each search link. Set 0 for as many as mobile.de serves: at most 2,000 per search, so split bigger searches with filters (price or registration bands). Listing links always give their one listing.

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

Opens each listing found by a search to add its equipment list (features), the seller's description and every spec on the listing page (specs). It costs one extra request per listing, so runs are slower and each listing with details is charged a little more (see the Pricing tab). Listing links always include details.

## Actor input object example

```json
{
  "startUrls": [
    "https://suchen.mobile.de/fahrzeuge/search.html?isSearchRequest=true&ms=20100%3B19%3B%3B&fr=2018%3A&s=Car&vc=Car"
  ],
  "maxListings": 20,
  "includeDetails": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://suchen.mobile.de/fahrzeuge/search.html?isSearchRequest=true&ms=20100%3B19%3B%3B&fr=2018%3A&s=Car&vc=Car"
    ],
    "maxListings": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/mobile-de-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 = {
    "startUrls": ["https://suchen.mobile.de/fahrzeuge/search.html?isSearchRequest=true&ms=20100%3B19%3B%3B&fr=2018%3A&s=Car&vc=Car"],
    "maxListings": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/mobile-de-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 '{
  "startUrls": [
    "https://suchen.mobile.de/fahrzeuge/search.html?isSearchRequest=true&ms=20100%3B19%3B%3B&fr=2018%3A&s=Car&vc=Car"
  ],
  "maxListings": 20
}' |
apify call mina_safwat/mobile-de-scraper --silent --output-dataset

```

## MCP server setup

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