# Novostavby Byty Scraper ČR (`huykenny/novostavby-byty-scraper`) Actor

Scrape new-build apartments in Czechia from Sreality.cz, Novostavby.com and developer websites into one normalized dataset: prices, price per m², availability, projects — deduplicated across sources.

- **URL**: https://apify.com/huykenny/novostavby-byty-scraper.md
- **Developed by:** [Kenny Ha](https://apify.com/huykenny) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.90 / 1,000 apartment in datasets

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Novostavby Byty Scraper ČR — Czech New Development Apartments

**Scrape Czech new-build apartment inventory — *novostavby* — from Sreality.cz, Novostavby.com and developer websites into one normalized dataset.**

*Novostavby* is the Czech word for new-build developments, and that is exactly what this Actor covers: new-build apartments (*novostavby byty*) across Czechia, from Prague (*novostavby Praha*) to regional cities.

Every run returns:

✓ Apartment prices ✓ Price per m² ✓ Disposition (layout) ✓ Floor ✓ Floor area ✓ Developer ✓ Project and stage ✓ Availability ✓ Location (city, district, GPS where published) ✓ Cross-source deduplication ✓ Price and status monitoring when enabled

**Supported sources**

| Source                                                                     | What it contributes                                                                                                                |
| -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| [Sreality.cz](https://www.sreality.cz/hledani/prodej/byty?stav=novostavby) | New-build apartment listings: price, floor area, floor, ownership, energy class, GPS, description, photos, seller                  |
| [Novostavby.com](https://novostavby.com/status/v-prodeji/)                 | Development project database: developer, location, unit count, move-in date, construction start, completion, architect             |
| [FINEP](https://www.finep.cz/cs/prodej-bytu-praha/)                        | Direct developer inventory: official unit number, project and stage, orientation, balcony area, price incl. VAT, real availability |

Try it with the **Run** button — the default input scrapes all three sources and needs no configuration. Results export to JSON, CSV, Excel or XML, and every field is available through the Apify API.

### Why use this Actor

Most Czech real estate scrapers give you one portal. This one answers a narrower and more valuable question: **what is actually for sale in Czech new developments, and how is it repriced over time.**

- **Portal listings *and* developer inventory.** A developer's own site publishes the official unit number, the concrete stage and whether a flat is reserved — a portal listing does not.
- **One schema across sources.** Same field names, same units, `null` where a source does not publish something. No per-source parsing on your side.
- **Values read from labelled fields, never from "the first number on the page".** A FINEP apartment page also contains a mortgage calculator; the price is taken only from the `Cena vč. DPH` field. A Novostavby.com project page also shows a promoted *different* project; labels are read only from that project's own detail block.
- **Nothing is invented.** Floor area comes from the detail payload or the listing title, never divided out of price and price per m². Values outside a plausible range are rejected and stored as `null` rather than published as facts.
- **Deterministic IDs.** `canonical_id` is derived from stable properties, so the same apartment keeps the same id between runs — which is what makes price history possible.

### Example use cases

- **Market research** — price per m² by project, district and layout across the Czech new-build market (*trh novostaveb*).
- **Investment screening** — spot repriced units with `price_dropped`, or fresh inventory with `is_new`.
- **Developer pricing** — compare a project against comparable stages in the same district.
- **Estate agencies and lead generation** — units that just came to market or changed availability.
- **Proptech and comparison sites** — one normalized feed instead of three site-specific parsers.
- **AI agents and property databases** — stable schema with ids that survive across runs.

### Ready-to-run examples

| Example                                                                                                                    | What it does                                                    |
| -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| [Prague New Build Apartments](https://apify.com/huykenny/novostavby-byty-scraper/examples/prague-new-build-apartments)     | Available new-build apartments in Prague from all three sources |
| [Sreality New Build Apartments](https://apify.com/huykenny/novostavby-byty-scraper/examples/sreality-new-build-apartments) | Czech new-build listings from Sreality.cz only                  |
| [FINEP Available Apartments](https://apify.com/huykenny/novostavby-byty-scraper/examples/finep-available-apartments)       | Currently available units straight from the developer           |

Also available: [Czech New Development Market Monitor](https://apify.com/huykenny/novostavby-byty-scraper/examples/czech-new-development-market-monitor) (all sources, deduplication and history, built for scheduling) and [Prague 2+kk and 3+kk New Apartments](https://apify.com/huykenny/novostavby-byty-scraper/examples/prague-2kk-3kk-new-apartments).

### Input

Everything is optional. The defaults scrape all three sources.

```json
{
    "sources": ["sreality", "finep", "novostavby"],
    "dealTypes": ["sale"],
    "maxItems": 1000,
    "includeDetails": true,

    "cities": ["Praha"],
    "districts": ["Praha 9"],
    "dispositions": ["2+kk", "3+kk"],
    "minPrice": 4000000,
    "maxPrice": 12000000,
    "minArea": 40,
    "maxArea": 120,
    "developers": ["FINEP"],
    "onlyAvailable": true,

    "deduplicate": true,
    "trackHistory": false,
    "includeProjectSummaries": false
}
```

**`maxItems` is the only limit you need to think about.** The Actor derives its request budget from it and splits it evenly between the selected sources, so one source cannot consume the budget and starve the others.

Filters are applied **after** the data is normalized, so they never change how a page is parsed. A listing that simply does not state a value is kept, not dropped.

> For Prague and other cities, filter with `cities` rather than `region`: Sreality publishes a region for every listing, but developer pages and project pages usually do not.

### Output

Two real records from a production run (22 August 2026), unchanged.

**Developer inventory (FINEP):**

```json
{
    "source": "finep.cz",
    "record_type": "unit",
    "unit_id": "302/C3",
    "developer": "FINEP",
    "project_name": "Byty Britská čtvrť",
    "project_stage": "Byty Britská čtvrť XVIII",
    "disposition": "2+kk",
    "area_m2": 45.7,
    "floor": 3,
    "orientation": "S",
    "balcony_m2": 7.8,
    "ownership": "personal",
    "price_czk": 8144469,
    "price_per_m2": 178216,
    "status": "available",
    "status_raw": "K prodeji",
    "construction_status": "under_construction",
    "city": "Praha",
    "unit_url": "https://www.finep.cz/cs/byty-britska-ctvrt-xviii/byt-302-c3",
    "project_url": "https://www.finep.cz/cs/byty-britska-ctvrt"
}
```

**Portal listing (Sreality.cz):**

```json
{
    "source": "sreality.cz",
    "record_type": "unit",
    "listing_id": "1542049868",
    "disposition": "2+kk",
    "area_m2": 51,
    "floor": 1,
    "total_floors": 3,
    "ownership": "personal",
    "energy_class": "B",
    "price_czk": 7499000,
    "price_per_m2": 147039,
    "status": "available",
    "city": "Praha",
    "city_part": "Bohnice",
    "district": "Praha 8",
    "region": "Hlavní město Praha",
    "address": "V Zámcích 51/34, Praha - Bohnice",
    "latitude": 50.13979,
    "longitude": 14.397823,
    "seller_name": "GEPARD REALITY/Living",
    "unit_url": "https://www.sreality.cz/detail/prodej/byt/2+kk/praha-bohnice-v-zamcich/1542049868"
}
```

Fields a source does not publish are `null`, never an empty string and never a guess.

### Output fields

#### Apartments (`record_type: "unit"`)

| Field                                                                | Meaning                                                                                                 |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `canonical_id`                                                       | Deterministic id — developer + project stage + unit number, or source + listing id. Stable across runs. |
| `source`                                                             | `finep.cz`, `sreality.cz`                                                                               |
| `listing_id` / `unit_id`                                             | Portal listing id / the developer's own unit designation (e.g. `302/C3`)                                |
| `developer`, `project_name`, `project_stage`                         | `project_name` is the umbrella project, `project_stage` the concrete building or phase                  |
| `deal_type`, `property_type`, `disposition`                          | `sale` / `rent`, `apartment`, Czech layout such as `2+kk` (`6+` for six rooms and more)                 |
| `area_m2`, `floor`, `total_floors`                                   | Apartment floor area; floor number (negative for basement levels)                                       |
| `orientation`                                                        | Compass orientation as published (`J`, `SZ`, …)                                                         |
| `balcony_m2`, `loggia_m2`, `terrace_m2`, `garden_m2`, `cellar_m2`    | Auxiliary areas, kept apart from the apartment area                                                     |
| `ownership`, `parking`, `garage`                                     | `personal` / `cooperative` / `municipal`; booleans                                                      |
| `price_czk`, `price_per_m2`                                          | Price; price per m² computed only when both price and area are valid                                    |
| `status`, `status_raw`                                               | `available` / `reserved` / `sold`, plus the original Czech wording                                      |
| `construction_status`, `construction_status_raw`                     | `under_construction` / `nearing_completion` / `completed` / `planned`, plus the original wording        |
| `city`, `city_part`, `district`, `municipality`, `region`, `address` | Location, as granular as the source publishes it                                                        |
| `latitude`, `longitude`                                              | Only where the source publishes real coordinates                                                        |
| `energy_class`                                                       | `A`–`G`                                                                                                 |
| `description`, `seller_name`, `seller_type`, `images`                | Portal-side context                                                                                     |
| `unit_url`, `project_url`, `source_url`                              | Listing page, project page, the page the record was discovered on                                       |
| `duplicate_group_id`, `dedupe_confidence`, `sources_found`, `offers` | Deduplication result and provenance                                                                     |
| `first_seen` … `is_removed`                                          | History fields, filled only with `trackHistory`                                                         |

#### Development projects (`record_type: "project"`)

`project_id`, `project_name`, `status`, `status_raw`, `developer`, `district`, `location`, `city`, `region`, `move_in_from`, `units_count`, `price_from_czk`, `price_to_czk`, `architect`, `general_contractor`, `construction_start`, `completion`, `designer`, `energy_class`, `description`, `official_project_url`, `project_url`.

#### Project summaries (`record_type: "project_summary"`, opt-in)

`total_units_seen`, `available_units`, `reserved_units`, `sold_units`, `price_from_czk`, `price_to_czk`, `price_per_m2_min|avg|median|max`, `dispositions`. These describe the units collected in that run, not a developer's full inventory.

### Deduplication

The same apartment can be listed by the developer and by a portal. Records are merged only across different sources and only when a location identifier matches — never on layout, area and price alone:

| Rule | Condition                                               | `dedupe_confidence` |
| ---- | ------------------------------------------------------- | ------------------- |
| 1    | Same developer + project + unit number                  | `exact`             |
| 2    | Same project + layout + area ±1 m² + floor + price ±3 % | `high`              |
| 3    | Same address + layout + area ±1 m² + floor + price ±3 % | `medium`            |

The developer record wins for identity and availability; the portal record contributes description, seller, photos and coordinates. Every source stays in `sources_found` and every price in `offers`, so merging never loses evidence. The rules deliberately merge less rather than risk merging two different flats.

### Price and availability monitoring

Set `trackHistory: true` and the Actor compares each run against the previous ones, filling in:

`first_seen`, `last_seen`, `previous_price_czk`, `price_change_czk`, `price_change_percent`, `price_changed`, `price_dropped`, `price_increased`, `previous_status`, `status_changed`, `is_new`.

The history lives in a named key-value store **inside your own Apify account**, keyed by `canonical_id`. It starts with your first run that has it enabled; entries not seen for 180 days are pruned. With `includeRemoved: true` you also get one row per unit that disappeared from the offer, flagged `is_removed`.

### Example workflows

- **Weekly market snapshot** — schedule the market monitor example weekly, then chart `price_per_m2` by district from the dataset.
- **Discount watch** — run daily with `trackHistory: true` and filter the dataset for `price_dropped: true`.
- **New inventory alert** — filter for `is_new: true` and push the rows to Slack or a spreadsheet through an Apify integration.
- **Project deep dive** — set `developers` and `includeProjectSummaries: true` for per-project price statistics.

### API usage

```bash
## Run and get results in one call
curl -X POST "https://api.apify.com/v2/acts/huykenny~novostavby-byty-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sources":["sreality"],"cities":["Praha"],"dispositions":["3+kk"],"maxItems":100}'
```

The dataset is also available as JSON, CSV, Excel and XML, and through the Apify integrations for Make, Zapier, Google Drive, webhooks and MCP.

### Scheduling

Price history is only useful when the Actor runs regularly. On the Actor page choose **Schedules → Create schedule**, point it at a task with `trackHistory: true` and a fixed `historyStoreName`, and you get a moving picture of the market rather than a snapshot.

### Pricing

This Actor uses **pay-per-result** pricing: **$4.90 per 1,000 dataset items**. You pay only for result events actually charged, according to the Apify Store pricing shown above; Apify platform usage is included in that price.

Deduplication reduces the number of billed items. `includeProjectSummaries` and `includeRemoved` add rows, which is why both are off by default.

### FAQ

**What does the Actor cover?** New-build apartments and development projects from the three sources listed above. It is not a complete index of the Czech property market, and it does not cover every Czech developer — currently one developer site (FINEP) is integrated directly.

**How many results can I get?** Sreality lists roughly 5,000 new-build apartments and Novostavby.com around 1,000 projects currently in sale. FINEP publishes about a hundred units at a time. Set `maxItems` to what you need.

**Why are some fields `null`?** Because the source does not publish them. FINEP does not state GPS or energy class per unit; Novostavby.com does not publish per-project coordinates. `null` means "not published", not "not scraped".

**Why is `status` always `available` on Sreality?** Sreality does not publish reservations. A listing that is online is being offered; `reserved` and `sold` come from developer sources.

**Do I need the detail pages?** For Sreality, yes if you want floor area, floor, ownership or energy class — the listing page does not contain them. `includeDetails: false` makes runs cheaper and the data thinner.

**Hledáte scraper novostaveb?** Yes — this is it. The Actor covers *novostavby* across Sreality.cz, the Novostavby.com project database and developer inventory, with Czech field values (`1+kk`, `2+kk`, `K prodeji`) preserved in `disposition` and `status_raw` alongside the normalized English values.

**Can another developer be added?** Each source is a self-contained module, so adding one is a contained change. Ask through the Issues tab.

### Responsible usage

The Actor reads publicly available pages, the same ones any visitor can open, at a modest request rate. Respect each site's terms of use, do not republish scraped content wholesale, and mind Czech and EU rules on personal data — listing contacts are personal data even when published. You are responsible for how you use the output.

***

### Česky — scraper novostaveb

Sbírá nabídku **novostaveb a bytů v novostavbách v ČR** ze Sreality.cz, Novostavby.com a z webů
developerů (zatím FINEP) do jednoho normalizovaného datasetu: ceny, cena za m², dispozice, patro,
plocha, developer, projekt, dostupnost a lokalita. Pokrývá **novostavby Praha** i krajská města.

- Hodnoty se čtou z pojmenovaných polí, ne regexem přes celou stránku.
- Plocha se nikdy nedopočítává z ceny; co zdroj neuvádí, je `null`.
- Byt inzerovaný developerem i portálem se spojí do jednoho záznamu, ale zůstane u něj seznam zdrojů (`sources_found`) i všechny ceny (`offers`).
- Volitelná historie cen a stavů (`trackHistory`) běží v key-value storu **vašeho** účtu.

Hlavní vstup je `maxItems` — rozpočet requestů si Actor odvodí sám a rozdělí ho mezi zdroje. Pro Prahu filtrujte přes `cities`, ne `region`. Účtuje se **$4,90 za 1 000 záznamů**.

# Actor input Schema

## `sources` (type: `array`):

Which sites to collect from. Sreality and FINEP return individual apartments, Novostavby.com returns development projects.

## `dealTypes` (type: `array`):

Sale is the default. Rent only affects Sreality — developer inventory is for sale only.

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

How many apartments and projects to return in total. The budget is split evenly between the selected sources, so no source can starve the others. A source with a smaller offer (FINEP publishes about a hundred units at a time) simply returns everything it has.

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

Recommended. Sreality listing pages do not contain floor area, floor number, ownership or energy class — those only exist on the detail page. Turning this off makes runs cheaper and the data thinner.

## `region` (type: `string`):

Czech region (kraj). Sreality publishes a region for every listing; developer pages and project pages usually do not, so for Prague and other cities filter with Cities instead. Leave empty for the whole country.

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

For example: Praha, Brno, Kladno. This is the most reliable location filter across all three sources.

## `districts` (type: `array`):

For example: Praha 9, Praha 4, Kladno.

## `dispositions` (type: `array`):

Czech apartment layouts, for example 1+kk, 2+kk, 3+1.

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

Listings without a price are kept — a missing value is not a failed filter.

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

Listings without a price are kept — a missing value is not a failed filter.

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

Floor area of the apartment itself, not including balcony or garden.

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

Floor area of the apartment itself, not including balcony or garden.

## `developers` (type: `array`):

Matches on the developer name, for example FINEP or Skanska.

## `onlyAvailable` (type: `boolean`):

Drops reserved and sold units, and limits Novostavby.com to projects currently in sale.

## `deduplicate` (type: `boolean`):

The same apartment can be listed by the developer and by a portal. Matched records are merged into one, keeping every source in `sources_found` and every price in `offers`.

## `trackHistory` (type: `boolean`):

Compares this run against previous runs and fills in first\_seen, price\_change\_percent, status\_changed and is\_new. The history lives in a key-value store in your own account.

## `historyStoreName` (type: `string`):

Named key-value store used for the history. Use different names to keep separate watchlists apart.

## `includeRemoved` (type: `boolean`):

Adds one row per unit that was in the history but is no longer offered, flagged with is\_removed. These rows are billed like any other result.

## `includeProjectSummaries` (type: `boolean`):

Adds one project\_summary row per project with unit counts, price range and price per m² statistics, computed from the units collected in this run. Billed like any other result.

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

Custom entry points. The source is detected from the domain. Overrides the Sources setting.

## `maxRequestsPerCrawl` (type: `integer`):

Hard cap on HTTP requests. Leave empty — the Actor derives a budget from Maximum results and splits it between sources.

## Actor input object example

```json
{
  "sources": [
    "sreality",
    "finep",
    "novostavby"
  ],
  "dealTypes": [
    "sale"
  ],
  "maxItems": 1000,
  "includeDetails": true,
  "onlyAvailable": false,
  "deduplicate": true,
  "trackHistory": false,
  "historyStoreName": "novostavby-history",
  "includeRemoved": false,
  "includeProjectSummaries": 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("huykenny/novostavby-byty-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("huykenny/novostavby-byty-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 '{}' |
apify call huykenny/novostavby-byty-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,huykenny/novostavby-byty-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/V5bKxbJUcVrKO5qCA/builds/Kogj6op5W2p2wdTWY/openapi.json
