# Reality ČR – Sreality, Bezrealitky, Bazoš a další (`huykenny/czech-real-estate-aggregator`) Actor

Agreguje šest českých realitních portálů do kanonických nemovitostí: jeden byt inzerovaný na třech portálech dvěma kancelářemi je jeden záznam se třemi odkazy. Sleduje historii ceny a hlásí nové, zlevněné, přeinzerované i stažené nabídky.

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

## Pricing

from $1.80 / 1,000 nemovitosts

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?

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

## Reality ČR — Sreality, Bezrealitky, Bazoš a další v jednom datasetu

Stáhne inzeráty z českých realitních portálů a spojí je do **jedné nemovitosti
s jedním ID**. Když je tentýž byt na třech portálech a inzerují ho dvě
kanceláře, dostanete jeden záznam se třemi odkazy — ne tři záznamy, které si
musíte párovat sami.

K tomu si Actor pamatuje, co viděl minule, takže umí říct: **tohle je nové,
tohle zlevnilo o 6 %, tohle je na trhu 214 dní a už bylo dvakrát přeinzerované,
a tohle z trhu zmizelo.**

### Proč vůbec deduplikovat

Na českém trhu je běžné, že jeden byt inzeruje víc kanceláří na víc portálech.
Kdo si stáhne portály zvlášť, dostane trh nadhodnocený o desítky procent —
a analýza nabídky, cenový průzkum nebo hledání příležitosti stojí na počtu
nabídek. Sloučit je ručně nejde: portály nemají společné ID, adresu píší jinak,
plochu měří jinak (užitná vs podlahová) a patro číslují jinak.

### Portály

| Portál | Stav |
|---|---|
| Sreality.cz | ✅ |
| Bezrealitky.cz | ✅ |
| iDNES Reality | ✅ |
| Bazoš Reality | ✅ |
| RealityMIX | ✅ |
| ČeskéReality | ✅ |

Nevybraný portál Actor **nahlásí** — prázdný výstup nikdy nevypadá jako
„na trhu nic není".

Bazoš je zvláštní případ: jeho `robots.txt` zakazuje parametry vyhledávání,
takže se u něj **nedá filtrovat lokalita ani cena na straně portálu**. Actor
proto prochází celou republiku a nevhodné nabídky zahazuje podle karty, ještě
než stáhne detail — a napíše, kolik jich to bylo.

> **Pozor na robots.txt:** Sreality a ČeskéReality mají v `robots.txt` pro
> `User-agent: *` uvedeno `Disallow: /`. Actor se identifikuje pravdivě, takže
> se ho to týká: ve výchozím nastavení (`robotsTxtPolicy: respect`) tyto portály
> **přeskočí** a napíše proč. Přepnutí na `ignore` je vědomé rozhodnutí
> uživatele. Podrobně v [`docs/SOURCE_RESEARCH.md`](docs/SOURCE_RESEARCH.md).

### Co dataset obsahuje

Jeden řádek = jedna skutečná nemovitost.

```json
{
  "propertyId": "cz_prop_b479db3ed5bca695ea0ac88e",
  "listingType": "SALE",
  "propertyType": "APARTMENT",
  "layout": "3+kk",
  "price": 10190000,
  "pricePerSqm": 135867,
  "area": 75,
  "location": {
    "city": "Praha", "cityPart": "Braník", "street": "Novodvorská",
    "latitude": 50.024161, "longitude": 14.438407
  },
  "ownership": "PERSONAL",
  "floor": 4, "totalFloors": 8,
  "condition": "AFTER_RECONSTRUCTION",
  "constructionType": "PANEL",
  "energyRating": "C",
  "advertiserType": "AGENCY",
  "firstSeenAt": "2026-08-23T10:14:02.511Z",
  "daysOnMarket": 41,
  "sourceCount": 2,
  "duplicateSourceCount": 1,
  "sources": [
    { "source": "sreality", "price": 10190000, "url": "https://www.sreality.cz/detail/…", "status": "ACTIVE" },
    { "source": "idnes",    "price": 10190000, "url": "https://reality.idnes.cz/detail/…", "status": "ACTIVE" }
  ],
  "historySummary": {
    "originalPrice": 10990000, "currentPrice": 10190000,
    "priceChangePercent": -7.28, "priceChangeCount": 2, "relistedCount": 0
  }
}
```

#### Co dataset vědomě neobsahuje

