# Sreality.cz Listings Scraper (`nice_dev/sreality-listings-scraper`) Actor

Scrape Sreality.cz property listings (sale, rent, auction; apartments, houses, land, commercial) by locality name or search URL: price, m², layout, GPS, photos, description, seller contact.

- **URL**: https://apify.com/nice\_dev/sreality-listings-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Real estate, Lead generation, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.39 / 1,000 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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🏠 What is Sreality Listings Scraper?

**Sreality Listings Scraper** extracts **property listings from [Sreality.cz](https://www.sreality.cz)**, the largest real-estate portal in the Czech Republic: **price, price per m², layout (1+kk, 2+1…), usable and plot area, floor, full address with GPS coordinates, building details, energy rating, photos, description, nearby public transport and the seller's contact**, for sale, rent, auctions and ownership shares; apartments, houses, land, commercial premises, garages and more.

Type one or **several region, city, city part or street names** (`Praha`, `Brno`, `Karlín`, `Praha 5`, `Jihomoravský kraj`) or paste any Sreality search URL, click **Start**, and download the listings in JSON, CSV or Excel. Schedule it with **Only new listings** to get, at each run, only what was not delivered before. No login needed, and it is **fast (about 150 listings with full details a minute, 3,000 without them in under a minute) and cheap**.

### 📋 What data can you extract from Sreality?

One item per listing, 119 fields:

| Category | What you get |
| --- | --- |
| 💰 **Price** | price in CZK, price per m², previous price (discounts), price note, price on request, negotiable, monthly charges and deposit (rent), agency commission |
| 📐 **Property** | sale, rent, auction or share; apartment, house, land, commercial or other; layout (1+kk, 2+1…), rooms, usable, floor, plot, garden, balcony and terrace areas, floor and floors of the building |
| 🏢 **Building** | building type, condition, ownership, furnished, energy rating and its PDF, year built and renovated, house type and position |
| ✨ **Features** | lift, balcony, terrace, loggia, cellar, garage, parking, pool, low-energy, wheelchair access; heating, water, electricity, gas, sewage, telecom |
| 📍 **Location** | full address, street and house number, city, city part, quarter, district, region, ZIP, GPS coordinates and their precision, Sreality's ids of every level |
| 🚌 **Neighbourhood** | 13 walking distances (metro, bus, school, shop, doctor…), the nearest stops with their line numbers, the closest named place of about 21 kinds with its rating |
| 🖼️ **Media** | every photo in full size with the room type Sreality's classifier sees and its caption, video, 3D tour |
| 📞 **Seller** | agency or private seller, agency name, website, logo, IČO, review score, Sreality page, agent id, contact name, e-mail, phone numbers — plus, as an option, the e-mails published on the agency's own website |
| 🕒 **Dates** | **first publication (true age of the listing)**, last update, view count |
| 📝 **Text** | title, full description, keywords, the agency's own reference |

Every field, with an example, is listed in the **Output** section below.

Fields marked **detail** in the Output tab (`description`, building details, exact areas, `floor`, dates, `viewCount`, `contactName`, `phones`, `imageCaptions`, `nearbyTransport`, `nearbyPlaces`) are filled when **Extract details** is on (default). Turn it off for a search-card-only scrape: 1 request per 200 listings, same price — the card already carries every photo with its room type, the ids and the 13 distances.

### ✅ Why use Sreality Listings Scraper?

- 🚀 **Fast**: about 150 listings with full details a minute (1,000 in about 6 minutes), 3,000 without them in under a minute; a whole-country search (22 000+ apartments) runs to completion on its own past Sreality's 10 000-result cap — raise **Max requests per minute** to shorten it.
- 🎯 **Type the place, not an id**: `Brno`, `Karlín`, `Praha 5`, `Plzeň-město`, `Jihomoravský kraj` or a street name are resolved through Sreality's own locality search, with an optional **radius in km** around a city, city part or street.
- 🗺️ **Several searches in one run**: up to 100 locations × several transactions (sale, rent…) × several property types (apartments, houses, land…), with a **cap per search** so that Prague does not eat the whole budget.
- 🔔 **Monitoring built in**: **Only new listings** remembers what it delivered; the next scheduled run saves — and charges — only what is new.
- 📅 **Any date range**: `postedAfter` / `postedBefore` take a date or a period (`3 days`, `2 weeks`); Sreality filters by age itself, so listings outside the range are never downloaded.
- 🧑 **Private sellers only**: skip the agencies (93 % of the site) without paying for them.
- 🔗 **Or paste any Sreality URL**: Czech or English search pages (every filter is kept) or single listings.
- 🧩 **Beyond the 10 000-result limit**: Sreality serves at most 10 000 results per search; the Actor splits bigger searches by region (plus the listings Sreality places abroad), then by layout, automatically.
- 🕒 **Real listing age and popularity**: `publishedAt`, `updatedAt` and `viewCount` from the listing itself.
- 💶 **Price intelligence**: `pricePerM2`, `priceOld` (discounts), `priceNote`, `isPriceOnRequest`, monthly charges and deposit for rentals.
- 🚌 **Neighbourhood**: 13 walking distances (metro, bus, school, shop, doctor…), the nearest public-transport stops with their line numbers, and the closest named place of about 21 kinds with its rating.
- 🖼️ **Photos you can sort**: every photo comes with the room type detected by Sreality's image classifier and with its caption.
- 🌐 **Czech or English labels**: `language: en` returns Sreality's own English titles and codebook names.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…), proxy rotation and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Sreality

1. Create a free Apify account.
2. Open **Sreality Listings Scraper**, type a **Location** (e.g. `Praha`) — add more under **More locations** —, choose one or several **transactions** (sale / rent / auction / share) and **property types** (apartments, houses, land, commercial, other), optionally pick **layouts / sub-types** and filters (price, area, plot area, radius, ownership, condition, building type, furnished, must-have features, keyword, sort, dates, private sellers only).
3. Or paste your own Sreality URLs into **Start URLs**: any search results page (all filters set on the site are kept, pagination is automatic), single listing pages or API search URLs.
4. Set **Max listings** (100 by default, 0 = no limit) and click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Sreality?

This Actor uses **pay per event** pricing — details included:

| Apify plan | Price per 1,000 listings |
| --- | --- |
| Free | **$0.45** |
| Bronze | $0.43 |
| Silver | $0.41 |
| Gold | $0.39 |

Plus **$0.0015 per run start** (15 cents per 100 runs). Platform usage (compute, proxy) is included in the price.

- All 5,500 apartments for sale in Prague ≈ **$2.50**.
- A daily monitor of 300 new listings ≈ **$0.14** a day.
- The $5 of free credits every Apify account starts with already cover about **11,000 listings**.

The filters the Actor applies itself: a listing you keep costs its normal price, a listing a filter drops costs **$0.40 per 1,000** when **Private sellers only (no agencies)** or **Exclude keywords** drops it ($0.39 on Bronze, $0.38 on Silver, $0.37 on Gold), and **$0.40 per 1,000** when **Posted after** / **Posted before**, checked again on the listing page with **Extract details** on, drops it ($0.38 on Bronze, $0.36 on Silver, $0.34 on Gold). A listing they drop is never saved nor charged as a listing — filtering never costs more than taking everything. The filters Sreality applies itself (price, area, layout, dates sent as an age…) cost nothing, and you never pay twice for the same listing (`onlyNew`).

**Find e-mails on agency websites** (off by default) is included in the same price: no extra charge. On a sample of 300 apartments in Prague, Brno and Ostrava it added an address from the agency's own website to about two listings in three.

### ⚙️ Input

```json
{
    "location": "Brno",
    "transactions": ["pronajem"],
    "propertyTypes": ["byty"],
    "subtypes": ["2+kk", "2+1", "3+kk"],
    "priceMax": 25000,
    "radiusKm": 5,
    "sortBy": "PRICE_ASC",
    "language": "en",
    "maxItems": 200,
    "extractDetails": true
}
```

Several searches in one run (3 locations × 2 transactions = 6 searches, 50 listings each), new listings only:

```json
{
    "locations": ["Brno", "Plzeň", "Karlín, Praha"],
    "transactions": ["prodej", "pronajem"],
    "propertyTypes": ["byty"],
    "maxItems": 0,
    "maxItemsPerQuery": 50,
    "postedAfter": "7 days",
    "privateSellersOnly": false,
    "onlyNew": true,
    "stateKey": "three-cities"
}
```

Or with start URLs:

```json
{
    "startUrls": [
        { "url": "https://www.sreality.cz/hledani/prodej/domy/stredocesky-kraj?stav=novostavba&cena-do=12000000" },
        { "url": "https://www.sreality.cz/en/search/to-rent/apartments/praha?disposition=1+kt,2+kt&max-price=20000" },
        { "url": "https://www.sreality.cz/detail/prodej/byt/4+kk/praha-dolni-mecholupy-kryspinova/3166892108" }
    ],
    "maxItems": 500
}
```

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `startUrls` | array | — | Sreality search / listing / API URLs. When set, the search fields are ignored; dates, the Actor's filters, `maxItemsPerQuery` and `onlyNew` still apply. |
| `location`, `locations` | string, array | — (whole Czech Republic) | Region, district, city, city part or street names; one search per location (max 100). An unknown name stops the run before anything is charged. |
| `transactions` | array of `prodej` | `pronajem` | `drazby` | `podily` | `["prodej"]` | Sale, rent, auction, ownership share; one search each. |
| `propertyTypes` | array of `byty` | `domy` | `pozemky` | `komercni` | `ostatni` | `["byty"]` | Apartments, houses, land, commercial, other; one search each. |
| `subtypes` | array | — | Layouts (`1+kk` … `6-a-vice`, `atypicky`, `pokoj`) or sub-types (`rodinny`, `vila`, `bydleni`, `kancelare`, `garaz`…); each property type keeps its own. |
| `maxItems` | integer | `100` | 0 = no limit. |
| `maxItemsPerQuery` | integer | `0` | Cap for each search (or each search URL). 0 = none. |
| `priceMin`, `priceMax` | integer | — | CZK (monthly rent for rentals). |
| `areaMin`, `areaMax` | integer | — | m², usable area (plot area for land). |
| `plotAreaMin`, `plotAreaMax` | integer | — | m², plot area of houses, land, commercial and other properties. |
| `houseRooms` | array of `1`…`5`, `atypical` | — | Number of rooms, houses only. |
| `radiusKm` | integer | `0` | Radius around a city, city part or street. |
| `ownership`, `condition`, `buildingType`, `furnished`, `features`, `sortBy`, `keyword`, `searchQueries` |  |  | Sreality's own filters and sort orders; `searchQueries` = several keywords, one search each. |
| `postedAfter`, `postedBefore` | date or period | — | `2026-09-01`, `3 days`, `2 weeks`, `1 month`. Whole days (Sreality publishes the day, not the hour), read from `publishedAt`. |
| `privateSellersOnly` | boolean | `false` | Only listings posted by private persons; agencies are skipped for free. |
| `excludeKeywords` | array | — | Drop listings whose title contains one of these words (case and accents ignored). |
| `onlyNew`, `stateKey`, `resetState` | boolean, string, boolean | `false`, `default`, `false` | Only listings no previous run with the same `stateKey` delivered. |
| `language` | `cs` | `en` | `cs` | Language of titles and codebook names. |
| `extractDetails` | boolean | `true` | Off = search-card fields only. |
| `enrichEmails` | boolean | `false` | Visit each agency's website (3 pages max, once per agency and run) for the addresses it publishes: `websiteEmails`. Needs `extractDetails`. |
| `privateSellerContacts` | boolean | `true` | Off = name / e-mail / phone of private sellers set to null. |
| `proxyConfiguration`, `maxConcurrency`, `maxRequestsPerMinute`, `maxRequestRetries`, `pageSize`, `debugLog` |  |  | Advanced. Start with the default Apify proxy; switch to residential if you see blocked requests. |

### 📦 Output

One item, shortened to its main fields (the table below names all 119):

```json
{
    "id": 3166892108,
    "url": "https://www.sreality.cz/detail/prodej/byt/4+kk/praha-dolni-mecholupy-kryspinova/3166892108",
    "title": "Prodej bytu 4+kk 107 m²",
    "transaction": "sale",
    "category": "flat",
    "subtype": "4+kt",
    "disposition": "4+kk",
    "rooms": 4,
    "price": 14490000,
    "currency": "CZK",
    "pricePerM2": 135421,
    "isPriceOnRequest": false,
    "area": 107,
    "floor": 1,
    "buildingFloors": 5,
    "buildingType": "Cihlová",
    "buildingCondition": "Velmi dobrý",
    "ownership": "Osobní",
    "energyRating": "B - Velmi úsporná",
    "elevator": true,
    "balcony": true,
    "garage": true,
    "location": "Kryšpínova 619/5, Praha 10 - Dolní Měcholupy",
    "city": "Praha",
    "district": "Praha 10",
    "region": "Hlavní město Praha",
    "regionId": 10,
    "districtId": 5010,
    "latitude": 50.067023,
    "longitude": 14.550407,
    "imageRoomTypes": ["living_room", "living_dining_room", "dining_room", "kitchen"],
    "imageCaptions": ["Obývací pokoj", "Obývací pokoj", "Obývací pokoj", "Obývací pokoj - kuchyňská linka"],
    "imageCount": 31,
    "sellerType": "agency",
    "isPrivateSeller": false,
    "agencyUrl": "https://www.sreality.cz/adresar/remax-g8-reality/17959",
    "brokerId": 313760,
    "agencyName": "REMAX G8 REALITY",
    "agencyReviewScore": 4.7,
    "contactName": "Jan Novák",
    "phones": ["+420777123456"],
    "publishedAt": "2026-06-23",
    "updatedAt": "2026-09-15",
    "viewCount": 10589,
    "poiDistances": { "metro": 2658, "busStop": 210, "school": 413, "shop": 74 },
    "nearbyTransport": [{ "name": "Kardausova", "distance": 210, "lines": ["173", "204", "229"] }],
    "nearbyPlaces": [
        {
            "type": "small_shop",
            "name": "Globus Hypermarket",
            "distance": 781,
            "rating": 4,
            "url": "https://www.firmy.cz/detail/13484528-globus-hypermarket-praha-sterboholy.html"
        }
    ],
    "description": "Hledáte moderní rodinné bydlení…",
    "language": "cs",
    "scrapedAt": "2026-09-16T00:41:12.345Z"
}
```

#### All 119 fields

| Field | Example |
| --- | --- |
| `id`, `url`, `title` | `3166892108`, `https://www.sreality.cz/detail/prodej/byt/4+kk/praha-dolni-mecholupy-kryspinova/3166892108`, `Prodej bytu 4+kk 107 m²` |
| `transaction`, `category`, `subtype`, `subtypeName`, `disposition`, `rooms` | `sale`, `flat`, `4+kt`, `4+kk`, `4+kk`, `4` |
| `transactionId`, `categoryId`, `subtypeId` | `1`, `1`, `8` — Sreality's own numeric codes |
| `price`, `currency`, `priceCzk`, `pricePerM2`, `priceUnit`, `isPriceOnRequest` | `14490000`, `CZK`, `14490000`, `135421`, `za nemovitost`, `false` |
| `priceOld`, `isDiscounted`, `priceNegotiable`, `priceNote`, `costOfLiving`, `deposit`, `commission` | previous price before a discount, discount flag, negotiable flag, fee notes, monthly charges (rent), deposit (rent), agency commission note (rent) |
| `area`, `floorArea`, `plotArea`, `gardenArea`, `balconyArea`, `terraceArea`, `floor`, `buildingFloors` | `107`, `107`, `null`, `null`, `15`, `null`, `1`, `5` |
| `buildingType`, `buildingCondition`, `ownership`, `furnished`, `energyRating`, `energyCertificateUrl`, `acceptanceYear`, `reconstructionYear`, `houseType`, `housePosition` | `Cihlová`, `Velmi dobrý`, `Osobní`, `null`, `B - Velmi úsporná`, PDF link, `2018`, `null`, `Patrový` (houses), `Samostatný` (houses) |
| `elevator`, `balcony`, `terrace`, `loggia`, `cellar`, `garage`, `parking`, `pool`, `lowEnergy`, `wheelchairAccess`, `exclusiveAtAgency` | booleans |
| `heating`, `water`, `electricity`, `gas`, `sewage`, `transport`, `telecommunication`, `keywords` | `["Centrální dálkové","Radiátory"]`, … |
| `location`, `street`, `houseNumber`, `city`, `cityPart`, `quarter`, `ward`, `municipality`, `district`, `region`, `zip`, `country` | `Kryšpínova 619/5, Praha 10 - Dolní Měcholupy`, `Kryšpínova`, `619/5`, `Praha`, `Dolní Měcholupy`, `Praha-Dolní Měcholupy`, `null`, `null`, `Praha 10`, `Hlavní město Praha`, `11101`, `Česká republika` |
| `latitude`, `longitude`, `gpsAccuracy` | `50.067023`, `14.550407`, `gps` |
| `regionId`, `districtId`, `municipalityId`, `quarterId`, `wardId` | `10`, `5010`, `3468`, `135`, `14949` — Sreality's ids of the places, to join runs or to group by area |
| `mainImage`, `images`, `imageCount`, `videoUrl`, `matterportUrl`, `hasVideo`, `hasMatterport` | full-size photo URLs, video, 3D tour |
| `imageRoomTypes`, `imageCaptions` | one value per photo, in the order of `images`: what Sreality's image classifier sees (`living_room`, `kitchen`, `bathroom`, `floor_plan_2d`, `outdoor_building`… 32 values) and the caption written on the listing (`Obývací pokoj`, `Ložnice`) |
| `sellerType`, `isPrivateSeller`, `agencyId`, `agencyName`, `agencyWebsite`, `agencyLogo`, `agencyReviewScore`, `agencyReviewCount`, `agencyIco` | `agency`, `false`, `17959`, `REMAX G8 REALITY`, `https://www.remaxg8reality.cz`, logo URL, `4.7`, `2`, `01913638` |
| `agencySeoName`, `agencyUrl`, `brokerId` | `remax-g8-reality`, `https://www.sreality.cz/adresar/remax-g8-reality/17959`, `313760` |
| `contactName`, `contactEmail`, `phones`, `advertCode` | `Jan Novák`, `jan.novak@example-reality.cz`, `["+420777123456"]`, `0020-NP11251` |
| `websiteEmails`, `emailSource` | with **Find e-mails on agency websites**: `["info@callidoreality.cz"]`, `https://www.callidoreality.cz/` — the addresses the agency publishes on its own website |
| `publishedAt`, `updatedAt`, `viewCount` | `2026-06-23`, `2026-09-15`, `10589` — **the real age of the listing and its popularity** |
| `poiDistances`, `nearbyTransport`, `nearbyPlaces` | `{"metro":2658,"busStop":210,"school":413,…}` (13 distances in meters), `[{"name":"Kardausova","distance":210,"lines":["173","204"]}]`, `[{"type":"small_shop","name":"Globus Hypermarket","distance":781,"rating":4,"url":"https://www.firmy.cz/…"}]` (the closest place of about 21 kinds) |
| `description`, `language`, `searchUrl`, `scrapedAt` | full text, `cs`/`en`, the search it came from (group by it to count per search), ISO timestamp |

### 💡 Tips

#### Several searches in one run

Every combination of **location × transaction × property type × keyword** is its own search (max 500 per run), with its own pagination and its own counter. `maxItemsPerQuery` caps each of them, `maxItems` caps the run. A listing found by two searches is saved — and charged — once, for the search that saw it first. The `searchUrl` field of each listing tells which search it came from, and the log ends with the count per search.

#### Monitoring: only the new listings

Turn **Only new listings** on and schedule the Actor. The ids of the listings it delivers are kept in a named key-value store (`sreality-listings-scraper-seen`, one record set per `stateKey`, up to 150 000 ids). At the next run the listings already delivered are skipped from the search results: not opened, not saved, not charged. An id is remembered only once the listing is written to the dataset, so a failed run loses nothing. Give each schedule its own `stateKey`; `resetState` starts over. With the default sort order the run stops paginating after 400 already-delivered listings in a row (Sreality puts the listings updated today among the new ones, so one page is not enough to conclude).

#### Filter by publication date

`postedAfter` and `postedBefore` take a date (`2026-09-01`) or a period before now (`3 days`, `2 weeks`, `1 month`). They are sent to Sreality as an age in days, so the listings outside the range are never downloaded and never charged; with **Extract details** on, the day is checked again on `publishedAt`. Sreality publishes the **day** of first publication, not the hour: both bound days are included. `postedBefore: "60 days"` finds what has been on the market for two months.

#### More tips

- **Monitor new listings**: `onlyNew: true`, a `stateKey` per schedule, the default sort order, and a daily schedule. Add `postedAfter: "7 days"` to ignore old listings that are new to your memory only.
- **Whole country**: leave `location` empty. Searches above 10 000 results are split by region (plus abroad) and layout automatically; you can also narrow by `priceMin`/`priceMax`.
- **Owners, not agencies**: `privateSellersOnly: true`. About 7 % of the listings; the other 93 % cost nothing.
- **Cheaper market scans**: `extractDetails: false` returns price, layout, area (from the title), GPS, address, ids, every photo with its room type and the POI distances with a single request per 200 listings.
- **Prague districts**: `Praha 5` is a quarter, `Karlín` a ward, `Praha` the whole region. `radiusKm` applies to cities, quarters, wards and streets, not to regions or districts.
- **Private sellers**: about 7 % of listings. Their name, phone and e-mail are personal data; keep `privateSellerContacts` on only when you have a lawful basis to process them.

### 🔌 Integrations and API

Run it from the Apify API or SDKs (JavaScript, Python), schedule it, or connect it to Make, Zapier, n8n, Google Sheets, Slack, webhooks. Every run exposes its dataset in JSON, CSV, Excel, XML and RSS.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Sreality listing. Actor id: `nice_dev/sreality-listings-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/sreality-listings-scraper`.

Smallest input, for a cheap first call:

```json
{
    "location": "Praha",
    "maxItems": 10
}
```

Key output fields: `url`, `title`, `price`, `currency`, `disposition`, `area`, `city`, `publishedAt`.

Cost: $0.45 per 1,000 listings plus $0.0015 per run start ($0.39 per 1,000 on the Gold plan); a listing a filter of the Actor drops costs a filter fee, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

**Does it need a login or a proxy?** No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session (without a proxy, after a pause of 5 seconds, doubled at each retry up to 20 seconds).

**Why is a listing missing from the results?** Sreality inserts new listings while a run paginates; the Actor deduplicates by id but a listing published during the run may appear on the next run only. Listings removed between the search and the detail request are not saved: the run counts them apart ("N no longer on Sreality" in its last line, never as failed requests) and lists them in the `FAILED_REQUESTS` record.

**Is it legal to scrape Sreality?** The Actor only reads what Sreality shows publicly to any anonymous visitor. It logs in to nothing. Results can contain personal data — the name, phone and e-mail of private sellers and of brokers — which is protected by GDPR: do not store it without a legitimate reason, and turn `privateSellerContacts` off if you do not need it. You are responsible for using the data in compliance with Sreality's Terms of Use and applicable law. This Actor is not affiliated with Sreality or with Seznam.cz.

**Where do the agency e-mails come from?** With `enrichEmails` on, the Actor reads the pages each agency publishes on its own website (home page, contact page, legal notice; 3 pages at most, once per agency and per run) and returns the contact addresses shown there — what any visitor sees: the agency's general address, often other brokers' addresses too. It does not log in, guess addresses or read contact forms. Some of these addresses are personal data under GDPR (`firstname.lastname@…`): you remain responsible for having a lawful basis before using them, for informing the people concerned and for honouring opt-outs.

**Is the data safe to open in Excel or to show on a web page?** Titles and descriptions are the sellers’ own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a title such as `-20 % dnes`, a phone number): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number, and an `advertCode` such as `0020-NP11251` as a date. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every field that holds a URL (`url`, `images`, `videoUrl`, `agencyWebsite`, `energyCertificateUrl`…) is an http(s) URL or `null`, never another kind of link. On a web page, escape every field like any text written by a stranger.

