Otodom Scraper avatar

Otodom Scraper

Pricing

Pay per event

Go to Apify Store
Otodom Scraper

Otodom Scraper

Export public Otodom Poland sale and rental listings with prices, property attributes, photos, locations, and advertiser metadata.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Export public Otodom Poland sale and rental listings as structured JSON, CSV, Excel, XML, or RSS data. The Actor follows real Otodom search URLs, preserves their filters, paginates results, and returns prices, property attributes, photos, location details, and advertiser metadata. Use it for one-time research or schedule repeated snapshots for Polish property market monitoring.

The default search mode is efficient: it reads the structured data already embedded in Otodom result pages. Optional detail enrichment visits each offer page to add full descriptions, more attributes, coordinates, images, and available public advertiser contacts. No Otodom login is required.

What can you do with this Otodom scraper?

  • Export current apartments, houses, plots, commercial properties, rooms, garages, and developments covered by an Otodom search URL.
  • Compare sale or rental inventory between cities, districts, property types, and saved filter combinations.
  • Build recurring snapshots for new-listing, removed-listing, and price-change analysis in your own database.
  • Collect PLN prices, price per square metre, area, room count, floor, market type, and location hierarchy.
  • Preserve property photo URLs without downloading large image files.
  • Capture public agency, developer, owner classification, and available assigned-agent metadata.
  • Enrich selected listings with complete descriptions and detailed property attributes.
  • Feed Otodom data into spreadsheets, BI tools, warehouses, CRM workflows, or Apify integrations.

Who is it for?

Property investors and analysts can compare asking prices, price per square metre, and available inventory across Polish markets.

Real estate agencies can monitor competing listings, neighbourhood supply, and public advertiser information.

Developers and researchers can use the Actor as an unofficial Otodom data export rather than maintaining page parsing and retry logic.

Relocation and housing teams can create filtered rental datasets for cities such as Lublin, Warsaw, Gdańsk, or Katowice.

Data teams can schedule repeatable runs and join records by stable Otodom IDs in an external history table.

Why use this Actor?

  1. Search URL fidelity — copy a real filtered Otodom results URL and the Actor keeps those source filters.
  2. Typed records — output is normalized into stable fields instead of raw HTML.
  3. Two depth levels — use fast search snapshots or enable offer-page enrichment only when the additional detail is valuable.
  4. Bounded collectionmaxItems stops pagination and avoids unnecessary source requests.
  5. Economical delivery — a browser-like direct HTTP route avoids browser runtime and proxy transfer while bounded retries handle transient failures.
  6. Integration-ready output — the default dataset works with Apify API clients, webhooks, schedules, exports, and MCP.
  7. Transparent partial enrichment — if one optional detail page fails, the useful search record is retained instead of disappearing.

What Otodom property data is extracted?

FieldMeaning
propertyIdStable Otodom listing or development identifier
urlCanonical public offer URL
titleListing headline
transactionSale or rental classification
propertyTypeFlat, house, land, investment, or other source category
marketPrimary, secondary, or another available market value
priceAdvertised amount and currency
rentPriceRent or maintenance amount when exposed
pricePerSquareMeterPLN/m² or other source currency/m² value
areaSquareMetersInterior floor area
terrainAreaSquareMetersPlot area when relevant
roomsRoom count classification
floorFloor classification
city, provinceLocality and Polish voivodeship
locationPathOrdered source location hierarchy
latitude, longitudeApproximate public coordinates when available
advertiserTypeAgency, developer, or private-owner classification
agencyPublic agency or developer metadata
contactAvailable public advertiser or assigned-agent metadata
descriptionSearch summary, or full plain text when enriched
attributesBuild year, heating, equipment, market, and other source attributes
featuresProperty tags and feature labels
imageUrlsPublic property photo URLs
createdAt, modifiedAtSource timestamps when available
sourceSearchUrlInput or paginated search URL that produced the record
scrapedAtTimestamp when this Actor produced the record