Popisy inzerátů, fotografie ani kontakty na inzerenta. Cena a plocha jsou
fakta; popis a fotografie jsou autorské dílo inzerenta. Actor je v běhu
používá **interně** pro deduplikaci a pak zahazuje — místo nich dostanete
odkaz na originál. Důvody v [`docs/SOURCE_RESEARCH.md`](docs/SOURCE_RESEARCH.md).

### Jak funguje deduplikace

Rozhodování je záměrně **opatrné**. Nesloučená duplicita je vada, kterou
uvidíte a odpustíte. Dva různé byty slepené do jednoho jsou nepravdivá data,
na kterých někdo postaví rozhodnutí.

1. **Kandidáti** — porovnává se jen to, co má společnou geo buňku (~200 m),
   adresu, telefon, hash fotky, podobný popis nebo kód zakázky. Nikdy se
   neporovnávají dva inzeráty z téhož portálu.
2. **Tvrdé podmínky** — jiný typ nabídky, jiný typ nemovitosti, jiná dispozice,
   plocha nad 15 % rozdíl, jiné patro, cena nad 30 % rozdíl nebo přesné
   souřadnice dál než 500 m spojení zakážou bez ohledu na skóre.
3. **Vážené signály** — shodné fotky interiéru, kód zakázky, shodné adresní
   místo RÚIAN, téměř identický popis, přesná adresa, blízké souřadnice,
   shodný telefon, plocha a cena na 2 %.
4. **Podmínka jedinečnosti** — sloučí se jen tehdy, když je přítomný aspoň
   jeden signál, který identifikuje **konkrétní nemovitost**, ne dům nebo
   kancelář. V developerském projektu má třicet různých bytů stejnou adresu,
   stejnou RK, stejný telefon i stejné fotky fasády; bez téhle podmínky by
   se slily do jedné nemovitosti.
5. **Tranzitivní spojení** — když A odpovídá B a B odpovídá C, je to jedna
   nemovitost, i když se A a C přímo porovnat nedaly (typicky když jeden
   z portálů nedává souřadnice).

Měření na ručně označeném vzorku: [`docs/DEDUP_BENCHMARK.md`](docs/DEDUP_BENCHMARK.md).

### Sledování změn

Actor si mezi běhy drží stav v key-value store, takže druhý běh už umí porovnat.

| Změna | Kdy se hlásí |
|---|---|
| `NEW_PROPERTY` | nemovitost, kterou jsme ještě neviděli |
| `PRICE_DROP` / `PRICE_INCREASE` | pohyb ceny nad 0,5 % |
| `NEW_LISTING_SOURCE` | tatáž nemovitost se objevila na dalším portálu |
| `SOURCE_REMOVED` | zmizela z jednoho portálu, na jiném pořád je |
| `PROPERTY_REMOVED` | zmizela ze všech portálů |
| `RELISTED` | byla pryč a je zpět (pod novým ID, se zachovanou historií) |

**Stažení z trhu se hlásí až po třech po sobě jdoucích běžích**, ve kterých
nabídka chyběla, a jen když byl běh úplný (plný, nefiltrovaný, se všemi
portály v pořádku). Jednorázový výpadek portálu tak nevyrobí vlnu falešných
hlášení „stáhnuto"; místo toho dostane nabídka stav `UNKNOWN`.

Pro monitoring zapněte `onlyChanges` — do datasetu půjdou jen změny, ne celý
katalog.

### Vstup

Předvyplněný vstup je záměrně malá ukázka, která doběhne do minuty (3 portály,
4 inzeráty z každého). Pro skutečný sběr zvedněte `maxItems` a případně
přidejte další portály.

| Pole | Výchozí | Popis |
|---|---|---|
| `sources` | bezrealitky, idnes, realitymix | které portály stahovat (na výběr je všech 6) |
| `mode` | `incremental` | inkrementální dojede k první známé nabídce; `full` projde katalog |
| `listingType` | vše | `SALE`, `RENT`, `AUCTION` |
| `propertyTypes` | vše | byty, domy, pozemky, komerční, chaty, garáže |
| `region` / `district` / `city` | celá ČR | lokalita |
| `priceMin` / `priceMax` | – | cena v Kč |
| `areaMin` / `areaMax` | – | plocha v m² |
| `maxItems` | 12 | strop pro celý běh; pro reálný sběr zvyšte (max 200 000) |
| `fetchDetails` | `true` | detail dá plochu, patro, vlastnictví a fotky, na kterých stojí dedup |
| `deduplicate` | `true` | vypnutím dostanete každý inzerát zvlášť |
| `mergeThreshold` | 45 | vyšší = opatrnější slučování (30–100) |
| `useImageMatching` | `true` | nejsilnější signál; stahují se jen náhledy, hash se nikam neukládá |
| `onlyChanges` | `false` | jen změnové záznamy |
| `includeRawDataset` | `false` | surové inzeráty do datasetu `raw-listings` |
| `detectRemovals` | `true` | funguje jen u plného nefiltrovaného běhu |
| `robotsTxtPolicy` | `respect` | viz upozornění výše |
| `stateStoreName` | `czech-real-estate-state` | stejný název = navazující historie |

