# WG-Gesucht Scraper — Germany Flatshare & Rental Data (`sian.agency/wg-gesucht-property-scraper`) Actor

WG-Gesucht scraper & real estate data API for wg-gesucht.de. German flatshare rooms (WG-Zimmer), 1-room flats, apartments & houses: rent, deposit, size, WG details, district, GPS, photos — clean JSON/CSV. Fast overview or full detail. No-code, no API key needed.

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

## Pricing

from $2.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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## WG-Gesucht Scraper — German Flatshare & Rental Data API 🏠

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Idealista Scraper](https://img.shields.io/badge/Store-Idealista%20Scraper-E60023)](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) [![Immobiliare Scraper](https://img.shields.io/badge/Store-Immobiliare%20Scraper-00A599)](https://apify.com/sian.agency/immobiliare-property-scraper?fpr=sian) [![Bayut Scraper](https://img.shields.io/badge/Store-Bayut%20Scraper-93D500)](https://apify.com/sian.agency/bayut-property-scraper?fpr=sian)

#### 🎉 Turn wg-gesucht.de into a clean dataset — every flatshare room, flat & house, with rent, WG details & GPS
##### For renters, relocators, students, agents and proptech teams who need German rental data without copy-pasting

---

### 📋 Overview

**Need wg-gesucht.de data without scrolling endless pages?** — this scraper turns Germany's biggest flatshare & rental portal into a clean, structured dataset you can filter, map, and feed into any tool.

**Why renters, researchers and agencies choose us:**
- ✅ **The most complete WG-Gesucht data**: rent, deposit, total rent, room size, WG size, district, exact address, GPS coordinates, features and photos — not just a title and a price.
- ⚡ **Two speeds, one actor**: a cheap **overview** mode for sizing a whole city, and a rich **detail** mode for the listings you care about.
- 🎯 **Every German city**: search Berlin, München, Hamburg, Köln, Frankfurt by name — or paste any wg-gesucht.de search URL with your filters baked in.
- 💰 **Pay only per listing**: transparent pay-per-result pricing, no monthly subscription, no API key.
- 💎 **Map-ready & finance-ready**: real GPS lat/lng plus computed rent-per-m² and a live EUR→USD conversion on every row.
- ✨ **No code required**: run it from the Apify Console, schedule it, or call it from your own app.

---

### ✨ Features

- 🏘️ **All categories**: WG-Zimmer (flatshare rooms), 1-room flats, apartments, and houses.
- 📋 **Overview mode**: fast card-level scrape — id, title, rent, WG size, area, district, available-from, thumbnail.
- 🔎 **Detail mode**: full listing pages — deposit, total rent, GPS, floor, features, full description, exact address.
- 📍 **By city**: just type a German city name and pick a category.
- 🔗 **By search URL**: paste a wg-gesucht.de search link and keep every filter (rent band, size, short/long term, photos-only, virtual tour, sort).
- 🆔 **By listing URL/ID**: pull specific listings directly.
- 🌐 **GPS coordinates**: real latitude/longitude for mapping and proximity analysis.
- 📊 **Computed KPIs**: rent-per-m² and a live EUR→USD price on every listing.
- 📦 **Clean exports**: JSON, CSV, or Excel straight from the Apify dataset.

---

### 🎬 Quick Start

Pick a scrape mode, give it a city (or a search URL), set how many listings you want — and run. Results land in a clean dataset you can export or call via API.

```bash
curl -X POST https://api.apify.com/v2/acts/sian.agency~wg-gesucht-property-scraper/runs?token=YOUR_TOKEN \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"byCity","cities":["Berlin"],"category":"wg-zimmer","maxResults":50}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose your mode

Pick **overview** (fast, cheap, whole-city) or **detail** (rich, full listing pages).

#### Step 2: Tell it where to look

Type one or more German **cities** + a **category**, paste a **search URL**, or drop specific **listing URLs/IDs**.

#### Step 3: Run & export

Hit **Start** and watch listings stream in. Export to JSON, CSV, or Excel — or call the dataset API.

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

- A clean, deduplicated dataset of live wg-gesucht.de listings
- Rent, size, WG details, district, GPS and photos per listing
- Map-ready and spreadsheet-ready data

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| scrapeMode | string | No | `overview` (card list) or `detail` (full pages) |
| searchMode | string | No | `byCity`, `bySearchUrl`, or `byListingUrl` |
| cities | array | No | German city names (byCity) — e.g. `Berlin`, `München` |
| category | string | No | `wg-zimmer`, `1-zimmer-wohnungen`, `wohnungen`, `haeuser` |
| searchUrls | array | No | wg-gesucht.de search URLs (bySearchUrl) |
| listingUrls | array | No | Listing detail URLs or numeric IDs (byListingUrl, detail mode) |
| maxResults | integer | No | Max listings per run (FREE: 25, PAID: unlimited) |

**Example — overview by city:**

```json
{
  "scrapeMode": "overview",
  "searchMode": "byCity",
  "cities": ["Berlin", "München"],
  "category": "wg-zimmer",
  "maxResults": 100
}
```

**Example — detail by search URL:**

```json
{
  "scrapeMode": "detail",
  "searchMode": "bySearchUrl",
  "searchUrls": ["https://www.wg-gesucht.de/wg-zimmer-in-Berlin.8.0.1.0.html?rMax=600"],
  "maxResults": 40
}
```

***

### 📤 Output

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

| Field | Type | Description |
|-------|------|-------------|
| id | string | wg-gesucht listing id |
| url | string | Canonical listing URL |
| propertyTitle | string | Listing headline |
| property\_type | string | WG-Zimmer / 1-Zimmer-Wohnung / Wohnung / Haus |
| price | number | Base rent (Miete), EUR |
| total\_rent | number | Total rent (Gesamtmiete), EUR |
| deposit | number | Deposit (Kaution), EUR |
| price\_per\_sqm\_eur | number | Computed rent per m² |
| price\_usd | number | Rent in USD at the run's live FX rate |
| area\_sqm | number | Room or flat size, m² |
| rooms | number | WG size (3er WG → 3) or room count |
| address | string | Street / zip / city / district |
| city | string | City name |
| district | string | Stadtteil |
| zip | string | Postal code |
| latitude / longitude | number | GPS coordinates (detail mode) |
| available\_from | string | Frei ab — move-in date |
| features | array | möbliert, WLAN, Badewanne, … |
| images | array | Photo URL(s) |

**Example row:**

```json
{
  "id": "13616431",
  "url": "https://www.wg-gesucht.de/wg-zimmer-in-Berlin-Schoeneberg.13616431.html",
  "propertyTitle": "Wg Zimmer Schöneberg",
  "property_type": "WG-Zimmer",
  "price": 600,
  "total_rent": 600,
  "deposit": 1000,
  "price_per_sqm_eur": 35,
  "area_sqm": 17,
  "rooms": 3,
  "address": "Grazer Damm 124 12157 Berlin Schöneberg",
  "city": "Berlin",
  "district": "Schöneberg",
  "zip": "12157",
  "latitude": 52.469388,
  "longitude": 13.346557,
  "available_from": "16.06.2026",
  "features": ["möbliert", "Badewanne", "WLAN"],
  "images": ["https://img.wg-gesucht.de/media/up/..."]
}
```

***

### 💼 Use Cases & Examples

#### 1. Relocation & student housing search

**Anyone moving to a new German city who needs to compare rooms fast.**
**Input:** city + `wg-zimmer` category. **Output:** every live room with rent, size and district. **Use:** sort by rent-per-m², shortlist, and contact.

#### 2. Rental market research

**Analysts tracking rent levels across German cities.**
**Input:** multiple cities, overview mode. **Output:** a clean rent/size/district dataset. **Use:** benchmark median rents and €/m² per Stadtteil.

#### 3. Lead generation for agents & property managers

**Agents sourcing private landlords and new listings.**
**Input:** city + detail mode. **Output:** full listings with contact context and features. **Use:** build outreach lists of fresh inventory.

#### 4. Proptech & data feeds

**Product teams that need a structured WG-Gesucht feed.**
**Input:** scheduled runs via API. **Output:** JSON straight into your pipeline. **Use:** power a map, an alert, or a comparison tool.

#### 5. Investment & yield sourcing

**Investors screening rental yields by area.**
**Input:** `wohnungen` / `haeuser` categories. **Output:** rent, size, GPS, €/m². **Use:** spot under-priced areas and estimate yields.

#### 6. WG / flatshare availability monitoring

**Communities and HR/relocation teams watching for openings.**
**Input:** a saved search URL, scheduled daily. **Output:** new listings each run. **Use:** alert members the moment a room appears.

***

### 🔗 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/wg-gesucht-property-scraper').call({
  scrapeMode: 'overview',
  searchMode: 'byCity',
  cities: ['Berlin'],
  category: 'wg-zimmer',
  maxResults: 50,
});

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/wg-gesucht-property-scraper').call(
    run_input={
        'scrapeMode': 'overview',
        'searchMode': 'byCity',
        'cities': ['Berlin'],
        'category': 'wg-zimmer',
        '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~wg-gesucht-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"detail","searchMode":"byListingUrl","listingUrls":["13616431"]}'
```

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

1. **Trigger**: Schedule (daily) or webhook
2. **HTTP Request**: Call the actor API
3. **Process**: Handle the JSON dataset
4. **Action**: Save to a sheet, alert on Telegram/Slack, or sync to your DB

***

### 📊 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 searches

#### PAID Tier (Production Ready)

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

💰 **Pay-per-result pricing** — a cheap, high-volume **overview** event plus a richer **detail** event. You pick the depth, you control the cost.

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

***

### ❓ Frequently Asked Questions

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

**Q: Which cities are supported?**
A: Every city on wg-gesucht.de. Use **byCity** for Berlin, München, Hamburg, Köln and Frankfurt by name, or paste any wg-gesucht.de search URL (**bySearchUrl**) for any other city with your filters.

**Q: Why don't WG rooms show bedrooms, bathrooms or an energy class?**
A: WG-Zimmer are single shared rooms — wg-gesucht doesn't publish bedroom/bathroom counts or an Energieausweis for them. That's expected, not a gap. Flats and houses carry richer fields.

**Q: A listing ID returns nothing — why?**
A: wg-gesucht listings churn fast; old IDs are deleted ("Angebot nicht vorhanden"). Always discover fresh IDs via byCity / bySearchUrl.

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

**Q: Do I need an API key or a wg-gesucht account?**
A: No. Just run the actor.

***

### 🐛 Troubleshooting

**No results returned**

- Check the city spelling, or switch to **bySearchUrl** and paste a working wg-gesucht.de search link.
- Make sure the category matches what you expect (e.g. `wg-zimmer` for rooms).

**Fewer detail rows than overview**

- Some listings get deleted between discovery and the detail fetch; those are skipped. Re-run for the freshest set.

**Missing GPS / address**

- GPS and the exact street appear in **detail** mode. Some private offers withhold the street; district + zip are still returned.

***

### ⚖️ 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/).

> WG-Gesucht and wg-gesucht.de are trademarks of their respective owners. This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by WG-Gesucht.

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check the [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)**

# Actor input Schema

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

⚡ **Choose the depth of data per listing.**

- **overview** — fast card-level scrape from the search result list (id, title, rent, WG size, area, district, available-from, thumbnail). Cheapest, highest volume.
- **detail** — opens every listing's full page for richer fields (deposit, total rent, GPS coordinates, floor, features, full description, exact address).

💡 **TIP:** Start with overview to size a city, then switch to detail for the listings you care about.

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

🔍 **How to tell the scraper which listings to fetch.**

- **byCity** — give one or more German city names + a category.
- **bySearchUrl** — paste a wg-gesucht.de search URL (all your filters preserved).
- **byListingUrl** — give specific listing URLs or IDs (detail mode only).

## `cities` (type: `array`):

📍 **CITY SEARCH:** German city names to scrape, e.g. `Berlin`, `München`, `Hamburg`, `Köln`, `Frankfurt`.

💡 **TIP:** Add several cities to compare markets in one run.

⚠️ For a city outside this common set, use **By search URL** mode and paste a wg-gesucht.de search link instead.

Used when **Search mode = byCity**.

## `category` (type: `string`):

🏘️ **What kind of listing to search.**

- **wg-zimmer** — flatshare rooms (WG-Zimmer) — the classic wg-gesucht use case.
- **1-zimmer-wohnungen** — 1-room flats.
- **wohnungen** — apartments.
- **haeuser** — houses.

Used with **byCity** search. (WG rooms have no bedroom/bathroom/energy fields — that is normal for shared rooms.)

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

🔗 **SEARCH-URL MODE:** Paste wg-gesucht.de search URLs — every filter you set on the site (rent band, size, short/long term, photos-only, virtual tour, sort) is preserved.

✅ **SUPPORTED:** the standard search path, e.g. `https://www.wg-gesucht.de/wg-zimmer-in-Berlin.8.0.1.0.html?rMax=600`.

💡 **BULK EDIT:** Click "Bulk edit" to paste one URL per line.

Used when **Search mode = bySearchUrl**.

## `listingUrls` (type: `array`):

🆔 **DETAIL-BY-URL MODE:** Specific listing detail URLs (`https://www.wg-gesucht.de/wg-zimmer-in-Berlin-Schoeneberg.13616431.html`) or bare numeric IDs (`13616431`).

⚠️ wg-gesucht listings churn fast — old IDs return "Angebot nicht vorhanden" (deleted). Discover fresh IDs via byCity / bySearchUrl.

💡 **BULK EDIT:** Click "Bulk edit" to paste one per line.

Used when **Search mode = byListingUrl** (requires **Scrape mode = detail**).

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

🔢 **Maximum listings per run.**

- **FREE users:** capped at 25 listings/run.
- **PAID users:** unlimited.

The scraper stops paginating once this many listings are collected.

## Actor input object example

```json
{
  "scrapeMode": "overview",
  "searchMode": "byCity",
  "cities": [
    "Frankfurt"
  ],
  "category": "wg-zimmer",
  "searchUrls": [
    "https://www.wg-gesucht.de/wg-zimmer-in-Berlin.8.0.1.0.html"
  ],
  "listingUrls": [
    "13616431"
  ],
  "maxResults": 100
}
```

# Actor output Schema

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

Scraped flatshare & rental listings — rent, size, WG details, location, GPS, photos and more.

# 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 = {
    "cities": [
        "Frankfurt"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/wg-gesucht-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 = { "cities": ["Frankfurt"] }

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/wg-gesucht-property-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "cities": [
    "Frankfurt"
  ]
}' |
apify call sian.agency/wg-gesucht-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=sian.agency/wg-gesucht-property-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "WG-Gesucht Scraper — Germany Flatshare & Rental Data",
        "description": "WG-Gesucht scraper & real estate data API for wg-gesucht.de. German flatshare rooms (WG-Zimmer), 1-room flats, apartments & houses: rent, deposit, size, WG details, district, GPS, photos — clean JSON/CSV. Fast overview or full detail. No-code, no API key needed.",
        "version": "1.0",
        "x-build-id": "YIrtYzMadH9HIrV1A"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~wg-gesucht-property-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-wg-gesucht-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/sian.agency~wg-gesucht-property-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-wg-gesucht-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/sian.agency~wg-gesucht-property-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-wg-gesucht-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "scrapeMode": {
                        "title": "🧭 Scrape mode",
                        "enum": [
                            "overview",
                            "detail"
                        ],
                        "type": "string",
                        "description": "⚡ **Choose the depth of data per listing.**\n\n- **overview** — fast card-level scrape from the search result list (id, title, rent, WG size, area, district, available-from, thumbnail). Cheapest, highest volume.\n- **detail** — opens every listing's full page for richer fields (deposit, total rent, GPS coordinates, floor, features, full description, exact address).\n\n💡 **TIP:** Start with overview to size a city, then switch to detail for the listings you care about.",
                        "default": "overview"
                    },
                    "searchMode": {
                        "title": "🎯 Search mode",
                        "enum": [
                            "byCity",
                            "bySearchUrl",
                            "byListingUrl"
                        ],
                        "type": "string",
                        "description": "🔍 **How to tell the scraper which listings to fetch.**\n\n- **byCity** — give one or more German city names + a category.\n- **bySearchUrl** — paste a wg-gesucht.de search URL (all your filters preserved).\n- **byListingUrl** — give specific listing URLs or IDs (detail mode only).",
                        "default": "byCity"
                    },
                    "cities": {
                        "title": "📍 Cities",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "📍 **CITY SEARCH:** German city names to scrape, e.g. `Berlin`, `München`, `Hamburg`, `Köln`, `Frankfurt`.\n\n💡 **TIP:** Add several cities to compare markets in one run.\n\n⚠️ For a city outside this common set, use **By search URL** mode and paste a wg-gesucht.de search link instead.\n\nUsed when **Search mode = byCity**.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "category": {
                        "title": "🏘️ Category",
                        "enum": [
                            "wg-zimmer",
                            "1-zimmer-wohnungen",
                            "wohnungen",
                            "haeuser"
                        ],
                        "type": "string",
                        "description": "🏘️ **What kind of listing to search.**\n\n- **wg-zimmer** — flatshare rooms (WG-Zimmer) — the classic wg-gesucht use case.\n- **1-zimmer-wohnungen** — 1-room flats.\n- **wohnungen** — apartments.\n- **haeuser** — houses.\n\nUsed with **byCity** search. (WG rooms have no bedroom/bathroom/energy fields — that is normal for shared rooms.)",
                        "default": "wg-zimmer"
                    },
                    "searchUrls": {
                        "title": "🔗 Search URLs",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "🔗 **SEARCH-URL MODE:** Paste wg-gesucht.de search URLs — every filter you set on the site (rent band, size, short/long term, photos-only, virtual tour, sort) is preserved.\n\n✅ **SUPPORTED:** the standard search path, e.g. `https://www.wg-gesucht.de/wg-zimmer-in-Berlin.8.0.1.0.html?rMax=600`.\n\n💡 **BULK EDIT:** Click \"Bulk edit\" to paste one URL per line.\n\nUsed when **Search mode = bySearchUrl**.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "listingUrls": {
                        "title": "🆔 Listing URLs or IDs",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "🆔 **DETAIL-BY-URL MODE:** Specific listing detail URLs (`https://www.wg-gesucht.de/wg-zimmer-in-Berlin-Schoeneberg.13616431.html`) or bare numeric IDs (`13616431`).\n\n⚠️ wg-gesucht listings churn fast — old IDs return \"Angebot nicht vorhanden\" (deleted). Discover fresh IDs via byCity / bySearchUrl.\n\n💡 **BULK EDIT:** Click \"Bulk edit\" to paste one per line.\n\nUsed when **Search mode = byListingUrl** (requires **Scrape mode = detail**).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "🔢 Max results",
                        "minimum": 1,
                        "type": "integer",
                        "description": "🔢 **Maximum listings per run.**\n\n- **FREE users:** capped at 25 listings/run.\n- **PAID users:** unlimited.\n\nThe scraper stops paginating once this many listings are collected.",
                        "default": 100
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