Otodom does not expose every field for every listing. Missing source values are returned as null, empty arrays, or empty objects rather than invented values.

Getting started

  1. Open an Otodom search in your browser.
  2. Apply the location, transaction, property type, price, room, or other filters you need.
  3. Copy the resulting https://www.otodom.pl/pl/wyniki/... URL.
  4. Add it to Otodom search or offer URLs.
  5. Choose a maxItems limit.
  6. Leave detail enrichment off for a fast inventory snapshot, or enable it for richer offer data.
  7. Click Start.
  8. Open the Property listings dataset view or export it in your preferred format.

The prefilled Lublin apartment search is a working example and can be run without editing any field.

Input parameters

startUrls

An array of public Otodom Poland URLs. Supported paths are:

  • Search results: https://www.otodom.pl/pl/wyniki/...
  • Individual offers: https://www.otodom.pl/pl/oferta/...

You can mix search and offer URLs in one run. Duplicate properties are emitted once by stable propertyId. Only HTTPS Otodom URLs are accepted; unrelated domains and unsupported paths fail validation. If omitted, the Actor uses a nationwide apartments-for-sale search.

maxItems

Maximum unique records saved across all start URLs. Allowed range: 1–1,000. Default: 20. The Actor stops fetching new result pages after reaching the limit.

includeDetails

When false, records come from structured search-page data and already include the main price, property, image, location, and advertiser fields.

When true, each search record is enriched from its public offer page with full descriptions, additional attributes, coordinates, image variants, and available public contact metadata. Offer URLs supplied directly are always parsed as detail pages.

maxConcurrency

Maximum simultaneous offer-page enrichment requests. Allowed range: 1–10. Default: 3. Lower values are gentler and often more reliable for long jobs. This setting does not increase search-page pagination concurrency.

Example input: Lublin apartments for sale

{
"startUrls": [
{
"url": "https://www.otodom.pl/pl/wyniki/sprzedaz/mieszkanie/lubelskie/lublin/lublin/lublin"
}
],
"maxItems": 25,
"includeDetails": false,
"maxConcurrency": 3
}

For rental data, use a real Otodom URL containing /wyniki/wynajem/. For another city or property type, build the search on Otodom and paste its URL unchanged.

Example output

{
"propertyId": "12345678",
"url": "https://www.otodom.pl/pl/oferta/bright-three-room-apartment-IDexample",
"title": "Bright three-room apartment with balcony",
"transaction": "SELL",
"propertyType": "FLAT",
"market": "secondary",
"price": { "value": 650000, "currency": "PLN" },
"rentPrice": { "value": 620, "currency": "PLN" },
"pricePerSquareMeter": { "value": 12500, "currency": "PLN" },
"areaSquareMeters": 52,
"terrainAreaSquareMeters": null,
"rooms": "THREE",
"floor": "SECOND",
"city": "Lublin",
"province": "lubelskie",
"locationPath": ["lubelskie", "Lublin", "Śródmieście"],
"latitude": 51.2465,
"longitude": 22.5684,
"advertiserType": "AGENCY",
"isPrivateOwner": false,
"agency": { "name": "Sample Property Agency", "type": "AGENCY" },
"contact": { "name": "Sample Agent", "phones": ["+48123456789"] },
"description": "Three-room apartment near public transport with a balcony.",
"attributes": { "build_year": "2020", "heating": "urban" },
"features": ["BALCONY", "PARKING_SPOT"],
"imageUrls": ["https://ireland.apollo.olxcdn.com/v1/files/sample/image"],
"createdAt": "2025-01-15T12:00:00Z",
"modifiedAt": "2025-01-16T09:30:00Z",
"sourceSearchUrl": "https://www.otodom.pl/pl/wyniki/sprzedaz/mieszkanie/lubelskie/lublin/lublin/lublin",
"scrapedAt": "2025-01-16T10:00:00Z"
}

The example is anonymized. Actual records contain current public source values.

How much does it cost to scrape Otodom properties?