Filtry, které portál v URL neumí, Actor dorovná na své straně a **napíše,
kolik inzerátů kterým filtrem vyřadil**. Nikdy se nestane, že si vyžádáte
Prahu a mlčky dostanete celou republiku.

### Kolik to stojí

Platí se za výsledek, ne za pokus:

| Event | FREE | GOLD+ | Kdy |
|---|---|---|---|
| `actor-start` | $0,02 | $0,015 | jednou za běh |
| `property-scraped` | $0,003 | $0,0018 | za jednu **nemovitost** v datasetu |
| `change-detected` | $0,0015 | $0,0009 | za jeden změnový záznam |
| `raw-listing` | $0,0004 | $0,00025 | za jeden surový inzerát (jen když si ho vyžádáte) |

Účtuje se **až za záznam, který skutečně odešel do datasetu** — ne za stažený
inzerát, ne za HTTP požadavek. Když portál spadne a nic nepřijde, nezaplatíte
nic kromě startu.

Klíčové je, že jednotkou je **nemovitost, ne inzerát**. Byt inzerovaný na třech
portálech je jeden účtovaný event, ne tři. Kdo dedupem ušetří 30 % záznamů,
zaplatí o 30 % méně — jinak by ceník šel proti tomu, co produkt slibuje.

| Scénář | Účtováno |
|---|---|
| katalog 115 nemovitostí + 115 změn + 120 RAW | $0,586 |
| monitoring „jen změny", 20 změn | $0,050 |
| monitoring „jen změny", nic se nezměnilo | $0,020 |

### Výkon (změřeno na produkci 23. 8. 2026)

Všech šest portálů, Praha, byty, 20 nabídek na portál, detaily i porovnávání
fotek zapnuté:

| | první běh (`full`) | navazující běh (`incremental`) |
|---|---|---|
| doba běhu | 360 s | 239 s |
| stažených inzerátů | 120 | 63 |
| nemovitostí v datasetu | 115 | 61 |
| duplicit sloučeno | 5 | 2 |
| peak paměti | 117 MB | 128 MB |

Actor **nepoužívá žádné proxy** — chodí přímo, s pravdivým User-Agentem.
Přenesená data jsou jednotky až desítky MB za běh.

Navazující běh je levnější, protože si Actor pamatuje, co už viděl: portály,
na kterých se nic nezměnilo, odpoví jedním požadavkem a skončí. V měřeném běhu
to u Bezrealitek znamenalo **22 → 1 požadavek** a u iDNESu **81 → 13**.

**Paměť si nastavte nízko.** Peak je pod 130 MB, takže 1024 MB je dost
s velkou rezervou. Compute unit se počítá jako GB × hodina, takže zbytečné 4 GB
znamenají čtyřnásobnou cenu za tentýž výsledek.

### Na co si dát pozor

- **Detekce stažených nabídek nefunguje u filtrovaného běhu.** Ve výběru
  „byty v Praze do 8 mil." nelze rozlišit „nabídka je pryč" od „nevešla se do
  filtru". Actor to proto v takovém běhu vypne a napíše důvod.
- **Souřadnice z centroidu se nepoužívají.** Když portál pošle střed ulice nebo
  PSČ místo bodu nemovitosti, hodnota se zahodí, místo aby se vydávala za
  polohu domu.
- **Cena „na dotaz" zůstane prázdná.** Nikdy se nedoplňuje odhadem.
- **`localMedianPricePerSqm`, `estimatedRent`, `dealScore` jsou zatím `null`.**
  Pole existují pro budoucí cenovou analytiku; dokud není spočítaná, zůstávají
  prázdná. Vymyšlené číslo by bylo horší než chybějící.
- **`daysOnMarket`** se počítá od data zveřejnění, když ho portál dává, jinak od
  našeho prvního záchytu. Nikdy se neodhaduje.
