# Otodom Property Scraper — Poland Sale + Rent · PLN/m² Market (`sian.agency/otodom-property-scraper`) Actor

Scrape Otodom.pl into clean structured data. Extract Polish sale and rental property listings by location, ZIP, coordinates, polygon, or search URL — with price, PLN per square meter, area, rooms, geo, built-in market KPIs, and optional owner/agent contact enrichment.

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

## Pricing

from $1.50 / 1,000 property extracteds

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

## Otodom Property Scraper — Poland Sale + Rent · PLN/m² · Market KPIs

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian)
[![Related Actor](https://img.shields.io/badge/Store-Zillow%20Scraper-006AFF)](https://apify.com/sian.agency/zillow-property-scraper?fpr=sian)

#### 🎯 Extract Polish Sale + Rent Listings With Market KPIs in Seconds
##### Real estate investors, agents, market analysts, and data teams — get full Otodom listing data plus PLN/m² analytics and optional owner/agent contacts

---

### 📋 Overview

**Pull Otodom.pl listings — both for-sale AND rentals — into clean structured data.** Search anywhere in Poland by location name, ZIP code, coordinates, drawn polygon, or an Otodom search URL, and get back complete listings with price, price-per-square-metre, area, rooms, floor, geo, and photo metadata.

**Why investors and agents choose us over the alternatives:**
- 📊 **Analytics included, not just raw data**: Auto-generated HTML market report with median price, PLN/m² distribution (min/median/avg/p90/max), top cities by inventory, and property-type breakdown — computed for you on every run
- 🧭 **Five search modes**: location, ZIP, coordinates (+ radius), polygon, and search URL — the full Otodom geo-search surface, plus primary/secondary market and advertiser-type filters
- ✅ **Sale + Rent in one actor**: One `listingType` toggle gets you sales, rentals, or both sides
- 📇 **Optional owner/agent contact enrichment**: Owner or agent name + phone, agency contacts, plus build year, construction status, heating, and ownership — a lead-generation and due-diligence layer (PAID)
- 🆓 **FREE tier with full feature parity**: 25 listings per run, no credit card, same KPIs and HTML report — just a smaller cap

---

### ✨ Features

- 🏠 **Both sides of the market** — sale and rent via a single `listingType` toggle
- 🧭 **Five search modes** — by location name, ZIP (NN-NNN), coordinates (+ radius), polygon, or Otodom search URL
- 🔧 **Rich server-side filters** — property type, market (primary/secondary), advertiser type, sort order, price / area / rooms / year-built ranges, listed-within-days, photos-only
- 📈 **Market KPIs in HTML report** — median price, PLN/m² distribution, top cities by inventory, property-type tally
- 📇 **Owner/agent contact enrichment** — name, phone, agency, and full characteristics per listing (PAID toggle)
- 📦 **Bulk search** — pass an array of locations, ZIP codes, or search URLs in one run (PAID)
- 📱 **Standard Apify exports** — JSON, CSV, XLSX, RSS, HTML

---

### 🎬 Quick Start

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~otodom-property-scraper/runs?token=[YOUR_TOKEN]' \
  -H 'Content-Type: application/json' \
  -d '{"searchMode":"location","location":"Warszawa","listingType":"sale","maxResults":50}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Pick Sale, Rent, or Both

Set `listingType` to `sale`, `rent`, or `both`. Both runs each query twice (PAID — doubles the query count).

#### Step 2: Pick Your Search Mode

Choose a `searchMode` and provide its input:

- `location` → `location` (e.g. `"Warszawa"`)
- `zip` → `zipCode` (e.g. `"00-950"`)
- `coordinates` → `latitude` + `longitude` (+ optional `radius`)
- `polygon` → `polygon` (a drawn map ring)
- `url` → `url` (an Otodom search-results URL)

#### Step 3: Run & Export

Hit Run. Listings stream into the dataset; an HTML market report lands in the key-value store. Export as JSON, CSV, or Excel.

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `listingType` | string | No | `sale`, `rent`, or `both` (default: `sale`). `both` is PAID-only. |
| `searchMode` | string | No | `location`, `zip`, `coordinates`, `polygon`, or `url` (default: `location`). |
| `location` | string | If `searchMode=location` | Polish place name (e.g. `Warszawa`). |
| `locations` | array | No | Multiple place names in one run (PAID). |
| `zipCode` | string | If `searchMode=zip` | Polish postal code, `NN-NNN`. |
| `zipCodes` | array | No | Multiple ZIP codes in one run (PAID). |
| `latitude` / `longitude` | number | If `searchMode=coordinates` | Search centre. |
| `radius` | integer | No | Radius in km around the centre. |
| `polygon` | string | If `searchMode=polygon` | A `lon lat,...` ring. |
| `url` | string | If `searchMode=url` | An Otodom search-results URL. |
| `urls` | array | No | Multiple search URLs in one run (PAID). |
| `propertyType` | string | No | Flat, House, Land, Commercial, Warehouse, Garage, Room, Investment. |
| `market` | string | No | All, Primary, Secondary. |
| `ownerType` | string | No | All, Agency, Private, Developer. |
| `sortOrder` | string | No | Relevance, Newest, Price\_Low\_to\_High, Price\_High\_to\_Low, Price\_Per\_Meter\_Low, Area\_Large\_to\_Small. |
| `minPrice` / `maxPrice` | integer | No | Price range in PLN. |
| `minArea` / `maxArea` | integer | No | Living-area range in m². |
| `minRooms` / `maxRooms` | integer | No | Room-count range. |
| `minYearBuilt` / `maxYearBuilt` | integer | No | Construction-year range. |
| `daysSinceCreated` | integer | No | Only listings created within the last N days. |
| `hasPhotos` | boolean | No | Only listings with at least one photo. |
| `maxResults` | integer | No | Listings per query, 1–500 (default: 72). FREE tier capped at 25 per run. |
| `includeDetails` | boolean | No | Fetch full detail + owner/agent contacts per listing — PAID only (default: false). |

**Example — Location sale search:**

```json
{
  "listingType": "sale",
  "searchMode": "location",
  "location": "Kraków",
  "propertyType": "Flat",
  "maxResults": 100
}
```

**Example — Coordinates rentals with radius:**

```json
{
  "listingType": "rent",
  "searchMode": "coordinates",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "radius": 5,
  "maxResults": 50
}
```

**Example — Bulk locations, both sides, with contact enrichment:**

```json
{
  "listingType": "both",
  "searchMode": "location",
  "locations": ["Warszawa", "Wrocław", "Gdańsk"],
  "maxResults": 200,
  "includeDetails": true
}
```

***

### 📤 Output

Results land in the Apify dataset. Common fields on every listing:

| Field | Type | Description |
|-------|------|-------------|
| `propertyId` | integer | Unique Otodom listing ID |
| `propertyTitle` | string | Listing headline |
| `listingType` | string | `sale` or `rent` |
| `propertyType` | string | FLAT, HOUSE, LAND, etc. |
| `url` | string | Full listing URL on otodom.pl |
| `thumbnailUrl` | string | Preview image |
| `pricing` | object | `price`, `currency`, `pricePerSquareMeter`, `rentAdminFee`, `hidePrice` |
| `specs` | object | `areaInSquareMeters`, `terrainAreaInSquareMeters`, `rooms`, `floor` |
| `location` | object | `city`, `province`, `street`, `district`, `hierarchy` |
| `flags` | object | `isPrivateOwner`, `isExclusiveOffer`, `isPromoted` |
| `agency` | object | Search-card agency (null for private offers) |
| `images` | array | Photo URLs |
| `scrapedAt` | string | ISO timestamp |

**Enriched fields (when `includeDetails` is on):** `propertyDescription`, `market`, `advertiserType`, `characteristics` (build year, construction status, material, heating, ownership, floor), `coordinates`, and `contact` (owner/agent name + phone, agency name/URL/address/phones).

**Sale example:**

```json
{
  "propertyId": 68159688,
  "listingType": "sale",
  "propertyType": "FLAT",
  "url": "https://www.otodom.pl/pl/oferta/mieszkanie-46-92-m-warszawa-ID4BZrO",
  "pricing": { "price": 2000000, "currency": "PLN", "pricePerSquareMeter": 42626 },
  "specs": { "areaInSquareMeters": 46.92, "rooms": 2, "floor": "3" },
  "location": { "city": "Warszawa", "province": "mazowieckie", "district": "Śródmieście" }
}
```

***

### 💼 Use Cases

#### 1. Polish Market Analysis

Pull median price, PLN/m², and city/type breakdowns across any Polish location for housing-market research and dashboards.

#### 2. Property Comparables (Comps)

Extract deduped, structured sale or rent comps by location, ZIP, coordinates, polygon, or search URL for valuation and underwriting.

#### 3. Agent & Owner Lead Generation

Enrich listings with owner/agent name, phone, and agency contacts for CRM building and outreach.

#### 4. Investment Underwriting

Compare price and PLN/m² across primary vs secondary market and property types to source and price deals.

#### 5. Real-Estate Data Pipelines

Feed clean Otodom listing data into AVMs, price-prediction models, and scheduled monitoring pipelines.

***

### 🔗 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/otodom-property-scraper').call({
  listingType: 'sale',
  searchMode: 'location',
  location: 'Warszawa',
  maxResults: 100,
  includeDetails: true
});

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/otodom-property-scraper').call(
    run_input={
        'listingType': 'rent',
        'searchMode': 'zip',
        'zipCode': '00-950',
        'maxResults': 100
    }
)

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

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~otodom-property-scraper/runs?token=YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"listingType":"sale","searchMode":"location","location":"Gdańsk","maxResults":150}'
```

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 listings** per run — full feature parity, same data quality
- 1 query per run
- No credit card required

#### PAID Tier (Production Ready)

- **Unlimited** listings and queries per run
- `listingType: "both"` (sale + rent in one run)
- Bulk location / ZIP / URL arrays
- Owner/agent contact + full-detail enrichment
- Pay-per-result: only charged for listings actually returned

💰 **Transparent per-result pricing** — a low per-listing rate for search results, with a separate charge only when you opt into full-detail contact enrichment. Every listing comes with structured pricing and the run produces a full HTML market report with median, distribution, and city breakdowns — no post-processing required.

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

***

### ❓ Frequently Asked Questions

**Q: Does this cover rentals?**
A: Yes — set `listingType: "rent"` for rentals only, or `listingType: "both"` (PAID) to scrape sale + rent in a single run.

**Q: How many listings can I extract?**
A: FREE tier: 25 per run. PAID tier: unlimited — each query auto-paginates the full result set.

**Q: How do I get owner/agent phone numbers?**
A: Turn on `includeDetails` (PAID). Each listing is enriched with the owner or agent name + phone and any agency contacts.

**Q: Which areas of Poland are covered?**
A: All of Poland — search by any city, district, or voivodeship name, by ZIP, by coordinates, by polygon, or by an Otodom search URL.

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

***

### ⚠️ Trademark Disclaimer

This Actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by Otodom, Grupa OLX sp. z o.o., or any of their subsidiaries**. The name "Otodom" is used solely in a descriptive sense to identify the public data source the Actor reads from. All trademarks, service marks, and trade names referenced in this Actor or its documentation are the property of their respective owners.

***

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

Our actors are ethical and do not extract any private user data. 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/).

***

### 🤝 Support

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

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

# Actor input Schema

## `listingType` (type: `string`):

Which side of the market to scrape.

• **sale** — for-sale listings
• **rent** — rental listings
• **both** — runs each query twice, once for sale and once for rent (PAID — doubles the query count)

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

How to specify where to search.

• **location** — free-text place name (e.g. Warszawa)
• **zip** — Polish postal code (NN-NNN)
• **coordinates** — latitude + longitude (+ radius)
• **polygon** — a drawn map area
• **url** — an Otodom search-results URL

## `location` (type: `string`):

Polish place name — a city, district, or voivodeship. Examples: 'Warszawa', 'Kraków', 'Gdańsk, pomorskie'.

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

Array of Polish place names. PAID tier only.

## `zipCode` (type: `string`):

Polish postal code in NN-NNN format. Example: '00-950'.

## `zipCodes` (type: `array`):

Array of Polish postal codes (NN-NNN). PAID tier only.

## `latitude` (type: `number`):

Latitude of the search centre (-90 to 90).

## `longitude` (type: `number`):

Longitude of the search centre (-180 to 180).

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

Search radius in kilometres around the centre point. Leave empty for the default.

## `polygon` (type: `string`):

A polygon ring as 'lon lat,lon lat,...' pairs. Copy it from an Otodom map draw-search.

## `url` (type: `string`):

An Otodom search-results URL (starts with https://www.otodom.pl/). All filters encoded in the URL are respected.

## `urls` (type: `array`):

Array of Otodom search-results URLs. PAID tier only.

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

Filter by property type. Leave empty for all types.

## `market` (type: `string`):

Primary (new / from developer), Secondary (resale), or All.

## `ownerType` (type: `string`):

Filter by who posted the listing.

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

Ordering of the search results.

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

Minimum price. For sale this is the asking price; for rent it is the monthly rent. Leave empty for no minimum.

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

Maximum price. Leave empty for no maximum.

## `minArea` (type: `integer`):

Minimum living area in square metres. Leave empty for no minimum.

## `maxArea` (type: `integer`):

Maximum living area in square metres. Leave empty for no maximum.

## `minRooms` (type: `integer`):

Minimum number of rooms. Leave empty for any.

## `maxRooms` (type: `integer`):

Maximum number of rooms. Leave empty for any.

## `minYearBuilt` (type: `integer`):

Earliest construction year. Leave empty for any.

## `maxYearBuilt` (type: `integer`):

Latest construction year. Leave empty for any.

## `daysSinceCreated` (type: `integer`):

Only listings created within the last N days. Leave empty for all.

## `hasPhotos` (type: `boolean`):

When ON, only return listings that have at least one photo.

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

Hard cap on listings returned per query. Auto-paginates until the cap is reached or the search is fully drained. FREE tier is always capped at 25 listings per run.

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

When ON, fetches the full detail record for each listing (owner/agent name + phone, agency, build year, construction status, heating, ownership, coordinates). Adds a ListingEnriched charge per listing. Disabled on FREE tier.

## Actor input object example

```json
{
  "listingType": "sale",
  "searchMode": "location",
  "location": "Warszawa",
  "zipCode": "00-950",
  "hasPhotos": false,
  "maxResults": 72,
  "includeDetails": false
}
```

# Actor output Schema

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

Structured Otodom sale and rent listings with price, PLN/m², specs, location, and (optional) owner/agent contact + full-detail enrichment.

## `htmlReport` (type: `string`):

HTML summary with run stats, market KPIs (median price, PLN/m² distribution), city + property-type breakdowns, and per-query totals.

# 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 = {
    "location": "Warszawa"
};

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

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

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Otodom Property Scraper — Poland Sale + Rent · PLN/m² Market",
        "description": "Scrape Otodom.pl into clean structured data. Extract Polish sale and rental property listings by location, ZIP, coordinates, polygon, or search URL — with price, PLN per square meter, area, rooms, geo, built-in market KPIs, and optional owner/agent contact enrichment.",
        "version": "1.0",
        "x-build-id": "w9P77dyay0Mvqlnfe"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~otodom-property-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-otodom-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~otodom-property-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-otodom-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~otodom-property-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-otodom-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": {
                    "listingType": {
                        "title": "🏠 Listing Type",
                        "enum": [
                            "sale",
                            "rent",
                            "both"
                        ],
                        "type": "string",
                        "description": "Which side of the market to scrape.\n\n• **sale** — for-sale listings\n• **rent** — rental listings\n• **both** — runs each query twice, once for sale and once for rent (PAID — doubles the query count)",
                        "default": "sale"
                    },
                    "searchMode": {
                        "title": "🧭 Search Mode",
                        "enum": [
                            "location",
                            "zip",
                            "coordinates",
                            "polygon",
                            "url"
                        ],
                        "type": "string",
                        "description": "How to specify where to search.\n\n• **location** — free-text place name (e.g. Warszawa)\n• **zip** — Polish postal code (NN-NNN)\n• **coordinates** — latitude + longitude (+ radius)\n• **polygon** — a drawn map area\n• **url** — an Otodom search-results URL",
                        "default": "location"
                    },
                    "location": {
                        "title": "📍 Location  (Search Mode = location)",
                        "type": "string",
                        "description": "Polish place name — a city, district, or voivodeship. Examples: 'Warszawa', 'Kraków', 'Gdańsk, pomorskie'.",
                        "default": "Warszawa"
                    },
                    "locations": {
                        "title": "📋 Bulk Locations  (PAID, location mode)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Array of Polish place names. PAID tier only.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "zipCode": {
                        "title": "📮 ZIP Code  (Search Mode = zip)",
                        "type": "string",
                        "description": "Polish postal code in NN-NNN format. Example: '00-950'."
                    },
                    "zipCodes": {
                        "title": "📋 Bulk ZIP Codes  (PAID, zip mode)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Array of Polish postal codes (NN-NNN). PAID tier only.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "latitude": {
                        "title": "🌐 Latitude  (Search Mode = coordinates)",
                        "type": "number",
                        "description": "Latitude of the search centre (-90 to 90)."
                    },
                    "longitude": {
                        "title": "🌐 Longitude  (Search Mode = coordinates)",
                        "type": "number",
                        "description": "Longitude of the search centre (-180 to 180)."
                    },
                    "radius": {
                        "title": "📏 Radius (km)  (Search Mode = coordinates)",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Search radius in kilometres around the centre point. Leave empty for the default."
                    },
                    "polygon": {
                        "title": "✏️ Polygon  (Search Mode = polygon)",
                        "type": "string",
                        "description": "A polygon ring as 'lon lat,lon lat,...' pairs. Copy it from an Otodom map draw-search."
                    },
                    "url": {
                        "title": "🔗 Search URL  (Search Mode = url)",
                        "type": "string",
                        "description": "An Otodom search-results URL (starts with https://www.otodom.pl/). All filters encoded in the URL are respected."
                    },
                    "urls": {
                        "title": "📋 Bulk Search URLs  (PAID, url mode)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Array of Otodom search-results URLs. PAID tier only.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "propertyType": {
                        "title": "🏷 Property Type",
                        "enum": [
                            "Flat",
                            "House",
                            "Land",
                            "Commercial",
                            "Warehouse",
                            "Garage",
                            "Room",
                            "Investment"
                        ],
                        "type": "string",
                        "description": "Filter by property type. Leave empty for all types."
                    },
                    "market": {
                        "title": "🏢 Market",
                        "enum": [
                            "All",
                            "Primary",
                            "Secondary"
                        ],
                        "type": "string",
                        "description": "Primary (new / from developer), Secondary (resale), or All."
                    },
                    "ownerType": {
                        "title": "👤 Advertiser Type",
                        "enum": [
                            "All",
                            "Agency",
                            "Private",
                            "Developer"
                        ],
                        "type": "string",
                        "description": "Filter by who posted the listing."
                    },
                    "sortOrder": {
                        "title": "↕️ Sort Order",
                        "enum": [
                            "Relevance",
                            "Newest",
                            "Price_Low_to_High",
                            "Price_High_to_Low",
                            "Price_Per_Meter_Low",
                            "Area_Large_to_Small"
                        ],
                        "type": "string",
                        "description": "Ordering of the search results."
                    },
                    "minPrice": {
                        "title": "💵 Min price (PLN)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Minimum price. For sale this is the asking price; for rent it is the monthly rent. Leave empty for no minimum."
                    },
                    "maxPrice": {
                        "title": "💵 Max price (PLN)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum price. Leave empty for no maximum."
                    },
                    "minArea": {
                        "title": "📐 Min area (m²)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Minimum living area in square metres. Leave empty for no minimum."
                    },
                    "maxArea": {
                        "title": "📐 Max area (m²)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum living area in square metres. Leave empty for no maximum."
                    },
                    "minRooms": {
                        "title": "🚪 Min rooms",
                        "minimum": 0,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Minimum number of rooms. Leave empty for any."
                    },
                    "maxRooms": {
                        "title": "🚪 Max rooms",
                        "minimum": 0,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Maximum number of rooms. Leave empty for any."
                    },
                    "minYearBuilt": {
                        "title": "🏗 Min year built",
                        "minimum": 1800,
                        "maximum": 2100,
                        "type": "integer",
                        "description": "Earliest construction year. Leave empty for any."
                    },
                    "maxYearBuilt": {
                        "title": "🏗 Max year built",
                        "minimum": 1800,
                        "maximum": 2100,
                        "type": "integer",
                        "description": "Latest construction year. Leave empty for any."
                    },
                    "daysSinceCreated": {
                        "title": "🕒 Listed within (days)",
                        "minimum": 0,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Only listings created within the last N days. Leave empty for all."
                    },
                    "hasPhotos": {
                        "title": "🖼 Only with photos",
                        "type": "boolean",
                        "description": "When ON, only return listings that have at least one photo.",
                        "default": false
                    },
                    "maxResults": {
                        "title": "📊 Max results per query",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Hard cap on listings returned per query. Auto-paginates until the cap is reached or the search is fully drained. FREE tier is always capped at 25 listings per run.",
                        "default": 72
                    },
                    "includeDetails": {
                        "title": "📇 Include full detail + contacts (PAID)",
                        "type": "boolean",
                        "description": "When ON, fetches the full detail record for each listing (owner/agent name + phone, agency, build year, construction status, heating, ownership, coordinates). Adds a ListingEnriched charge per listing. Disabled on FREE tier.",
                        "default": false
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
