# Immowelt Scraper — Germany Property Data & API (`sian.agency/immowelt-property-scraper`) Actor

Immowelt.de scraper & real estate data API for Germany's #2 property portal. Sale & rent listings: price, Kaltmiete/Warmmiete, deposit, size, rooms, floor, address, GPS, photos, agent, energy class & build year — clean JSON/CSV. Fast overview or full detail. No-code, no API key.

- **URL**: https://apify.com/sian.agency/immowelt-property-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Real estate, Automation, Lead generation
- **Stats:** 16 total users, 5 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 overview 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

## Immowelt Scraper — Germany Property Data & Real Estate API 🏠

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store-Immobiliare.it Scraper](https://img.shields.io/badge/Store-Immobiliare.it%20Scraper-009246)](https://apify.com/sian.agency/immobiliare-property-scraper?fpr=sian) [![Store-Idealista Scraper](https://img.shields.io/badge/Store-Idealista%20Scraper-E60023)](https://apify.com/sian.agency/idealista-property-scraper?fpr=sian) [![Store-Zoopla Scraper](https://img.shields.io/badge/Store-Zoopla%20Scraper-8046F1)](https://apify.com/sian.agency/zoopla-property-scraper?fpr=sian)

#### 🎉 Every Immowelt.de listing as clean structured data — price, size, rooms, GPS, agent & energy class, no code

##### Built for German real-estate analysts, agents, investors and proptech teams

***

### 📋 Overview

**Turn Immowelt.de into a structured dataset in minutes** — Germany's #2 property portal (AVIV Group), scraped into clean JSON/CSV/Excel for analysts, agents, investors and proptech builders.

**Why thousands of professionals choose us:**

- ✅ **Full German RE field set**: price, Kaltmiete/Warmmiete, Kaution, Nebenkosten, size, rooms, floor, address, postal code, GPS, energy class, build year, agent — 39 fields
- ⚡ **Three modes, your call**: fast & cheap **Overview** (every search card), full **Detail** (price breakdown, GPS, Baujahr, features, agent vs. private) or **Agency listings** (one agency's whole portfolio in a city)
- 🎯 **Accurate by design**: parses Immowelt's own server-rendered data — not guesswork
- 💰 **Pay per result**: you're only charged for listings actually extracted; generous free tier to test
- 💎 **Dual-currency**: every price also in USD at the run's live FX rate, plus €/m²
- ✨ **No-code & no API key**: paste a search URL or pick a region — done

***

### ✨ Features

- 🏠 **Sale & rent listings**: mieten (rent) and kaufen (sale), Wohnung (apartment) and Haus (house)
- 🔗 **Search by URL or query**: paste any Immowelt search URL (filters preserved) or pick contract + type + region
- 💶 **Full price breakdown**: base price, Warmmiete, Nebenkosten, Kaution — and price-per-m²
- 🧭 **GPS coordinates**: exact latitude/longitude for every detail listing (map-ready)
- ⚡ **Energy & build data**: energy class (A+…H), build year (Baujahr), condition
- 🧑‍💼 **Agent intelligence**: agency name + contact, or flagged as private seller, with reference number
- 🏢 **Agency portfolios**: pull every listing an agency advertises in a city — name the agencies or auto-discover all of them
- 🖼️ **All photos**: every listing image plus a thumbnail-first field
- 💵 **Dual-currency**: EUR price + USD conversion at the live FX rate
- 🎚️ **Powerful filters**: price, rooms, living area, sort order
- 📤 **Clean exports**: JSON, CSV, Excel straight from the Apify dataset

***

### 🎬 Quick Start

Pick a mode and a search, hit run, and collect a clean dataset. Paste an Immowelt search URL or choose contract + property type + region. Results stream into the dataset as they're scraped.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~immowelt-property-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"bySearchUrl","searchUrls":["https://www.immowelt.de/suche/mieten/wohnung/deutschland/ad02de1"],"maxResults":60}'
```

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose your search

Paste an Immowelt.de search URL, or set contract (rent/sale), property type and a region.

#### Step 2: Pick a mode

**Overview** for fast, cheap listing cards — **Detail** for the full field set — or **Agency listings** to pull an agency's whole portfolio in a city (set Agency location; leave Agency names empty to auto-discover every agency there).

#### Step 3: Run & export

Hit **Start** and download your results as JSON, CSV or Excel.

**That's it! In a few minutes, you'll have:**

- A clean, structured property dataset
- Prices in EUR and USD, plus €/m²
- Map-ready GPS coordinates and agent contacts

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| scrapeMode | string | No | `overview` (fast, cheap), `detail` (full fields) or `agencyListings` (agency portfolios) |
| searchMode | string | No | `byQuery` or `bySearchUrl` |
| searchUrls | array | No | Immowelt.de search URLs (bySearchUrl mode) |
| contract | string | No | `rent` (mieten) or `sale` (kaufen) — byQuery & agencyListings modes |
| propertyType | string | No | `wohnung` or `haus` — byQuery mode |
| geoId | string | No | AVIV region token, e.g. `ad02de1` (all Germany) — byQuery mode |
| agencyLocation | string | No\* | City/region for agency portfolios, e.g. `Berlin` — \*required in agencyListings mode |
| agencyNames | array | No | Agency names (partial match ok); empty = auto-discover every agency in the location |
| maxResults | integer | No | Listing cap this run (FREE: 25, PAID: unlimited) |
| priceMin / priceMax | integer | No | Price filter (€) |
| roomsMin / roomsMax | number | No | Rooms filter |
| areaMin / areaMax | integer | No | Living-area filter (m²) |

**Example (by search URL):**

```json
{
  "scrapeMode": "detail",
  "searchMode": "bySearchUrl",
  "searchUrls": ["https://www.immowelt.de/suche/kaufen/wohnung/hamburg/ad08de1113"],
  "maxResults": 100
}
```

**Example (by query):**

```json
{
  "scrapeMode": "overview",
  "searchMode": "byQuery",
  "contract": "rent",
  "propertyType": "wohnung",
  "geoId": "ad02de1",
  "priceMax": 1500,
  "maxResults": 200
}
```

**Example (agency listings):**

```json
{
  "scrapeMode": "agencyListings",
  "agencyLocation": "Berlin",
  "agencyNames": ["Engel & Völkers"],
  "contract": "sale",
  "maxResults": 100
}
```

***

### 📤 Output

Results are saved to the Apify dataset with **39 fields** including:

| Field | Type | Description |
|-------|------|-------------|
| id | string | Immowelt Online-ID (join key) |
| url | string | Listing URL |
| propertyTitle | string | Listing title / summary |
| contract | string | rent or sale |
| property_type | string | Wohnung / Haus |
| price | number | Base price (Kaltmiete / Kaufpreis), € |
| price_usd | number | Price in USD at live FX |
| price_per_sqm | number | €/m² |
| total_rent | number | Warmmiete (detail) |
| deposit | number | Kaution (detail) |
| area_sqm | number | Living area (m²) |
| rooms | number | Rooms |
| floor | string | Floor / Geschoss |
| city / zip / district | string | Location |
| latitude / longitude | number | GPS (detail) |
| energy_class | string | Energy class A+…H |
| construction_year | number | Build year (detail) |
| agent_name | string | Agency / contact |
| is_private | boolean | Private seller flag |
| images | array | All photo URLs |

**Example:**

```json
{
  "id": "26N7GPBIXZKP",
  "url": "https://www.immowelt.de/expose/adf39d0f-3c0f-417c-a8d0-818ab59795da",
  "propertyTitle": "Wohnung zur Miete - Hamburg - 1.280 € - 2 Zimmer, 66 m², 2. Geschoss",
  "contract": "rent",
  "property_type": "Wohnung",
  "price": 1280,
  "price_usd": 1382,
  "price_per_sqm": 19,
  "area_sqm": 66,
  "rooms": 2,
  "city": "Hamburg",
  "zip": "22043",
  "latitude": 53.5689,
  "longitude": 10.0949,
  "energy_class": "A",
  "currency": "EUR"
}
```

***

### 💼 Use Cases & Examples

#### 1. Market Research & Comparables

**Analysts benchmarking rents and sale prices across German cities.**
**Input:** Search URLs per city · **Output:** Price, €/m², size, energy class · **Use:** Build price/rent comparables and heatmaps.

#### 2. Lead Generation for Agents

**Agents sourcing private-seller listings to win mandates.**
**Input:** Rent/sale by region · **Output:** Agent name, private-seller flag, reference number · **Use:** Prioritise direct-from-owner outreach.

#### 3. Investment & Rental-Yield Analysis

**Investors modelling yields on apartments.**
**Input:** By query with price/area filters · **Output:** Kaltmiete, Warmmiete, Nebenkosten, €/m² · **Use:** Compute gross/net yields at scale.

#### 4. Proptech Real-Estate Data API

**Builders feeding a German property data product.**
**Input:** Scheduled runs per region · **Output:** Structured JSON · **Use:** Power a search/valuation app without an Immowelt API key.

#### 5. Relocation & Site Selection

**Companies finding housing near new offices.**
**Input:** By query around a postal code · **Output:** Address, GPS, price, energy class · **Use:** Shortlist map-ready options.

#### 6. Energy & Sustainability Studies

**Researchers studying building efficiency.**
**Input:** Detail mode per region · **Output:** Energy class, build year, condition · **Use:** Analyse the German housing stock's efficiency.

***

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/immowelt-property-scraper').call({
  scrapeMode: 'overview',
  searchMode: 'bySearchUrl',
  searchUrls: ['https://www.immowelt.de/suche/mieten/wohnung/deutschland/ad02de1'],
  maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/immowelt-property-scraper').call(run_input={
    'scrapeMode': 'detail',
    'searchMode': 'byQuery',
    'contract': 'sale',
    'propertyType': 'wohnung',
    'geoId': 'ad02de1',
    'maxResults': 50,
})

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item)
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~immowelt-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"byQuery","contract":"rent","propertyType":"wohnung","geoId":"ad02de1"}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: Schedule or webhook
2. **HTTP Request**: Call the actor API
3. **Process**: Handle the JSON results
4. **Action**: Save to a sheet/DB, notify, or transform

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 listings** per run — full feature access, same quality
- No credit card required
- Perfect for testing and small projects

#### PAID Tier (Production Ready)

- **Unlimited** listings per run
- Faster throughput, no delays
- Pay-per-result: only charged for listings actually extracted

💰 **Fair, transparent pricing** — a cheap high-volume Overview event and a premium Detail event for the full field set. Agency-listings rows bill at the Overview rate.

🔗 [View current pricing](https://apify.com/sian.agency/immowelt-property-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: How many listings can I extract?**
A: FREE tier: 25 per run. PAID tier: unlimited.

**Q: What's the difference between Overview and Detail?**
A: Overview returns the search-card fields (price, rooms, area, address, energy, agent) fast and cheap. Detail visits each listing for the full set — price breakdown, GPS, build year, features, private/agent.

**Q: Can I get all listings from one agency?**
A: Yes — switch Scrape mode to **Agency listings**, set the city (e.g. `Berlin`) and the agency name (partial match works). Leave the names empty to auto-discover every agency advertising in that city and pull all of their portfolios.

**Q: Do I need an Immowelt account or API key?**
A: No. Just paste a search URL or pick a region.

**Q: What output formats are available?**
A: JSON, CSV, Excel — export directly from the Apify dataset.

**Q: Can I scrape a whole city or all of Germany?**
A: Yes. Note Immowelt's pager caps a single query at ~10,000 results — split large regions by price/type bands to enumerate fully.

**Q: Are prices available in USD?**
A: Yes — every row carries `price_usd` at the run's live FX rate, plus `price_per_sqm`.

**Q: Is this legal?**
A: We only extract publicly available data. See the legal note below.

***

### 🐛 Troubleshooting

**No results returned**

- Confirm the search URL opens real listings in a browser
- Widen filters (price/rooms/area) — they may be too narrow
- For byQuery, verify the `geoId` token (use bySearchUrl if unsure)

**Fewer results than expected**

- Immowelt caps a single query at ~10,000 listings; split by region/price bands
- Check `maxResults` and `maxPages`

**Missing detail-only fields (GPS, deposit, build year)**

- Those appear in **Detail** mode only — switch `scrapeMode` to `detail`

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

> *Immowelt® is a trademark of its respective owner. This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Immowelt or the AVIV Group.*

***

### 🤝 Support

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Changelog

This Actor's version history is a separate document: https://apify.com/sian.agency/immowelt-property-scraper/changelog.md

# Actor input Schema

## `scrapeMode` (type: `string`):

⚡ **OVERVIEW** — fast & cheap. Pulls ~30 fully-populated listing cards per search page (price, rooms, area, floor, address, zip, energy class, agent, photos, teaser).

🔍 **DETAIL** — full fields per listing (price breakdown: Kaltmiete/Warmmiete/Nebenkosten/Kaution, GPS coordinates, build year (Baujahr), condition, complete feature list, agent vs. private, reference number, full description, hi-res photos). Slower and priced higher per result.

🏢 **AGENCY LISTINGS** — pull an agency's full portfolio in a city. Set **Agency location** below (and optionally agency names); Contract (rent/sale) applies. Priced like Overview.

**TIP:** Start with Overview — upgrade to Detail only when you need the extra fields.

## `searchMode` (type: `string`):

🧭 How to tell the scraper what to fetch:

- **By query** — pick contract (rent/sale), property type and a geo token, then narrow with the filters below.
- **By search URL** — paste an immowelt.de search-results URL; every on-page filter in the URL is honored.

## `contract` (type: `string`):

🏷️ **Rent** (mieten) or **Sale** (kaufen). Applies to By query searches.

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

🏠 Filter By query searches by typology.

## `geoId` (type: `string`):

🗺️ The AVIV geo token immowelt.de uses for a region, e.g. `ad02de1` = all of Germany. City/region tokens come from immowelt's location autosuggest.

**TIP:** The easiest path is **Search by URL** — build any search on immowelt.de and paste the URL; then you never need this token. For By query, `ad02de1` (whole Germany) is the safe default.

## `geoPath` (type: `string`):

🏙️ Human-readable region slug for the URL, e.g. `deutschland`, `hamburg`, `berlin`. Cosmetic — the geoId above decides the actual region.

## `searchUrls` (type: `array`):

🔗 immowelt.de search-results URLs to scrape. Used when **Search by = By search URL**.

**TIP:** Build any search on immowelt.de (set your filters, sort order, region), then copy the URL from the address bar — every on-page filter is honored.

**BULK EDIT:** Click "Bulk edit" to paste many URLs, one per line.

## `agencyLocation` (type: `string`):

🏙️ German city or region to look for agencies in, e.g. `Berlin`, `München`, `Hamburg`. **Required when Scrape mode = Agency listings** (ignored otherwise). Combine with **Contract** above to pull rental or for-sale portfolios.

## `agencyNames` (type: `array`):

🏢 Agency names to pull portfolios for, e.g. `Engel & Völkers`. Case-insensitive partial match. **Leave empty to auto-discover every agency currently advertising in the location** and pull all of their listings.

**BULK EDIT:** Click "Bulk edit" to paste many names, one per line.

## `maxResults` (type: `integer`):

🔢 Maximum listings to extract this run.

- **FREE tier:** capped at 25 listings per run.
- **PAID tier:** unlimited — set as high as you need.

Note: immowelt's pager caps a single query at ~10,000 results (333 pages × 30). For more, split by region/price bands.

## `maxPages` (type: `integer`):

📄 Optional hard cap on how many search-result pages to walk per query (each page ≈ 30 listings). Leave empty to let Max results decide.

## `priceMin` (type: `integer`):

💶 Optional. Minimum price filter (By query mode). Kaltmiete for rent, Kaufpreis for sale.

## `priceMax` (type: `integer`):

💶 Optional. Maximum price filter (By query mode).

## `roomsMin` (type: `number`):

🚪 Optional. Minimum number of rooms (By query mode). Half-rooms allowed, e.g. 2.5.

## `roomsMax` (type: `number`):

🚪 Optional. Maximum number of rooms (By query mode).

## `areaMin` (type: `integer`):

📐 Optional. Minimum living area in m² (By query mode).

## `areaMax` (type: `integer`):

📐 Optional. Maximum living area in m² (By query mode).

## `sortOrder` (type: `string`):

↕️ Optional immowelt sort key, e.g. `DateDesc` (newest first). Leave empty for the site default.

## Actor input object example

```json
{
  "scrapeMode": "overview",
  "searchMode": "byQuery",
  "contract": "rent",
  "propertyType": "wohnung",
  "geoId": "ad02de1",
  "geoPath": "deutschland",
  "searchUrls": [
    "https://www.immowelt.de/suche/mieten/wohnung/deutschland/ad02de1"
  ],
  "agencyLocation": "Berlin",
  "agencyNames": [
    "Engel & Völkers"
  ],
  "maxResults": 100,
  "sortOrder": "DateDesc"
}
```

# Actor output Schema

## `results` (type: `string`):

All extracted immowelt.de listings with price, size, rooms, address, GPS, agent and energy data.

## `scrapingSummary` (type: `string`):

HTML summary of the run — mode, listings extracted, pages fetched, sample.

# 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 = {
    "geoId": "ad02de1",
    "geoPath": "deutschland"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/immowelt-property-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 = {
    "geoId": "ad02de1",
    "geoPath": "deutschland",
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/immowelt-property-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 '{
  "geoId": "ad02de1",
  "geoPath": "deutschland"
}' |
apify call sian.agency/immowelt-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sian.agency/immowelt-property-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/XgsvLJz70y7gJb3e8/builds/Fzambi9pYgXIfex05/openapi.json