- **Blokace se neobchází.** Když portál začne vracet 403 nebo 429, zdroj se pro
  daný běh zastaví a důvod je v souhrnu běhu. Totéž platí pro CDN fotografií
  Sreality, která na náš User-Agent odpovídá 401 — porovnávání fotek je u ní
  vypnuté a dedup se opře o ostatní signály.
- **Nemovitost bez adresy a bez souřadnic se mezi běhy nespáruje.** Bazoš často
  nedává ani jedno; u takové nabídky Actor nepozná, že jde o tutéž nemovitost
  přeinzerovanou pod novým ID, a vypíše ji jako novou. `RELISTED` u ní tedy
  nikdy nenastane a `daysOnMarket` se počítá od nového záchytu.

  Je to vědomá volba, ne opomenutí. Párovat podle „typ + dispozice + plocha" by
  spojovalo různé byty v jednom developerském projektu: dva byty 57,4 a 57,67 m²
  bez adresy jsou v takovém párování nerozlišitelné, a spojení by vyrobilo
  „zlevnění", které se nikdy nestalo. Chybějící spojení uvidíte a poznáte;
  vymyšlené zlevnění ne.
- **Bazoš neumí filtrovat lokalitu ani cenu** (jeho robots.txt zakazuje
  parametry vyhledávání), takže u úzkého dotazu prochází víc stránek než
  ostatní portály a je nejpomalejší ze šesti.

### Souhrn běhu

Každý běh zapíše do key-value store záznam `RUN_SUMMARY`: kolik nemovitostí,
kolik duplicit sloučeno, kolik změn, zdraví každého portálu (požadavky, chyby,
důvod případné blokace) a co se naúčtovalo.

### Dokumentace

- [`docs/SOURCE_RESEARCH.md`](docs/SOURCE_RESEARCH.md) — jak se čte který portál a jaká jsou právní rizika
- [`docs/DEDUP_BENCHMARK.md`](docs/DEDUP_BENCHMARK.md) — měření na ručně označeném vzorku
- [`docs/LIVE_TEST_REPORT.md`](docs/LIVE_TEST_REPORT.md) — co ukázaly běhy proti živým portálům

# Actor input Schema

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

Ze kterých portálů stahovat. Čím víc portálů, tím lépe funguje deduplikace — jedna nemovitost inzerovaná na třech portálech se pozná jen tehdy, když máte všechny tři. Předvyplněné jsou tři portály, které vracejí data bez dalšího nastavení, takže první běh rychle něco najde. Sreality.cz a ČeskéReality mají v robots.txt „Disallow: /" pro všechny roboty, takže je actor při výchozím nastavení přeskočí — zapnout je jde vědomě přes „Postoj k robots.txt".

## `mode` (type: `string`):

Inkrementální běh dojede k první už známé nabídce a zastaví — je rychlý a levný, na denní monitoring stačí. Plný běh projde celý katalog; je potřeba pro první naplnění a pro detekci stažených nabídek.

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

Nechte prázdné pro prodej i pronájem.

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

Nechte prázdné pro všechny typy.

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

Například „Praha" nebo „Jihomoravský kraj". Nechte prázdné pro celou ČR.

## `district` (type: `string`):

Například „Praha 4" nebo „Brno-venkov". Portály, které okres v URL neumí, dorovná kontrola na naší straně.

## `city` (type: `string`):

Například „Praha", „Brno" nebo „Hradec Králové". „Praha" zahrne i „Praha 5" — obvod se pro porovnání odřezává.

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

Dolní hranice ceny v korunách. Nabídky s cenou „na dotaz" se nevyřazují — chybějící cena neznamená, že do rozsahu nepatří.

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

Horní hranice ceny v korunách. Sreality tento filtr umí poslat rovnou do URL, ostatní portály se dorovnávají u nás.

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

Dolní hranice plochy v m². U Bazoše se plocha extrahuje z textu inzerátu, takže nabídky bez uvedené plochy zůstanou ve výsledku.

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

Horní hranice plochy v m².

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

Strop pro celý běh, napříč portály. Účtuje se za vypuštěné nemovitosti, ne za stažené inzeráty. Předvyplněná hodnota je záměrně malá, aby první běh skončil do minuty — pro skutečný sběr ji zvedněte (běžně 500–5000; strop je 200 000).

## `maxItemsPerSource` (type: `integer`):

Nechte prázdné a rozdělí se rovnoměrně mezi vybrané portály.

## `fetchDetails` (type: `boolean`):

Detail dá plochu, dispozici, podlaží, vlastnictví a fotky — tedy to, na čem stojí deduplikace. Vypnutím se běh zrychlí, ale kvalita párování napříč portály výrazně klesne.

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