**Why do some fields stay null?** They are filled from the listing detail (turn **Extract details** on) or simply not published by the seller (`furnished`, `reconstructionYear`, `energyRating`…). `price: null` with `isPriceOnRequest: true` means "price on request".

**Known limitations**

- Dates are whole days: Sreality publishes the day a listing was first posted, not the hour. With **Extract details** off the date range is applied by Sreality only, and `publishedAt` stays null.
- `onlyNew` with a low `maxItems`: what lies under 400 already-delivered listings in a row is never read — that is what "new" means. The run does not stop sooner, even when `maxItems` is lower: Sreality's default order puts the listings updated today among the new ones (runs of 78 already-delivered listings above a new one were measured in Prague), so a capped run may also save older listings that no previous run delivered, rather than miss a new one. Two runs at the same time on the same `stateKey` may return a listing twice. A run that finds nothing new still makes a few requests.
- Overlapping searches with a cap per search: a shared listing counts for the search that saw it first.
- `privateSellersOnly` reads the search results to find the 7 % of private sellers: on a search above 10 000 results Sreality only serves the first 10 000, so narrow it by location or price if you need them all.
- A single search is capped at 10 000 results by Sreality; the Actor splits by region (plus the listings Sreality places abroad), then by layout, and warns when a piece is still too big (narrow it by price or sub-type).
- The locality lookup uses Sreality's own suggest service: if it is unreachable, the run fails with a clear network message — retry later or paste a search URL.
- Listings removed between the search and the detail request are not saved: counted apart from failures ("no longer on Sreality") and listed in `FAILED_REQUESTS`.

