# DAHLER Real Estate Scraper (`datascrapers/dahler-scraper`) Actor

Scrapes buy and rent listings from DAHLER Immobilien (dahler.com) across Germany, Austria, and Spain. Extracts prices, property details, images, contact info, and energy certificate data via the public Solr search API and listing detail pages.

- **URL**: https://apify.com/datascrapers/dahler-scraper.md
- **Developed by:** [Data Scrapers](https://apify.com/datascrapers) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.70 / 1,000 dataset items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

**DAHLER Real Estate Scraper** creates a structured dataset of buy and rent listings collected from DAHLER (dahler.com) in Germany, Austria, and Spain. Each dataset item is one property and can include `property_id`, title, URL, purchase type, price or base rent, living area, room count, property type, city, country, coordinates, and energy class when the detail page provides it. Query the source with `region` and `marketingTypes` (`buy`, `rent`, or both). Cap the run with `maxItems`. Turn on `fetchDetails` for gallery, description, and office fields. Retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, or XML.

[![DAHLER Real Estate Scraper — input to structured data](https://raw.githubusercontent.com/faizanalii/apify-actor-assets/main/dahler-scraper/dahler-scraper-value-demo.gif)](https://apify.com/datascrapers/dahler-scraper)

### Dataset at a glance

| Property | Value |
|---|---|
| Source | dahler.com |
| Record unit | One property listing |
| Input methods | `region`, `marketingTypes`, `fetchDetails` |
| Main identifiers | `property_id`, `url` |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel, XML |
| Update model | Fresh records per Actor run |
| Pricing | $5.00 per 1,000 `dataset-item` events. Platform usage is billed separately. |

### Coverage and available records

Regions follow the Actor input, including a German state, Berlin, nationwide Germany, Austria, and Spain. `marketingTypes` selects buy, rent, or both. Overview rows come from the public search index. `fetchDetails` opens the listing page for description, images, energy data, and office contact. A detail failure keeps the overview row.

`price` is the asking purchase price for buy listings. `base_rent` is the rent figure for rent listings. `price_on_request` is true when the index marks the price as on request, and the numeric price is then empty.

### Data dictionary

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| property_id | string | no | DAHLER property id. Deduplication key. | DC-BER32752 |
| url | string | yes | Listing page | https://www.dahler.com/de/immobilie-kaufen/wohnimmobilien/dachgeschoss/berlin/dachgeschoss-highlight-mit-sonnenterrassen-am-rosenthaler-platz/DC-BER32752 |
| title | string | yes | Listing headline. Stored in German. | Dachgeschoss-Highlight mit Sonnenterrassen am Rosenthaler Platz |
| purchase_type | string | yes | BUY or RENT | BUY |
| marketing_type | string | yes | buy or rent | buy |
| price | number | yes | Asking purchase price, EUR | 995000 |
| base_rent | number | yes | Rent amount when the listing is a rental | |
| price_on_request | boolean | yes | True when no public price is posted | false |
| price_per_m2 | number | yes | Price per square meter | 7571.43 |
| living_area_m2 | number | yes | Living area | 139.27 |
| nr_rooms | number | yes | Room count | 4.0 |
| property_type | string | yes | Normalized type | OTHER |
| city | string | yes | Locality label | Berlin / Mitte |
| country | string | yes | Country label | Deutschland |
| energy_class | string | yes | Energy class when the detail page has one | |

### Example dataset record

Saved buy listing from a Berlin search. The headline on the site is German. Office contact names are omitted.

```json
{
  "property_id": "DC-BER32752",
  "url": "https://www.dahler.com/de/immobilie-kaufen/wohnimmobilien/dachgeschoss/berlin/dachgeschoss-highlight-mit-sonnenterrassen-am-rosenthaler-platz/DC-BER32752",
  "title": "Dachgeschoss-Highlight mit Sonnenterrassen am Rosenthaler Platz",
  "purchase_type": "BUY",
  "price": 995000,
  "living_area_m2": 139.27,
  "property_type": "OTHER",
  "city": "Berlin / Mitte",
  "base_rent": null,
  "energy_class": null
}
```

### Query and input reference

| Field | Type | Description |
|---|---|---|
| region | string | Search region, such as `Berlin`, `Deutschland`, or Austria. |
| marketingTypes | array | `buy`, `rent`, or both. |
| fetchDetails | boolean | Open listing pages for description, images, and office fields. |
| maxDetailConcurrency | integer | Parallel detail requests. |
| maxItems | integer | Maximum listings. |
| proxyConfiguration | object | Apify proxy settings. Residential is the intended default. |

### Retrieve the data through the API

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR-APIFY-TOKEN")
run = client.actor("datascrapers/dahler-scraper").call(run_input={
    "region": "Berlin",
    "marketingTypes": ["buy", "rent"],
    "fetchDetails": True,
    "maxItems": 5,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["property_id"], item["city"], item.get("price"))
```

### Data quality and record handling

Deduplicate on `property_id`. Prices are asking figures from DAHLER, in EUR unless the record says otherwise. `price` and `base_rent` are separate: a buy row leaves `base_rent` empty, and a rent row leaves `price` empty when the index only has rent. Coordinates come from the search index. Energy class is present only after a successful detail fetch.

### Pricing and cost examples

| Event | When it fires | Free | Bronze | Silver | Gold |
|---|---|---:|---:|---:|---:|
| dataset-item | Every listing saved | $5.00 / 1,000 | $4.90 / 1,000 | $4.80 / 1,000 | $4.70 / 1,000 |

Platinum and Diamond use the Gold rate. Platform usage, including residential proxy traffic, is billed separately.

1,000 saved listings cost $5.00 in event charges on Free and $4.70 on Gold, plus platform usage.

### Limitations and responsible data use

DAHLER can change region coverage and listing ids. Asking prices are not transaction prices. Office emails on a detail page belong to the agency. Use the dataset for market research. Do not treat a missing price as zero. `price_on_request` means the figure was withheld.

### Dataset questions

#### What is one record?

One DAHLER listing, buy or rent.

#### Which field is the key?

`property_id`.

#### Does fetchDetails change the charge?

No. The saved listing is one `dataset-item` whether or not the detail page was opened.

### Related datasets from Data Scrapers

- [CBRE Scraper](https://apify.com/datascrapers/cbre-scraper)
- [Funda Scraper](https://apify.com/datascrapers/funda-nl-scraper)
- [Boliga Scraper](https://apify.com/datascrapers/boliga-dk-scraper)
- [Crexi Scraper](https://apify.com/datascrapers/crexi-scraper)
- [Apartments Scraper](https://apify.com/datascrapers/apartments-scraper)

### Data Scrapers support

Questions about this dataset: stardustspotlight@gmail.com.

# Actor input Schema

## `region` (type: `string`):

Geographic region or country to search for listings.

## `marketingTypes` (type: `array`):

Listing types to include: buy (sale) and/or rent.

## `maxDetailConcurrency` (type: `integer`):

Maximum number of detail pages fetched in parallel (1–50).

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

Maximum number of listings to scrape (0 = unlimited).

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

Proxy settings for anti-bot protection. Residential proxies are recommended.

## Actor input object example

```json
{
  "region": "Deutschland",
  "marketingTypes": [
    "buy",
    "rent"
  ],
  "maxDetailConcurrency": 10,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset containing scraped DAHLER property listings

## `runStats` (type: `string`):

Aggregate statistics for the scrape run

# 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 = {
    "marketingTypes": [
        "buy",
        "rent"
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascrapers/dahler-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 = {
    "marketingTypes": [
        "buy",
        "rent",
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("datascrapers/dahler-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 '{
  "marketingTypes": [
    "buy",
    "rent"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call datascrapers/dahler-scraper --silent --output-dataset

```

## MCP server setup

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