# ImmoScout24 Scraper — German Rentals & Homes for Sale (`tortuga/immobilienscout24-scraper`) Actor

Scrape ImmobilienScout24 rentals and homes for sale from search URLs or city + filters: cold/warm rent or price, costs, deposit, m², rooms, floor, address, coordinates, year built, energy, realtor.

- **URL**: https://apify.com/tortuga/immobilienscout24-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 listing scrapeds

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

## ImmoScout24 Scraper — German Rentals & Homes for Sale

Scrape ImmobilienScout24 (immobilienscout24.de), Germany's largest property portal: apartments and houses for rent and for sale, from any search URL or simply from a city, district or postcode plus filters. Get cold rent and warm rent (Kaltmiete / Warmmiete) or the purchase price, additional and heating costs, deposit, living space, rooms, floor, full address with district and postcode, coordinates, year built, energy certificate, features (balcony, built-in kitchen, lift, garden, cellar), available-from date, pets policy, description, all photos and the realtor's company.

The actor reads ImmoScout24's own app data instead of the website, so it is not stopped by the "Ich bin kein Roboter" page, runs on cheap datacenter proxies and needs no browser. Every page of a search is reachable: one search can return tens of thousands of listings. You pay only for the listings you get.

### What data does ImmoScout24 Scraper extract?

From the result list (every listing):

| Field | Description |
|---|---|
| `id`, `url` | Scout-ID and the expose link `https://www.immobilienscout24.de/expose/<id>` |
| `title` | Listing headline |
| `propertyType`, `offerType`, `category` | `apartmentrent` / `apartmentbuy` / `houserent` / `housebuy` ..., `rent` or `buy`, `apartment` / `house` |
| `price`, `priceText`, `currency` | Main price as shown in the result list: cold rent for rentals, purchase price for sales (whole euros); `null` for "price on request" |
| `livingSpace`, `rooms` | Living space in m² and number of rooms (e.g. 2.5) |
| `address`, `street`, `postcode`, `city`, `district` | Address as published; `fullAddress` is `false` when the realtor shows only postcode and district |
| `latitude`, `longitude` | Map position when the realtor publishes the address |
| `energyEfficiencyClass` | A+ ... H |
| `realtorType`, `isPrivate` | `company` (agent, landlord company, developer) or `private` |
| `isProject`, `houseBuilderOffer`, `houseBuilder` | Unit of a new-build project; "Hausbau" offer from a house builder and its name |
| `published`, `publishedDate` | "vor 3 Tagen" as shown, and the date it works out to |
| `titleImage`, `images` | Photo URLs (1500x1000) |
| `search`, `scrapedAt` | The search the listing came from and the scrape time |

With **Include full listing details** (on by default) each listing is opened once and you also get:

| Field | Description |
|---|---|
| `coldRent`, `warmRent`, `additionalCosts`, `heatingCosts`, `heatingCostsIncluded` | Kaltmiete, Gesamtmiete (warm), Nebenkosten, Heizkosten, whether heating is included in the Nebenkosten |
| `deposit`, `depositText` | Kaution in euros ("3 Kaltmieten" is converted), plus the text as written |
| `purchasePrice`, `pricePerSqm`, `hausgeld`, `buyerCommission`, `commissionNote`, `rentalIncome` | Sale prices: Kaufpreis, €/m², Hausgeld, Käuferprovision, rental income of let properties |
| `propertySubtype` | Wohnungstyp / Haustyp: Etagenwohnung, Dachgeschoss, Penthouse, Doppelhaushälfte, Villa ... |
| `usableArea`, `plotArea`, `bedrooms`, `bathrooms` | Nutzfläche, Grundstück, Schlafzimmer, Badezimmer |
| `floor`, `floorText`, `buildingFloors` | Etage ("2 von 4" -> floor 2 of 4), number of floors of a house |
| `availableFrom`, `availableFromDate` | "Bezugsfrei ab" as written ("sofort", "1.11.2026") and as ISO date |
| `petsAllowed` | `yes`, `no`, `negotiable` (nach Vereinbarung) or `null` |
| `balcony`, `builtInKitchen`, `lift`, `garden`, `cellar`, `guestToilet`, `stepFreeAccess`, `wbsRequired`, `newBuilding` | Feature flags (true/false) |
| `features`, `parking`, `parkingSpaces`, `parkingPrice` | All ticked features as listed, garage / parking type, count and price |
| `constructionYear`, `lastRefurbishment`, `condition`, `interiorQuality`, `constructionPhase`, `heatingType` | Baujahr, Modernisierung, Objektzustand, Ausstattung, Bauphase, Heizungsart |
| `energyCertificate`, `energyCertificateType`, `energySource`, `energyConsumption`, `energyDemand`, `energyCertificateYear` | Energieausweis: availability, Verbrauchs- or Bedarfsausweis, Energieträger, kWh/(m²·a), year per certificate |
| `state` | Bundesland |
| `description`, `equipmentDescription`, `locationDescription`, `otherDescription` | Objektbeschreibung, Ausstattung, Lage, Sonstiges (German, as written) |
| `images`, `imageCount` | All photos |
| `realtorCompany`, `realtorContactName`, `realtorProfileUrl`, `realtorRating`, `realtorRatingCount`, `realtorVerified` | Realtor company and published contact person, ImmoScout24 profile, rating, verified badge (empty for private landlords) |
| `objectNumber`, `priceRating`, `publicationState` | Realtor's object number, ImmoScout24's price rating ("Guter Preis"), active/inactive |

### How to scrape ImmobilienScout24 listings

1. Run your search on immobilienscout24.de (location, price, rooms, area, features, sorting) and copy the address bar into **Start URLs**. Or type **Locations** ("Berlin", "Kreuzberg", "München Schwabing", "10115") and pick the **Property type** and filters.
2. Set **Max listings** (your cost cap). Leave **Include full listing details** on for costs, features and the realtor, or switch it off for a cheaper, faster run.
3. Click **Start**. Results appear in the **Dataset** tab; export them as JSON, CSV or Excel, or read them through the API.

Single listing links (`https://www.immobilienscout24.de/expose/171666598`) also work and return that listing with all details.

### Input example

```json
{
  "startUrls": [{ "url": "https://www.immobilienscout24.de/Suche/de/berlin/berlin/wohnung-mieten?price=-1500.0&livingspace=50.0-" }],
  "maxItems": 200,
  "includeDetails": true
}
```

or by location and filters:

```json
{
  "locations": ["Hamburg", "München"],
  "propertyType": "apartmentrent",
  "maxPrice": 1400,
  "priceType": "warm",
  "minRooms": 2,
  "features": ["balcony", "builtinkitchen"],
  "sort": "newest",
  "maxItems": 100
}
```

### Output example

```json
{
  "id": "171620556",
  "url": "https://www.immobilienscout24.de/expose/171620556",
  "title": "Modernisierte Altbauwohnung mit Aufzug nahe Schloss Charlottenburg!",
  "propertyType": "apartmentrent",
  "offerType": "rent",
  "category": "apartment",
  "propertySubtype": "Etagenwohnung",
  "price": 1300,
  "priceText": "1.300 €",
  "currency": "EUR",
  "coldRent": 1300,
  "warmRent": 1505,
  "additionalCosts": 205,
  "heatingCostsIncluded": true,
  "deposit": 3900,
  "pricePerSqm": 22.41,
  "livingSpace": 58,
  "rooms": 2,
  "bedrooms": 1,
  "bathrooms": 1,
  "floor": 4,
  "floorText": "4 von 5",
  "availableFrom": "1.11.2026",
  "availableFromDate": "2026-11-01",
  "petsAllowed": "negotiable",
  "balcony": true,
  "builtInKitchen": true,
  "lift": true,
  "garden": false,
  "cellar": true,
  "features": ["Balkon/Terrasse", "Keller", "Personenaufzug", "Einbauküche", "Wohnberechtigungsschein erforderlich"],
  "constructionYear": 1907,
  "lastRefurbishment": 2024,
  "condition": "Modernisiert",
  "energyCertificateType": "Verbrauchsausweis",
  "energySource": "Öl",
  "energyConsumption": 126,
  "energyEfficiencyClass": "E",
  "address": "10589 Charlottenburg, Berlin",
  "postcode": "10589",
  "city": "Berlin",
  "district": "Charlottenburg",
  "state": "Berlin",
  "fullAddress": false,
  "realtorType": "company",
  "realtorCompany": "GT24 Real Estate GmbH",
  "realtorVerified": true,
  "published": "vor 11 Stunden",
  "publishedDate": "2026-10-09",
  "description": "Diese stilvolle 2-Zimmer-Altbauwohnung befindet sich in einem repräsentativen Gebäude aus dem Jahr 1907 ...",
  "imageCount": 14,
  "detailsFetched": true
}
```