The Actor uses pay-per-event pricing:

  • one start event per run;
  • one item event for each unique property record written to the dataset.

At the FREE-tier price of $0.005 per run plus $0.0023 per property, approximate Actor charges are:

Result volumeApproximate Actor charge
10 properties$0.0280
100 properties$0.2350
1,000 properties$2.3050

Paid Apify plans receive the decreasing item prices configured for their tier. Optional detail enrichment has no separate charge event, but it can take longer and use more source requests. Your final total can also include Apify platform usage according to your account and plan. Always check the live pricing shown on the Actor page before starting a large run.

Recurring Polish property market monitoring

The Actor returns current snapshots; it does not silently retain a cross-run property history or send built-in alerts. Use Apify schedules and your own stable-ID store to create monitoring:

  1. Save a filtered Otodom URL for the market segment.
  2. Schedule the Actor daily, weekly, or monthly.
  3. Export each dataset to a database, object store, or spreadsheet.
  4. Join snapshots on propertyId.
  5. Compare price.value, modifiedAt, availability, and newly appearing IDs.
  6. Trigger your own notification or dashboard refresh when the comparison meets your rules.

This separation keeps every run reproducible and avoids mixing old records into the current run dataset.

Spreadsheet and data-pipeline exports

From the dataset page, export results as JSON, CSV, Excel, XML, RSS, or HTML. For repeat automation, use a dataset API URL or an Apify integration.

Useful patterns include:

  • send a completed dataset to Google Sheets;
  • load daily snapshots into BigQuery, Snowflake, PostgreSQL, or S3;
  • call a webhook after each run;
  • connect Make, Zapier, n8n, or another automation tool;
  • ingest records into a property intelligence or lead-review workflow.

Nested fields such as price, agency, contact, and attributes are objects. Flatten them in your destination if a spreadsheet workflow requires scalar columns.

Run through the Apify API with cURL

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~otodom-property-scraper/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": [{
"url": "https://www.otodom.pl/pl/wyniki/wynajem/mieszkanie/lubelskie/lublin/lublin/lublin"
}],
"maxItems": 20,
"includeDetails": false
}'

Poll the returned run ID until it reaches a terminal status, then read its default dataset. Keep your Apify token in an environment variable or secret manager.

