# ohne-makler.net Scraper — Germany FSBO Property Data & API (`sian.agency/ohne-makler-property-scraper`) Actor

ohne-makler.net scraper & real estate data API for Germany's FSBO / private-seller portal. Commission-free rent & sale listings in every German city: price, size, rooms, deposit, address, GPS, energy class, photos — clean JSON/CSV. Fast overview or full detail. No-code, no API key needed.

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

## Pricing

from $2.50 / 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

## ohne-makler.net Scraper — Germany FSBO Property Data & API 🏡

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Wohnungsbörse Scraper](https://img.shields.io/badge/Store-Wohnungsb%C3%B6rse%20Scraper-1AE392)](https://apify.com/sian.agency/wohnungsboerse-property-scraper?fpr=sian) [![Immobiliare.it Scraper](https://img.shields.io/badge/Store-Immobiliare.it%20Scraper-008C45)](https://apify.com/sian.agency/immobiliare-property-scraper?fpr=sian) [![Rightmove Scraper](https://img.shields.io/badge/Store-Rightmove%20Scraper-00DEB6)](https://apify.com/sian.agency/rightmove-property-scraper?fpr=sian)

#### 🎉 Every commission-free private-seller listing in Germany — the entire result set in a single fetch, clean JSON/CSV
##### For lead-gen teams, property analysts and investors who want provisionsfrei (no-agent) listings nobody else is scraping

---

### 📋 Overview

**Pull Germany's FSBO real-estate market straight into a spreadsheet.** ohne-makler.net is Germany's private-seller ("von privat", provisionsfrei) property portal — this scraper turns it into clean, structured data: rent (mieten) and sale (kaufen) listings in every German city, with price, size, rooms, deposit, exact address, GPS, energy class, photos and full descriptions.

**Why professionals choose this scraper:**
- ✅ **Whole market in one request**: the search page embeds the *entire* result set — a national rent search returns 2,000+ listings in a single fetch, no pagination, no page-by-page billing.
- ⚡ **Fast & reliable**: German residential routing returns the full page in seconds — no throttling, no broken half-pages.
- 🎯 **Rich, ready-to-use fields**: 40+ structured columns including GPS coordinates, energy class, deposit and price-per-m².
- 💰 **Pay only for what you keep**: transparent pay-per-result pricing — no charge until your input is validated.
- 💎 **A niche nobody else covers**: the only dedicated ohne-makler.net scraper — reach private sellers before the agencies do.
- ✨ **Two modes**: cheap **overview** to map a city, full **detail** for the complete listing.

---

### ✨ Features

- 🧭 **Overview mode** — enumerate every listing for a search (id, title, URL, GPS) in one cheap fetch.
- 🔎 **Detail mode** — full listing: exact address, all attributes, energy, deposit, description and every photo.
- 🗺️ **By place** — pick contract + property type + state/city, or go national.
- 🔗 **By search URL** — paste any ohne-makler.net search URL and scrape it as-is.
- 🆔 **By listing URL** — pass specific listing URLs or IDs straight to detail mode.
- 🎚️ **Built-in filters** — price, living area and search radius.
- 📊 **Computed KPIs** — price-per-m² and thumbnail-first rows out of the box.
- 🌐 **Map-ready geo** — latitude/longitude on every listing, with a precise/approximate flag.
- 👤 **FSBO-only signal** — every listing is a private, commission-free seller.

---

### 🎬 Quick Start

Choose a mode and a place (or paste a search URL), set how many listings you want, and run. Results land in the Apify dataset as JSON/CSV/Excel.

```bash
curl -X POST https://api.apify.com/v2/acts/sian.agency~ohne-makler-property-scraper/runs?token=YOUR_TOKEN \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"byPlace","contract":"rent","estateType":"wohnung","states":["berlin"],"cities":["berlin"]}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose your mode

Pick **Overview** (cheap, full list) or **Detail** (full data per listing).

#### Step 2: Tell it what to scrape

Set contract + property type + state/city, or paste an ohne-makler.net search URL.

#### Step 3: Run

Click **Start** and watch listings stream into your dataset.

**That's it! In under a minute, you'll have:**

- A clean dataset of private-seller listings
- Price, size, rooms, address and GPS for every result
- One-click export to JSON, CSV or Excel

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| scrapeMode | string | No | `overview` (cheap list) or `detail` (full data) |
| searchMode | string | No | `byPlace`, `bySearchUrl` or `byListingUrl` |
| contract | string | No | `rent` (mieten) or `sale` (kaufen) |
| estateType | string | No | `wohnung`, `haus`, `zimmer`, `grundstueck`, `buero`, … |
| states | array | No | State slugs, e.g. `berlin`, `bayern` |
| cities | array | No | City slugs, e.g. `berlin`, `berlin-lichterfelde` |
| searchUrls | array | No | ohne-makler.net search URLs |
| listingUrls | array | No | Listing URLs or IDs (detail mode) |
| priceMin / priceMax | integer | No | Price filter in EUR |
| areaMin / areaMax | integer | No | Living-area filter in m² |
| radius | integer | No | Search radius in km |
| enrichPreview | boolean | No | Add price/size/rooms to overview rows |
| maxResults | integer | No | Cap per run (FREE: 25, PAID: unlimited) |

**Example (overview by place):**

```json
{
  "scrapeMode": "overview",
  "searchMode": "byPlace",
  "contract": "rent",
  "estateType": "wohnung",
  "states": ["berlin"],
  "cities": ["berlin"],
  "maxResults": 100
}
```

**Example (detail by listing URL):**

```json
{
  "scrapeMode": "detail",
  "searchMode": "byListingUrl",
  "listingUrls": ["https://www.ohne-makler.net/immobilie/443590/", "465847"]
}
```

***

### 📤 Output

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

| Field | Type | Description |
|-------|------|-------------|
| id | string | Listing ID (Objekt-Nr) |
| propertyTitle | string | Listing headline |
| contract | string | rent / sale |
| price | number | Kaltmiete (rent) or Kaufpreis (sale), EUR |
| price\_per\_sqm\_eur | number | Computed price per m² |
| area\_sqm | number | Living area in m² |
| rooms | number | Number of rooms |
| deposit | number | Mietsicherheit / Kaution, EUR |
| address / city / zip / district | string | Location details |
| latitude / longitude | number | GPS coordinates |
| energy\_class | string | Energieeffizienzklasse |
| construction\_year | number | Baujahr |
| is\_private | boolean | Always true (FSBO portal) |
| images | array | All photo URLs (detail mode) |

**Example:**

```json
{
  "id": "443590",
  "url": "https://www.ohne-makler.net/immobilie/443590/",
  "propertyTitle": "Berlin Lichterfelde 3-Zi-Neubau 2025 76 m² A+ Privatgarten",
  "contract": "rent",
  "property_type": "Wohnung",
  "price": 1786,
  "price_per_sqm_eur": 23,
  "area_sqm": 76.4,
  "rooms": 3,
  "deposit": 5358,
  "address": "Schillerstr. 21, 12207 Berlin (Lichterfelde)",
  "city": "Berlin",
  "zip": "12207",
  "district": "Lichterfelde",
  "latitude": 52.42673,
  "longitude": 13.32214,
  "energy_class": "A+",
  "construction_year": 2025,
  "is_private": true,
  "image_count": 13
}
```

***

### 💼 Use Cases & Examples

#### 1. FSBO Lead Generation

**Real-estate agents & buyers sourcing commission-free sellers before the competition.**

**Input:** A city + contract.
**Output:** Every private-seller listing with location and price.
**Use:** Build an outreach list of provisionsfrei owners.

#### 2. Rent & Price Benchmarking

**Analysts tracking asking prices and price-per-m² by district.**

**Input:** A state/city with price filters.
**Output:** Structured price, area and price-per-m² columns.
**Use:** Benchmark a neighbourhood or build a market report.

#### 3. Investment Sourcing

**Investors scanning for undervalued private-sale opportunities.**

**Input:** Sale contract + area/price filters.
**Output:** Listings with construction year, energy class and condition.
**Use:** Shortlist deals that match an investment thesis.

#### 4. CRM & Map Enrichment

**PropTech teams enriching a CRM with geo-located inventory.**

**Input:** Search URLs for target regions.
**Output:** GPS coordinates on every listing.
**Use:** Plot inventory on a map or enrich existing records.

#### 5. Market Monitoring

**Researchers tracking how the FSBO segment moves over time.**

**Input:** Scheduled national or regional runs.
**Output:** A growing dataset of listings.
**Use:** Measure supply, price trends and time-on-market signals.

***

### 🔗 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/ohne-makler-property-scraper').call({
  scrapeMode: 'overview',
  searchMode: 'byPlace',
  contract: 'rent',
  estateType: 'wohnung',
  states: ['berlin'],
  cities: ['berlin'],
});

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/ohne-makler-property-scraper').call(
    run_input={
        'scrapeMode': 'detail',
        'searchMode': 'byListingUrl',
        'listingUrls': ['https://www.ohne-makler.net/immobilie/443590/'],
    }
)

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

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~ohne-makler-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"bySearchUrl","searchUrls":["https://www.ohne-makler.net/immobilien/wohnung-mieten/berlin/berlin/"]}'
```

#### 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, push to a CRM, or notify

***

### 📊 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 runs, no caps
- Pay-per-result: only charged for listings you actually extract

💰 **Cheap by design** — the overview event maps an entire city for cents, and you only pay for full detail when you need it.

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

***

### ❓ Frequently Asked Questions

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

**Q: Does it cover all of Germany?**
A: Yes — search nationally or narrow to any state, city or radius.

**Q: What's the difference between overview and detail?**
A: Overview returns the full result list cheaply (id, title, URL, GPS). Detail fetches each page for the complete field set (address, energy, deposit, description, all photos).

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

**Q: Do I need an account or API key for ohne-makler.net?**
A: No. Just run the actor.

**Q: Why are bedrooms / listing date sometimes empty?**
A: ohne-makler.net doesn't structure those fields for most listings — that's the source, not a bug.

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

***

### 🐛 Troubleshooting

**No results returned**

- Check the state/city slugs (e.g. `berlin`, `berlin-lichterfelde`) — they must match the site's URL slugs.
- Widen the scope: drop the city, or remove price/area filters.

**Fewer fields than expected in overview mode**

- Overview returns the list cheaply. Enable `enrichPreview` for price/size/rooms, or use **detail** mode for everything.

**Detail run is slow**

- Detail fetches one page per listing. Lower `maxResults` or split across runs.

***

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

> **Trademark note:** ohne-makler.net is a trademark of its respective owner. This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by ohne-makler.net. "ohne-makler" is used only to describe the public website this tool helps you access.

***

### 🤝 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`):

🧭 **OVERVIEW** = cheap full-list enumeration. ONE search fetch returns the *entire* result set (id, title, URL, GPS) — no pagination. Optionally enrich each with price/size/rooms.

🔎 **DETAIL** = full per-listing data: exact address, all attributes, energy, deposit, description and every photo.

💡 **TIP:** Start with overview to map a city cheaply, then run detail on the IDs you care about.

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

🔀 How to choose what to scrape:

- **By place** — pick contract + property type + (optional) state/city slugs.
- **By search URL** — paste one or more ohne-makler.net search URLs.
- **By listing URL** — detail mode only: pass explicit listing URLs or IDs.

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

🏷️ Rent (mieten) or sale (kaufen). Used in **By place** mode (and as a fallback otherwise).

## `estateType` (type: `string`):

🏘️ ohne-makler type slug used in **By place** mode: `wohnung` (apartment), `haus` (house), `zimmer` (room), `grundstueck` (plot), `buero` (office), `lagerhalle` (warehouse), …

## `states` (type: `array`):

🗺️ Optional German state slugs (e.g. `berlin`, `bayern`, `nordrhein-westfalen`). Leave empty for national scope.

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

🏙️ Optional city slugs (e.g. `berlin`, `berlin-lichterfelde`, `muenchen`). Pair with a matching state slug.

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

🔗 Paste one or more ohne-makler.net search URLs (used when **Search mode = By search URL**). Example: `https://www.ohne-makler.net/immobilien/wohnung-mieten/berlin/berlin/`

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

🆔 Detail-page URLs or bare listing IDs (used when **Scrape mode = Detail** + **Search mode = By listing URL**). Example: `https://www.ohne-makler.net/immobilie/443590/` or just `443590`.

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

💰 Minimum price filter in EUR (kaltmiete for rent, kaufpreis for sale).

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

💰 Maximum price filter in EUR.

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

📐 Minimum living area filter in m².

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

📐 Maximum living area filter in m².

## `radius` (type: `integer`):

📍 Search radius in km around the chosen city.

## `enrichPreview` (type: `boolean`):

✨ In **Overview** mode, also fetch each tiny preview fragment to fill price / area / rooms / city / zip. Adds one small request per listing (still far cheaper than full detail).

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

🔢 Cap on listings per run.

**FREE users:** up to 25 listings per run.
**PAID users:** unlimited — frame as upgrade, not limit.

## Actor input object example

```json
{
  "scrapeMode": "overview",
  "searchMode": "byPlace",
  "contract": "rent",
  "estateType": "wohnung",
  "states": [],
  "cities": [],
  "searchUrls": [],
  "listingUrls": [],
  "enrichPreview": false,
  "maxResults": 100
}
```

# Actor output Schema

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

Scraped property listings — price, size, rooms, location, energy, 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 = {
    "estateType": "wohnung"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/ohne-makler-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 = { "estateType": "wohnung" }

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/ohne-makler-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 '{
  "estateType": "wohnung"
}' |
apify call sian.agency/ohne-makler-property-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "ohne-makler.net Scraper — Germany FSBO Property Data & API",
        "description": "ohne-makler.net scraper & real estate data API for Germany's FSBO / private-seller portal. Commission-free rent & sale listings in every German city: price, size, rooms, deposit, address, GPS, energy class, photos — clean JSON/CSV. Fast overview or full detail. No-code, no API key needed.",
        "version": "1.1",
        "x-build-id": "lDfzJAMVUyoK2NRS4"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~ohne-makler-property-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-ohne-makler-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~ohne-makler-property-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-ohne-makler-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~ohne-makler-property-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-ohne-makler-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": "🧭 **OVERVIEW** = cheap full-list enumeration. ONE search fetch returns the *entire* result set (id, title, URL, GPS) — no pagination. Optionally enrich each with price/size/rooms.\n\n🔎 **DETAIL** = full per-listing data: exact address, all attributes, energy, deposit, description and every photo.\n\n💡 **TIP:** Start with overview to map a city cheaply, then run detail on the IDs you care about.",
                        "default": "overview"
                    },
                    "searchMode": {
                        "title": "🔀 Search mode",
                        "enum": [
                            "byPlace",
                            "bySearchUrl",
                            "byListingUrl"
                        ],
                        "type": "string",
                        "description": "🔀 How to choose what to scrape:\n- **By place** — pick contract + property type + (optional) state/city slugs.\n- **By search URL** — paste one or more ohne-makler.net search URLs.\n- **By listing URL** — detail mode only: pass explicit listing URLs or IDs.",
                        "default": "byPlace"
                    },
                    "contract": {
                        "title": "🏷️ Contract",
                        "enum": [
                            "rent",
                            "sale"
                        ],
                        "type": "string",
                        "description": "🏷️ Rent (mieten) or sale (kaufen). Used in **By place** mode (and as a fallback otherwise).",
                        "default": "rent"
                    },
                    "estateType": {
                        "title": "🏘️ Property type slug",
                        "type": "string",
                        "description": "🏘️ ohne-makler type slug used in **By place** mode: `wohnung` (apartment), `haus` (house), `zimmer` (room), `grundstueck` (plot), `buero` (office), `lagerhalle` (warehouse), …",
                        "default": "wohnung"
                    },
                    "states": {
                        "title": "🗺️ State slugs",
                        "type": "array",
                        "description": "🗺️ Optional German state slugs (e.g. `berlin`, `bayern`, `nordrhein-westfalen`). Leave empty for national scope.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "cities": {
                        "title": "🏙️ City slugs",
                        "type": "array",
                        "description": "🏙️ Optional city slugs (e.g. `berlin`, `berlin-lichterfelde`, `muenchen`). Pair with a matching state slug.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchUrls": {
                        "title": "🔗 Search URLs",
                        "type": "array",
                        "description": "🔗 Paste one or more ohne-makler.net search URLs (used when **Search mode = By search URL**). Example: `https://www.ohne-makler.net/immobilien/wohnung-mieten/berlin/berlin/`",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "listingUrls": {
                        "title": "🆔 Listing URLs or IDs",
                        "type": "array",
                        "description": "🆔 Detail-page URLs or bare listing IDs (used when **Scrape mode = Detail** + **Search mode = By listing URL**). Example: `https://www.ohne-makler.net/immobilie/443590/` or just `443590`.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "priceMin": {
                        "title": "💰 Min price (€)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "💰 Minimum price filter in EUR (kaltmiete for rent, kaufpreis for sale)."
                    },
                    "priceMax": {
                        "title": "💰 Max price (€)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "💰 Maximum price filter in EUR."
                    },
                    "areaMin": {
                        "title": "📐 Min living area (m²)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "📐 Minimum living area filter in m²."
                    },
                    "areaMax": {
                        "title": "📐 Max living area (m²)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "📐 Maximum living area filter in m²."
                    },
                    "radius": {
                        "title": "📍 Search radius (km)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "📍 Search radius in km around the chosen city."
                    },
                    "enrichPreview": {
                        "title": "✨ Enrich overview with price/size/rooms",
                        "type": "boolean",
                        "description": "✨ In **Overview** mode, also fetch each tiny preview fragment to fill price / area / rooms / city / zip. Adds one small request per listing (still far cheaper than full detail).",
                        "default": false
                    },
                    "maxResults": {
                        "title": "🔢 Max results",
                        "minimum": 1,
                        "type": "integer",
                        "description": "🔢 Cap on listings per run.\n\n**FREE users:** up to 25 listings per run.\n**PAID users:** unlimited — frame as upgrade, not limit.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