### How many listings can I get from one search?

All of them. ImmoScout24's app search has no page limit: in testing, every one of the 854 pages (100 listings each) of "all apartments for rent in Germany" (85,000+ listings) was reachable. Results are fetched 100 per request, so even large runs are quick and cheap. Several start URLs or locations can be combined in one run; duplicates are removed.

### Does it get warm rent, additional costs and the deposit?

Yes, with **Include full listing details** on (the default). The result list only shows the cold rent (or purchase price), living space and rooms; the details add warm rent, Nebenkosten, Heizkosten, deposit, floor, year built, energy certificate, all features, available-from date and pets policy. If a landlord writes "1.250 € zzgl. Heiz- und Nebenkosten" as the total rent, `warmRent` stays empty and the text is kept in `warmRentText`.

### Does it work without login or a browser?

Yes. It uses the public data ImmoScout24 serves to its mobile app, with no account, cookies or "Plus" membership. The website's "Ich bin kein Roboter" bot check does not apply to it, and the default Apify datacenter proxy is enough: in testing (4,000+ requests) no request was blocked for good. ImmoScout24 does ask busy IPs to slow down (about 3 % of requests get an HTTP 429 answer); the actor paces itself and retries those automatically, so a run with details takes about 8 minutes per 1,000 listings, and about 35 seconds without details. If a run ever reports real blocks, switch the proxy to Residential (Germany).

### Can I get the realtor's phone number or the landlord's name?

No. Phone numbers are only revealed on click on ImmoScout24 and are never collected. For realtors and housing companies the actor returns the company name, the published contact person and the ImmoScout24 profile link. For private landlords it returns no name, no street or house number, and coordinates rounded to about 1 km.

### Monitor changes on a schedule

Turn on **Only new or changed items** to watch a search: each run remembers what earlier runs returned and outputs only listings that are new or whose price (cold rent or purchase price) changed. Unchanged listings are dropped before any detail page is opened, so they are not charged. **Max listings** then sets how many of the newest listings are checked per run, so keep **Sort by** on "Newest first". Save the input as a task, add a Schedule in Apify (for example every morning), and give each watch its own **Monitoring key** if several schedules use the same search. Every output item has `changeType` (`new` or `changed`), and changed items carry `previousValues` with the old price, e.g. `{"price": 1450}`.

### Pricing

Pay per result: a small fee per listing, plus a small extra fee per listing opened when **Include full listing details** is on (see the Pricing tab). No start fee, no subscription; Apify's free plan is enough to try it. Platform usage is low: measured about $0.02 per 1,000 listings with details and under $0.01 per 1,000 without, on the default datacenter proxy.

### Integrations and API

Use the run in Zapier, Make, n8n or Google Sheets, or call it from Python/Node with the Apify client. See the **API** tab for ready-made snippets. Schedule it daily to get new flats in your area, or to track rents and asking prices by district.

### Is it legal to scrape ImmobilienScout24?