Run with JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/otodom-property-scraper').call({
startUrls: [{
url: 'https://www.otodom.pl/pl/wyniki/sprzedaz/mieszkanie/cala-polska',
}],
maxItems: 50,
includeDetails: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Collected ${items.length} Otodom properties`);

For asynchronous systems, use .start() instead of .call() and attach a webhook or poll the run.

Run with Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/otodom-property-scraper').call(run_input={
'startUrls': [{
'url': 'https://www.otodom.pl/pl/wyniki/sprzedaz/mieszkanie/cala-polska',
}],
'maxItems': 50,
'includeDetails': False,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(f'Collected {len(items)} Otodom properties')

Use the stable propertyId field when upserting records into your destination.

Use with Apify MCP

Add the Actor to Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/otodom-property-scraper"

Claude Desktop setup

Add this HTTP server to the mcpServers object in Claude Desktop configuration:

{
"mcpServers": {
"apify": {
"type": "http",
"url": "https://mcp.apify.com?tools=automation-lab/otodom-property-scraper"
}
}
}

Cursor setup

Open Cursor Settings → MCP → Add new global MCP server and use the same apify HTTP configuration above. Restart the MCP connection after saving it.

VS Code setup

Add the same server object under servers.apify in your workspace or user MCP configuration, with type set to http and the Actor-specific URL shown above. Start the server from the VS Code MCP servers view.

Example prompts to ask through MCP:

  • “Using the Apify MCP Otodom tool, collect 20 current apartments for sale in Lublin from this filtered URL and summarize median PLN per square metre.”
  • “Run the Otodom property scraper through MCP for five enriched rental listings and compare public amenities.”
  • “Use MCP to start the Otodom property scraper with my saved search URL and return the dataset link.”

The Actor only supports workflows represented by its input schema; an MCP prompt does not add unsupported filtering or alert features.

Reliability and retries

The Actor uses a lightweight direct request with a browser-like HTTP stack. If Otodom returns a temporary block, rate limit, network failure, or server error, it makes a bounded fresh direct request after backoff. The working route needs neither a browser nor proxy transfer, which keeps normal and enriched runs economical.

Search pages are fetched sequentially. Detail pages use the bounded maxConcurrency value. Transient failures are retried twice. Deterministic invalid URLs and missing offers are not retried indefinitely.

When optional detail enrichment fails for one offer, the Actor logs a warning and preserves the useful search-page record. A challenged or structurally unexpected search page is treated as an error, not as a successful empty result.

Limits and source behavior

  • The Actor supports public Polish Otodom search and offer pages only.
  • Otodom may change fields, categories, URL structures, or availability without notice.
  • Search ordering can change while long pagination jobs are running.
  • Promoted listings can appear alongside ordinary results.
  • Duplicate IDs are removed within one run.
  • Phone numbers, coordinates, descriptions, and agency details are returned only when publicly exposed by the source.
  • Photo URLs are collected, but the Actor does not download or archive image binaries.
  • maxItems is capped at 1,000 per run to keep jobs bounded.
  • Built-in historical storage, change alerts, valuation models, and owner identity inference are not provided.

For large recurring jobs, split work by meaningful Otodom search filters rather than repeatedly requesting one extremely broad search.

Troubleshooting

Why did the Actor return fewer records than maxItems?

The search may contain fewer unique public listings, the supplied page may be near the end of pagination, or several start URLs may overlap. Check the original Otodom URL in a browser and inspect run warnings.

Why is a field null?

Otodom does not expose every attribute for every property. Enable includeDetails for additional offer-page fields, but do not expect private or absent source data to appear.

Why did my input fail immediately?

Only HTTPS URLs on otodom.pl or www.otodom.pl are accepted. Use a /pl/wyniki/ search URL or /pl/oferta/ property URL copied from Otodom.

Why is an enriched record missing some detail fields?

The source can remove an offer between search discovery and the detail request, or a detail request can fail after retries. The Actor intentionally preserves the valid search record and logs the enrichment warning.

How should I detect price changes?

Schedule repeat runs, store each snapshot externally, and compare price.value by stable propertyId. The Actor does not compare past runs automatically.

Responsible use and legality

This Actor extracts publicly available property information. You are responsible for complying with Otodom terms, applicable law, database rights, privacy rules, and the rules governing your downstream use.

Collect only what you need. Do not use public contact details for spam, harassment, unlawful profiling, or discriminatory housing decisions. Protect exported personal data, set appropriate retention periods, and honour valid deletion or access requests where applicable. The Actor does not bypass logins or access private account data.

These are separate sources and datasets. They are not merged into Otodom results automatically.

FAQ

Does this provide an official Otodom API?

No. It provides an Actor and dataset API over public Otodom pages. It is not affiliated with or endorsed by Otodom.

Can I paste a filtered Otodom URL?

Yes. That is the recommended way to specify locations, transactions, property types, prices, rooms, and other source filters.

Can I scrape one property?

Yes. Pass its public /pl/oferta/ URL in startUrls. An individual offer is parsed as a detailed record.

Does it support Otodom mieszkania and rentals?

Yes. Use a real apartment search URL for sale (sprzedaz) or rent (wynajem). The same input pattern works for supported Otodom locations and property categories.

Does it download photos?

No. It returns public photo URLs, avoiding unnecessary storage and transfer.

Can I schedule it?

Yes. Use an Apify schedule, then store or compare datasets in your own monitoring workflow.

Is every public contact guaranteed?

No. Contacts appear only when the current public source record exposes them.

What happens when Otodom blocks a request?

The Actor retries transient failures with fresh direct HTTP requests and bounded backoff. If retries are exhausted, the run fails rather than claiming that a challenged page contains zero listings.