Hlavní funkce Actoru: jedna nemovitost = jedno ID, i když ji inzerují tři portály a dvě kanceláře. Vypnutím dostanete každý inzerát zvlášť.

## `mergeThreshold` (type: `integer`):

Vyšší číslo = opatrnější slučování. Výchozích 45 je nastaveno tak, aby se radši nesloučila skutečná duplicita, než aby se slily dva různé byty ve stejném domě.

## `useImageMatching` (type: `boolean`):

Nejsilnější signál duplicity: stejné fotky interiéru znamenají stejný byt. Stahují se jen náhledy a počítá se z nich hash — fotky se nikam neukládají ani nevypouštějí. Prodlužuje běh.

## `maxImagesPerListing` (type: `integer`):

Kolik náhledů z jednoho inzerátu stáhnout a spočítat z nich hash. Víc fotek = lepší párování duplicit, ale delší běh. Nula porovnávání fotek vypne.

## `onlyChanges` (type: `boolean`):

Do datasetu půjdou pouze změnové záznamy: nová nabídka, zlevnění, zdražení, stažení z trhu, přidání dalšího portálu. Režim pro monitoring — nedostanete celý katalog.

## `includeRawDataset` (type: `boolean`):

Do pojmenovaného datasetu „raw-listings" se uloží jeden záznam za každý inzerát na každém portálu, s odkazem na kanonickou nemovitost. Hodí se na kontrolu deduplikace.

## `detectRemovals` (type: `boolean`):

Funguje jen u plného nefiltrovaného běhu — u filtrovaného nelze rozlišit „nabídka je pryč" od „nebyla ve výběru". Stažení se hlásí až po třech po sobě jdoucích běžích, aby výpadek portálu nevyrobil vlnu falešných hlášení.

## `robotsTxtPolicy` (type: `string`):

Actor se identifikuje vlastním User-Agentem, takže se ho v robots.txt týká pravidlo pro „\*". Sreality a ČeskéReality tam mají „Disallow: /" — při volbě „Respektovat" se tyto portály přeskočí a v souhrnu běhu je uveden důvod. Volba „Ignorovat" je vědomé rozhodnutí uživatele a jeho odpovědnost.

## `stateStoreName` (type: `string`):

Key-value store, kde se drží historie mezi běhy. Stejný název = navazující historie. Změna názvu začne historii od nuly.

## Actor input object example

```json
{
  "sources": [
    "bezrealitky",
    "idnes",
    "realitymix"
  ],
  "mode": "incremental",
  "maxItems": 12,
  "fetchDetails": true,
  "deduplicate": true,
  "mergeThreshold": 45,
  "useImageMatching": true,
  "maxImagesPerListing": 4,
  "onlyChanges": false,
  "includeRawDataset": false,
  "detectRemovals": true,
  "robotsTxtPolicy": "respect",
  "stateStoreName": "czech-real-estate-state"
}
```

# Actor output Schema

## `properties` (type: `string`):

Kanonické nemovitosti — jeden řádek je jedna skutečná nemovitost, i když ji inzeruje víc portálů. Metadata, cena, historie ceny a odkazy na originální inzeráty; nikdy popisy, fotografie ani kontakty.

## `changes` (type: `string`):

Nové nabídky, zlevnění, zdražení, přeinzerování, zmizení z jednoho portálu a stažení z trhu.

## `runSummary` (type: `string`):

Počty, zdraví každého portálu (požadavky, chyby, důvod případné blokace) a co se naúčtovalo.

# 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 = {
    "sources": [
        "bezrealitky",
        "idnes",
        "realitymix"
    ],
    "mode": "incremental",
    "maxItems": 12
};

// Run the Actor and wait for it to finish
const run = await client.actor("huykenny/czech-real-estate-aggregator").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 = {
    "sources": [
        "bezrealitky",
        "idnes",
        "realitymix",
    ],
    "mode": "incremental",
    "maxItems": 12,
}

# Run the Actor and wait for it to finish
run = client.actor("huykenny/czech-real-estate-aggregator").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 '{
  "sources": [
    "bezrealitky",
    "idnes",
    "realitymix"
  ],
  "mode": "incremental",
  "maxItems": 12
}' |
apify call huykenny/czech-real-estate-aggregator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,huykenny/czech-real-estate-aggregator"
        }
    }
}

```

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/kBjTEgMJSp7dNNt0o/builds/AgAFLnuH69diuMexh/openapi.json