This Actor collects publicly visible listing data: properties, prices, costs, features and the advertising company's business details. It does not collect phone numbers, private landlords' names or their exact addresses, and it uses no login. You are responsible for how you use the data and for complying with ImmoScout24's terms and applicable law (including the GDPR).

### Support

Found a bug or need a field added? Open an issue in the **Issues** tab; it is usually answered within a day.

# Actor input Schema

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

ImmobilienScout24 search URLs with any filters set on the website (run the search on immobilienscout24.de and copy the address bar, e.g. https://www.immobilienscout24.de/Suche/de/berlin/berlin/wohnung-mieten?price=-1500.0\&livingspace=50.0-), radius searches, or single listing URLs (https://www.immobilienscout24.de/expose/123456789), which return that listing with full details. Leave empty if you use Locations below.

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

German cities, districts (Stadtteile) or postcodes, one per line, e.g. 'Berlin', 'Kreuzberg', 'München Schwabing', 'Hamburg', '10115'. Each is looked up with ImmoScout24's own location search and searched separately. Postcodes and streets are searched with a radius (2 km unless you set Radius).

## `propertyType` (type: `string`):

What to search for in the Locations. Start URLs keep their own type.

## `radiusKm` (type: `number`):

Search this many kilometres around each location instead of within its borders. Leave empty to search the city or district itself.

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

Minimum monthly rent (cold rent unless 'Price filter applies to' is warm rent) or minimum purchase price, in euros.

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

Maximum monthly rent (cold rent unless 'Price filter applies to' is warm rent) or maximum purchase price, in euros.

## `priceType` (type: `string`):

For rentals: whether Min/Max price filter the cold rent (Kaltmiete) or the warm rent (Warmmiete, incl. additional and heating costs).

## `minLivingSpace` (type: `integer`):

Minimum living space (Wohnfläche) in square metres.

## `maxLivingSpace` (type: `integer`):

Maximum living space (Wohnfläche) in square metres.

## `minRooms` (type: `number`):

Minimum number of rooms (Zimmer), e.g. 2 or 2.5.

## `maxRooms` (type: `number`):

Maximum number of rooms (Zimmer).

## `features` (type: `array`):

Only listings with all of these features.

## `newBuildingOnly` (type: `boolean`):

Only new-build properties.

## `petsAllowed` (type: `boolean`):

Only rentals where the landlord says pets are allowed.

## `minConstructionYear` (type: `integer`):

Only properties built in this year or later.

## `excludeSwapApartments` (type: `boolean`):

Leave out apartment-swap offers (rentals).

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

Order of the results (also used for start URLs that have no sorting of their own). 'Newest first' is the natural choice for monitoring.

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

Open each listing (one extra request) for warm rent, additional and heating costs, deposit, floor, bedrooms/bathrooms, year built, condition, energy certificate, all features, available-from date, pets, full description, all photos and the realtor's company. Charged as an extra 'detail' event. Turn off for a cheaper, faster run with result-list data only (price, m², rooms, address, coordinates, first photo).

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

Stop after this many listings in total (all searches together). Keeps cost predictable. With 'Only new or changed items' on, this is the number of newest listings checked per run.

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

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

Apify Proxy. The default datacenter proxy works for this site (the actor uses ImmoScout24's app API, not the protected website). Switch to Residential (Germany) only if runs start reporting blocks.

## Actor input object example

```json
{
  "locations": [
    "Berlin"
  ],
  "propertyType": "apartmentrent",
  "priceType": "cold",
  "newBuildingOnly": false,
  "petsAllowed": false,
  "excludeSwapApartments": false,
  "sort": "newest",
  "includeDetails": true,
  "maxItems": 100,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "locations": [
        "Berlin"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

# Run the Actor and wait for it to finish
run = client.actor("tortuga/immobilienscout24-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 '{
  "locations": [
    "Berlin"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call tortuga/immobilienscout24-scraper --silent --output-dataset

```

## MCP server setup

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