Otodom Poland Real Estate Scraper
Pricing
Pay per event
Otodom Poland Real Estate Scraper
Scrape sale and rent listings from Otodom.pl, Poland's #1 property portal. Get clean numeric price, area, room, district, and city data per listing while we handle blocks and fingerprint rotation for you.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
🎯 What this scrapes
Otodom.pl is Poland's #1 property portal, and the rival cluster targeting it is the deepest we've measured in this fleet: 41 Actors already compete for it on the Apify Store, 16 with real paying users, the leader (fatihtahta/otodom-pl-scraper) running 90 jobs a month for 145 users. This Actor pulls listing cards straight off Otodom's own search-results JSON for both sprzedaż (sale) and wynajem (rent) — flats, houses, plots, commercial units, warehouses, and garages — across as many Polish cities and districts as you want in a single run, and normalizes every card into clean numeric fields: bare PLN price, price-per-m², floor area, room count, and district/city/province, instead of forcing you to scrape the rendered page yourself.
🔥 What we handle for you
- 🛡️ Browser fingerprint rotation —
curl-cffiimpersonates real Chrome and Firefox TLS handshakes, rotated across requests, so the target sees a browser, not Python. - 🌐 Proxy session rotation via Apify Proxy — fresh session and exit IP on every block, always pinned to a Polish (
PL) residential exit so you never get a wrong-country page silently. - 🔁 Retries with exponential backoff on
408 / 429 / 5xx— up to 5 attempts per page,Retry-Afterhonoured. - 🧱 Search- and page-level fault isolation — one blocked search or one bad listing is skipped and logged, never crashes the run.
- 🧊 Clean, typed dataset rows — Pydantic-validated, ISO-8601 timestamps, numeric price/area/room fields with an explicit currency instead of one rendered blob.
- 💰 Pay-Per-Event pricing — you only pay for results that hit your dataset. No data, no charge.
💡 Use cases
- Home-buyer market research — pull current sprzedaż listings for a Polish city, price-per-m² included, to compare districts fast.
- Rental market benchmarking — track wynajem listing prices and area across Warsaw, Kraków, Wrocław, and other cities in one run.
- PropTech and real-estate analytics — feed a clean, deduped listings dataset into a pricing or valuation model.
- Relocation services — build client-facing property shortlists with district, room-count, and fee data included.
⚙️ How to use it
- Click Try for free at the top of the page.
- Add one or more searches — pick a transaction type (sale/rent), a property type, and a location path copied from an otodom.pl search URL (e.g.
mazowieckie/warszawa/warszawa/warszawa). - Click Start. Output streams into the run's dataset.
- Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
searches | array | yes | — | 1-50 structured searches: transactionType ('sale'|'rent'), propertyType ('flat'|'house'|'room'|'plot'|'commercial'|'warehouse'|'garage'), locationPath, maxPages (1-50). |
maxResults | integer | no | 100 | Cap on rows this run, summed across all Searches. |
proxyConfiguration | object | no | RESIDENTIAL group | The Actor pins country_code='PL' internally whenever a proxy is used (never user-configurable). |
Example input
{"searches": [{"transactionType": "sale","propertyType": "flat","locationPath": "mazowieckie/warszawa/warszawa/warszawa","maxPages": 2},{"transactionType": "rent","propertyType": "flat","locationPath": "malopolskie/krakow/krakow/krakow","maxPages": 1}],"maxResults": 40,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
📤 Output
Every row is one dataset item.
| Field | Type | Notes |
|---|---|---|
listing_id | string | Otodom's numeric ad id, stringified — stable, globally unique. |
url | string | Canonical https://www.otodom.pl/pl/oferta/ |
transaction_type | string | 'sale' or 'rent', from the listing itself. |
property_type | string | Otodom's estate label, e.g. 'flat', 'house', 'investment'. |
title | string | Listing headline as shown on the search card. |
price | ['number', 'null'] | Asking price (sale) or monthly rent (rent). |
currency | string | Always 'PLN'. |
price_per_sqm | ['number', 'null'] | Otodom's own computed price/m². |
additional_rent_fee | ['number', 'null'] | Monthly administrative/maintenance fee (czynsz), separate from price. |
area_sqm | ['number', 'null'] | Floor area in square metres. |
terrain_area_sqm | ['number', 'null'] | Plot/terrain area in square metres, for houses and plots. |
rooms | ['integer', 'null'] | Room count, parsed from Otodom's enum label. |
floor | ['string', 'null'] | Otodom's raw floor label, e.g. 'FIRST', 'GROUND'. |
district | ['string', 'null'] | District/neighbourhood name, when geocoded. |
city | ['string', 'null'] | City name from the listing's address. |
province | ['string', 'null'] | Voivodeship (province) name. |
is_private_owner | ['boolean', 'null'] | True when listed directly by owner. |
is_promoted | ['boolean', 'null'] | True when Otodom marks the ad as promoted. |
image_urls | array | Gallery photo URLs (empty OK). |
scraped_at | string | ISO 8601 UTC row-creation timestamp. |
Example output
{"listing_id": "65432101","url": "https://www.otodom.pl/pl/oferta/mieszkanie-3-pokoje-mokotow-warszawa-ID4abcd","transaction_type": "sale","property_type": "flat","title": "Przestronne mieszkanie na Mokotowie","price": 850000.0,"currency": "PLN","price_per_sqm": 15454.5,"additional_rent_fee": 600.0,"area_sqm": 55.0,"rooms": 3,"floor": "FIRST","district": "Mokotów","city": "Warszawa","province": "mazowieckie","is_private_owner": false,"is_promoted": true,"image_urls": ["https://ap.otodom.pl/img/65432101_large.jpg"],"scraped_at": "2026-09-17T12:00:00+00:00"}
💰 Pricing
Pay-Per-Event — you pay only when these events fire:
| Event | USD | What it is |
|---|---|---|
actor-start | $0.20 | One-off warm-up charge per run |
result-row | $0.0018 | Per unique dataset item |
Example: 1 000 results at the rates above ≈ $2.00. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.
🚧 Limitations
v1 is search-results only — no detail-page enrichment, so fields only the detail page carries (full description text, energy label, exact address, building year) are out of scope for v1. district is null when a listing's reverse-geocoding doesn't carry one (common for some rural/plot listings). A location_path must be copied from a real otodom.pl search URL's path segments — a free-text city name alone is not accepted, since Otodom's own path vocabulary is what determines which listings a search matches.
❓ FAQ
Do I need an Otodom account or API key?
No. This Actor scrapes Otodom.pl's own publicly listed property data — no login, no API key.
How do I find my locationPath?
Search on otodom.pl with your filters, then copy the path segments after /wyniki/sprzedaz/mieszkanie/ (or /wynajem/...) from the resulting URL — e.g. mazowieckie/warszawa/warszawa/warszawa.
Can I scrape multiple cities and both sale and rent in one run?
Yes — add as many searches entries as you want (up to 50), mixing transaction types, property types, and cities freely; we dedupe across all of them.
Why is there no enrich option like some of your other real-estate Actors?
Otodom's search-results JSON already carries price, area, rooms, fees, and location — v1 focuses on getting that data reliably rather than shipping a partial detail-page enrichment toggle.
💬 Your feedback
Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.