**A run stopped without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the listings already saved are skipped: none is delivered or charged twice, and **Max items** still counts them.
- With **Only new listings**, the memory of what was delivered is saved once a minute too: resurrect the stopped run and the listings it had saved meanwhile join the memory; leave it stopped for good, and the next run may return up to a minute of them once more.

#### Something doesn't work?

The last line of the log counts the listings saved, filtered out, already delivered and no longer on Sreality (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed listings are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause (a search Sreality refuses says so, instead of "run it again"). A run that saved some listings fails too when at least as many requests failed for good as were read: a green run with a short dataset would hide the outage. One failed request among many is only a warning.

If Sreality changes its pages, you are told instead of paying for blank rows. A results page that counts listings but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No listings found". If the first 20 listings read all lack their title, city, GPS position or photos — or, with **Extract details** on, their publication day or description — the run saves nothing more, stops and fails, and its last message names the missing field: at most those first listings are charged.

### 🛟 Support

Something doesn't work, a field is missing, or Sreality changed its pages? Open an issue in the **Issues** tab of this Actor with a link to your run: the run log and the `FAILED_REQUESTS` record in the key-value store are usually enough to fix it quickly. Feature requests are welcome in the same place.

# Actor input Schema

## `startUrls` (type: `array`):

Sreality.cz search-result URLs (`https://www.sreality.cz/hledani/...` or `/en/search/...`, every filter set on the site is kept, pagination is automatic), single listing URLs (`https://www.sreality.cz/detail/.../<id>`) or raw API search URLs (`https://www.sreality.cz/api/v1/estates/search?...`). Max 1 000 URLs. When this list is not empty, the search fields (locations, transaction, property type, site filters, sort) are ignored; the dates, the Actor's filters, **Max listings per search** and **Only new listings** still apply.

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

Region, district, city, city part or street name, e.g. `Praha`, `Brno`, `Karlín`, `Jihomoravský kraj`, `Praha 5`, `Plzeň-město`. Empty = whole Czech Republic. Resolved through Sreality's own location search: the exact name typed wins even when Sreality ranks a longer, similarly-spelled place first; a name shared by several places (there are several `Kamenice`) is told apart by adding a nearby town or region (`Kamenice, Benešov`). Combine with 'Radius (km)' for a circle around a city, city part or street.

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

Several locations in one run: one search per location (times each transaction, property type and keyword; max 500 searches). Added to **Location**. A listing found by several searches is saved once; an unknown location stops the run before anything is charged.

## `transactions` (type: `array`):

Sale (`prodej`), rent (`pronajem`), auction (`drazby`) or ownership share (`podily`). Several allowed: one search each. Empty = sale.

## `propertyTypes` (type: `array`):

Sreality main category. Several allowed: one search each. Empty = apartments.

## `subtypes` (type: `array`):

Optional sub-types (several allowed, OR); each property type keeps its own. Apartments: layout `1+kk`…`6-a-vice`, `atypicky`, `pokoj` (room share). Houses: `rodinny`, `vila`, `chalupa`, `chata`… Land: `bydleni` (building plot), `komercni`, `pole`, `les`… Commercial: `kancelare`, `sklad`, `obchodni-prostor`… Other: `garaz`, `garazove-stani`… A sub-type of no chosen property type is ignored with a warning.

## `maxItems` (type: `integer`):

Maximum number of listings to save (after deduplication). 0 = no limit. For reference: apartments for sale in Prague ≈ 5 500 listings, whole Czech Republic ≈ 22 000. Searches above 10 000 results are split automatically (by region, then by country for the properties Sreality lists outside the Czech Republic) so the whole search is still reached; the rare case a split cannot cover is reported instead of dropped silently.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (one location × transaction × property type × keyword, or one search URL), so that the first search cannot use up the whole **Max listings** budget. 0 = no per-search cap.

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

Minimum total price (sale) or monthly rent (rent), in CZK.

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

Maximum total price (sale) or monthly rent (rent), in CZK.

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

Minimum usable area in m² (plot area for `pozemky`).

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

Maximum usable area in m² (plot area for `pozemky`).

## `plotAreaMin` (type: `integer`):

Minimum plot (land) area in m², for houses, land, commercial and other properties. Ignored for apartments.

## `plotAreaMax` (type: `integer`):

Maximum plot (land) area in m², for houses, land, commercial and other properties. Ignored for apartments.

## `houseRooms` (type: `array`):

Houses only: number of rooms (several allowed, OR). Apartments use **Layout / sub-type** instead.

## `radiusKm` (type: `integer`):

Search radius around each location, in km (0 = exact administrative area). Only applies to a city, city part or street, not to a region or district.

## `ownership` (type: `string`):

Apartments and houses: personal (`osobni`), cooperative (`druzstevni`) or state/municipal (`statni-obecni`) ownership.

## `condition` (type: `array`):

Condition of the property (several allowed, OR).

## `buildingType` (type: `array`):

Construction material / type (several allowed, OR).

## `furnished` (type: `string`):

Rentals: furnished, unfurnished or partly furnished.

## `features` (type: `array`):

Required features (several allowed, AND).

## `keyword` (type: `string`):

Full-text word searched in listing descriptions (Sreality's own filter), e.g. `balkon`, `garáž`, `metro`.

## `searchQueries` (type: `array`):

Several keywords in one run: one search per keyword (times each location, transaction and property type). Added to **Keyword in description**.

## `sortBy` (type: `string`):

Order of the results (matters when maxItems is lower than the number of matching listings). The site's default puts the listings published or updated last first; keep it for **Only new listings**.

## `postedAfter` (type: `string`):

Only listings first published on or after this day: `2026-09-01`, or a period before now such as `7 days`, `2 weeks`, `1 month` (API: `24 hours` and full ISO date-times work too). Sreality gives the day of publication, not the hour: the whole day of the bound is included. Read from the listing's `publishedAt`.

## `postedBefore` (type: `string`):

Only listings first published on or before this day (the whole day is included), or older than a period such as `30 days`: finds the listings that have been on the market for a long time.

## `privateSellersOnly` (type: `boolean`):

Keep only the listings posted by private persons, about 7 % of the site. Agency listings are skipped from the search results, before their page is opened: not saved. Each agency listing dropped is charged a filter fee, lower than a listing; a listing you keep costs its normal price (see Pricing).

## `excludeKeywords` (type: `array`):

Drop the listings whose title contains one of these words (case and accents ignored), e.g. `dražba`, `podíl`, `rezervace`.

## `onlyNew` (type: `boolean`):

Skip the listings that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and their page is not even opened. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new listings**. Give each schedule / task its own key (e.g. `praha-rentals`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every listing again. Untick it afterwards.

## `language` (type: `string`):

Language of the site's own texts in the output: title, layout / sub-type / condition names (`cs` = Czech, `en` = English). Descriptions are written by the sellers and stay as published.

## `extractDetails` (type: `boolean`):

Open each listing (1 extra request per listing) for the description, exact usable / plot area, floor, building type and condition, ownership, energy rating, equipment (heating, water…), publication and update dates, view count, seller name / phone / e-mail, agency rating, photo captions, video, 3D tour, nearby public transport and named places. Off = search-card fields only (price, layout, GPS, address, all photos with their room type, POI distances, agency and broker ids): 1 request per 200 listings, same price.

## `enrichEmails` (type: `boolean`):

Visits the website of each listing's agency (home page + contact / legal pages, 3 pages max, once per agency and per run) and adds the e-mail addresses published there to `websiteEmails` — the agency's general address, other brokers (the broker's own e-mail is already in `contactEmail`). Needs **Extract details** (the agency website is only on the listing page); private sellers have no website. Slower. Included in the listing price: no extra charge.

## `privateSellerContacts` (type: `boolean`):

About 7 % of listings are posted by private persons: their name, phone and e-mail are personal data under GDPR. Agencies and their brokers are always included. Turn off to output `contactName` / `contactEmail` / `phones` as null for private sellers.

## `proxyConfiguration` (type: `object`):

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Global request rate. Lower it if the site answers HTTP 429 / 403 in the log.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed.

## `pageSize` (type: `integer`):

How many listings one search request brings back (1-1000). Leave the default unless a run needs to be gentler.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "location": "Praha",
  "locations": [],
  "transactions": [
    "prodej"
  ],
  "propertyTypes": [
    "byty"
  ],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "radiusKm": 0,
  "ownership": "ALL",
  "furnished": "ALL",
  "searchQueries": [],
  "sortBy": "NEWEST",
  "privateSellersOnly": false,
  "excludeKeywords": [],
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "language": "cs",
  "extractDetails": true,
  "enrichEmails": false,
  "privateSellerContacts": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 10,
  "maxRequestsPerMinute": 300,
  "maxRequestRetries": 5,
  "pageSize": 200,
  "debugLog": false
}
```

# Actor output Schema

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

No description

# 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": "Praha",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/sreality-listings-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": "Praha",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/sreality-listings-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": "Praha",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/sreality-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/sreality-listings-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/lx9eTq5U2wLgi0W7p/builds/8ikZXdem7HoMBlmvE/openapi.json
