# Krisha.kz Scraper — Kazakhstan Real Estate (Almaty, Astana) (`yadroo/krisha-kz`) Actor

Krisha.kz listings for analysts, agencies and AI agents: apartments, houses, commercial, land for sale or rent in Almaty, Astana, Shymkent or all of Kazakhstan. Price, price per m², rooms, floor, photos, market summary. Monitoring mode: only new listings and price drops. No login.

- **URL**: https://apify.com/yadroo/krisha-kz.md
- **Developed by:** [Samat Makatov](https://apify.com/yadroo) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 18 total users, 6 monthly users, 97.3% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.70 / 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

Structured listings from **krisha.kz**, the #1 real-estate marketplace of Kazakhstan: apartments, houses, commercial property, land and garages — for sale or rent — in Almaty, Astana, Shymkent, any city, region or district. Every krisha.kz filter is available (price, area, floor, year built, building type, owner-only, new buildings, furniture, pets…), each item comes with price per m², seller type and publish date, and `detail: true` adds full description, all parameters, GPS coordinates and photos. Built for analysts, agencies, developers, banks and AI agents.

Two things in one actor that usually cost you separate tools: **new-listing and price-drop alerts** for a saved search on a schedule (`onlyNew`, `trackPriceChanges`), and a **market summary** (median price, ₸/m², breakdown by rooms and district, owner vs agency share) written after every run.

No browser in your run, no API key — plain HTTP, cheap and fast. Since November 2026 krisha.kz shows a browser check to automated requests on its listing pages, so the Actor reads krisha.kz through Yadroo's own server in Kazakhstan, which passes that check; if that server is unavailable, the run carries on the usual way — see [Speed and pricing](#speed-and-pricing).

> **Need it tailored to your workflow?** Missing a field, a filter, another source or a different output format? [Open an issue](https://apify.com/yadroo/krisha-kz/issues) and describe what you need — we read every request and adapt the actor.
>
> **Нужна доработка под вашу задачу?** Не хватает поля, фильтра или другого формата выгрузки — [откройте тикет](https://apify.com/yadroo/krisha-kz/issues) и опишите, что нужно: читаем каждый запрос и дорабатываем актор.

### Use cases

- **New-listing alerts** — save a search as a task, schedule it hourly with `onlyNew: true`: each run returns only listings you have not seen yet. Pipe them to Telegram, Slack, email or a CRM.
- **Price-drop tracking** — add `trackPriceChanges: true`: known listings whose price moved come back with `previousPrice`, `priceChange` and `priceChangePct`.
- **Lead generation for agencies** — `ownerOnly: true` + your district: fresh owner-posted apartments every hour, with phone-free contact through the listing URL.
- **Price monitoring / market reports** — pull 1 000 listings of 2-room apartments in Almaty weekly; the `SUMMARY` record already has median price, median ₸/m² and a breakdown by rooms and district.
- **Investment screening** — `newBuildingOnly` + `mortgageAvailable` + `yearFrom: 2020`, sorted `cheapest`, with `detail: true` for coordinates and all parameters.
- **Rental yield analysis** — run once for `prodazha` and once for `arenda` on the same complex (`complexId`) and divide.
- **Paste a search from the browser** — set the filters on krisha.kz, copy the address into `searchUrl`, and the Actor returns exactly that search (every krisha.kz filter, even ones without an input field here).
- **Commercial real estate sourcing** — `kommercheskaya-nedvizhimost` with `commercialUse: "warehouse"`, `withTenants: true` (income-producing assets).
- **Developer competitive intel** — `seller: "developer"` items reveal which complexes are actively marketed, at what ₸/m².

### Input

All fields are optional. Location and type fields mirror the krisha.kz URL: `https://krisha.kz/{dealType}/{propertyType}/{city}/` — or paste such a URL into `searchUrl`.

| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
| `dealType` | string | `prodazha` | `prodazha` (sale), `arenda` (rent) |
| `propertyType` | string | `kvartiry` | `kvartiry`, `doma-dachi`, `komnaty`*, `kvartiry-posutochno`*, `kvartiry-po-chasam`*, `doma-dachi-posutochno`*, `kommercheskaya-nedvizhimost`, `biznes`\*\*, `prombazy`, `uchastkov`, `garazhi`, `zarubezhnoj-nedvizhimosti` (\* rent only, \*\* sale only). Exactly these values: Apify refuses any other value before the run starts. |
| `city` | string | – (all Kazakhstan; the Console form is prefilled with `almaty`) | Any slug from **Reference → Locations** (city, region or district), or its name in Russian, Kazakh or Latin letters: `Алматы`, `Бостандыкский р-н` / `Бостандыкский район`, `Алматинская область`, `г. Алматы`, `Нур-Султан`, `Қарағанды`, `Karagandy`, `Almaty region`, `Алматы, Медеуский р-н` (see **Reference → Accepted spellings**). The status message and `SUMMARY.warnings` say how a name was read. A name that matches no location stops the run within seconds with "did you mean …" — it is never sent to krisha.kz, which would answer with all of Kazakhstan. Empty = all Kazakhstan. |
| `searchUrl` | string | – | A krisha.kz search address copied from the browser, e.g. `https://krisha.kz/arenda/kvartiry/astana/?das[live.rooms][]=1&das[price][to]=300000`. Its section, property type, location, `das[...]` filters and sort replace `dealType`, `propertyType`, `city` and `sort`; filters set in the other fields are added on top (on the same filter the URL wins, with a warning); `page` and non-search parameters are dropped. A URL pasted into `city` is read the same way. A listing page (`/a/show/…`), a complex page or another site is refused with a clear message. |
| `complexId` | integer | – | Residential complex id (number in `https://krisha.kz/complex/almaty/<id>`). |
| `rooms` | string\[] | `[]` | `"1"`, `"2"`, `"3"`, `"4"`, `"5+"` (five and more; `"5"` means the same), and `"6"`…`"10"` for houses. Any other value fails the run with this list — it is never ignored (an ignored room filter would return every room count). |
| `priceFrom` / `priceTo` | integer | – | Tenge. For `arenda` = monthly rent. |
| `areaFrom` / `areaTo` | integer | – | Total area m² (commercial → premises area). |
| `kitchenAreaFrom` / `kitchenAreaTo` | integer | – | Apartments. |
| `floorFrom` / `floorTo` | integer | – | Apartments. |
| `notFirstFloor` / `notLastFloor` | boolean | `false` | Apartments. |
| `buildingFloorsFrom` / `buildingFloorsTo` | integer | – | Floors in the building. |
| `yearFrom` / `yearTo` | integer | – | Year built. |
| `buildingType` | string | – | `brick`, `panel`, `monolith`, `other` |
| `bathroom` | string | – | `separate`, `combined`, `twoOrMore`, `none` |
| `ownerOnly` | boolean | `false` | Only owner-posted listings (`das[who]=1`). |
| `fromAgentsOnly` | boolean | `false` | Only verified Krisha Agents. |
| `hasPhoto` | boolean | `false` | |
| `newBuildingOnly` | boolean | `false` | Primary market only. |
| `mortgageAvailable` | boolean | `false` | |
| `notDormitory` | boolean | `false` | Exclude former dormitories. |
| `exchangePossible` | boolean | `false` | |
| `furniture` | string | – | Rent only: `full`, `partial`, `none` |
| `petsAllowed` / `kidsAllowed` | boolean | `false` | Rent only. |
| `houseType` | string | – | Houses: `detached`, `partOfHouse`, `dacha` |
| `wallMaterial` | string | – | Houses: `brick`, `monolith`, `wood`, `adobe`, `gasSilicate`, `aeratedConcrete`, `cinderBlock`, `foamBlock`, `thermoBlock`, `frameReed`, `framePanel`, `sip`, `concretePanel`, `shellRock`, `finBlock` |
| `renovation` | string | – | Houses: `fresh`, `decent`, `needsRepair`, `roughFinish`, `demolition`, `unfinished` |
| `heating` | string | – | Houses: `central`, `gas`, `solidFuel`, `liquidFuel`, `electric`, `mixed`, `none` |
| `sewage` | string | – | Houses: `central`, `canConnect`, `septic`, `none` |
| `landAreaFrom` / `landAreaTo` | integer | – | Sotka (100 m²): houses, land, garages. |
| `commercialUse` | string | – | `any`, `office`, `retail`, `warehouse`, `auto`, `catering`, `beauty`, `agriculture`, `hospitality`, `medical`, `education`, `entertainment` |
| `commercialLocation` | string | – | `businessCenter`, `residential`, `mall`, `market`, `standalone` |
| `withTenants` / `asBusiness` | boolean | `false` | Commercial. |
| `extraParams` | object | `{}` | Any other raw `das[...]` parameter copied from a krisha.kz URL, e.g. `{"das[flat.phone]": "1"}`. A key that does not start with `das[` fails the run. |
| `sort` | string | `newest` | `newest`, `cheapest`, `expensive`. Note: paid "hot" listings are pinned to the top of every krisha.kz page regardless of sort — filter on `hot: false` if you need a strict order. |
| `sinceHours` | integer | – | Keep only listings published in the last N hours (day precision). With `sort: newest` pagination stops at the first page that is entirely older. |
| `maxItems` | integer | `40` | 1–5000. ~20 listings per page. With `detail: true` about 1.2 s per listing through Yadroo's server in Kazakhstan (6.5 s the usual way): a 1-hour run holds well over 1 000. |
| `maxPages` | integer | `50` | 1–300 safety cap. Raise it together with `maxItems` (5000 items ≈ 250 pages). |
| `detail` | boolean | `false` | Open every listing page: full description, all parameters, coordinates, photos, owner name/type, exact publish date. +1 request per listing. Since November 2026 krisha.kz shows a browser check to automated requests on listing pages: they are read through Yadroo's server in Kazakhstan, which passes that check (about 1.2 s per listing, measured 2026-11-09). If that server is unavailable, the run reads them the usual way (about 6.5 s each); if krisha.kz refuses every page tried that way, the run stops trying after a few refusals and still delivers every listing with its search-card fields, `detailError` saying why. |
| `includeViews` | boolean | `false` | Attach the site's view counter (1 batch request per 25 listings). **Off by default**: the counter endpoint (`/ms/views/…`) is disallowed by krisha.kz's robots.txt (`Disallow: /ms/*`); turn it on only if you accept that. Off = `views: null`. |
| `proxyConfiguration` | object | off | **Off = the normal run.** On = fast mode for `detail: true`: Apify Proxy → 8 IPs (group RESIDENTIAL) or 4 IPs (datacenter groups, whose IPs are shared) open listing pages at once, at the fast-mode price; your own proxy URLs (`http://user:pass@host:port`, one per IP, up to 10 at once) → as many IPs as URLs, at the normal price. Search pages are read directly (through the proxy only if krisha.kz does not answer the run's server); without `detail` the proxy is not used. While Yadroo's server in Kazakhstan reads the listing pages, the proxy is only the fallback and every listing is charged the normal price. See [Speed and pricing](#speed-and-pricing). |
| `dedupe` | boolean | `true` | Drop repeated ids (paid listings repeat in the "hot" block). |
| `onlyNew` | boolean | `false` | Monitoring: return only listings previous runs of the same search have not returned. See **Monitoring**. |
| `trackPriceChanges` | boolean | `false` | Monitoring: also return known listings whose price changed. Implies `onlyNew`. |
| `monitorKey` | string | – | Monitoring: name of the saved state. Empty = derived from the search filters. |

Filters that do not apply to the chosen property type (e.g. `furniture` for a sale) are dropped with a warning in the log, in the run's status message and in `SUMMARY.warnings` — nothing is ignored silently. Fields with a fixed list of values (`dealType`, `propertyType`, `sort`, `buildingType`, `bathroom`, `furniture`, `houseType`, `wallMaterial`, `renovation`, `heating`, `sewage`, `commercialUse`, `commercialLocation`) take exactly the values above: Apify refuses any other value before the run starts.

### Monitoring (scheduled runs)

Save your search as a **task**, switch on `onlyNew` and attach a **schedule** (Apify Console → Schedules, e.g. every hour). Every run then returns only what is new since the previous run.

```json
{
  "dealType": "prodazha", "propertyType": "kvartiry", "city": "almaty-bostandykskij",
  "rooms": ["2"], "priceTo": 60000000,
  "onlyNew": true, "trackPriceChanges": false,
  "maxItems": 100, "maxPages": 20
}
```

Schedule: cron `0 * * * *` (hourly) or `0 8 * * *` (every morning), action = run the task above. Add an integration (Telegram, Slack, email, webhook, Make, Zapier, n8n) on the task to get the new rows pushed to you.

How it works:

- **First run** returns everything it finds (up to `maxItems`) and saves it as the baseline — the log says `first monitoring run — baseline of N listing(s) saved`. It records at least 3 result pages even if `maxItems` is smaller, so the second run has a solid reference.
- **Next runs** return only listings the monitor has not returned before, each with `changeType: "new"`. With `sort: newest` paging stops once **two pages in a row** hold only already-known listings, so an hourly run usually reads 2–4 pages.
- **`trackPriceChanges: true`** also returns known listings whose price changed (`changeType: "price_changed"`, `previousPrice`, `priceChange`, `priceChangePct`). Price changes can be on any page, so these runs read up to `maxPages` pages — keep `maxPages` modest (10–30). Listings met there for the first time are added to tracking without being reported, unless their id shows they were published after the monitor last looked.
- **State** lives in the named key-value store `krisha-kz-monitor` of your Apify account, one record per search (key = hash of the search URL, or your `monitorKey`). It keeps the last 20 000 listings (id → last price and date). A listing is remembered only once it is saved to your dataset, and the record is written after the saved batches and at the end: a run cut short by your spending limit or the timeout never marks the listings it did not save as seen (the next run returns them), and listings a run did save are not returned again, even if that run failed later.
- **Same search in two tasks** shares one memory (the second task would see nothing new). Give each task its own `monitorKey` to keep them apart, or the same key to share on purpose. To start over, use a new `monitorKey` or delete the record in `krisha-kz-monitor`.
- **Cheaper runs** — you pay per returned listing, and a monitoring run returns only new and repriced ones: an hourly monitor that finds 3 new listings costs $0.02 + 3 × $0.003 = **$0.029 per run** instead of paying for the whole result list every time.
- **Good to know** — krisha.kz sorts "newest" by the last time a listing was raised, and sellers pay to raise old listings to the top. A raised listing the monitor has never seen counts as new (you have not seen it either), but gets `recentlyPublished: false`; listings actually published since the last run get `recentlyPublished: true` — filter on it if you only want brand-new supply. On broad searches (all of Almaty) most "new" rows are raised older listings; narrow searches are much quieter. The 3 paid "hot" listings pinned on top of page 1 rotate through the whole search; they count as new only when they were published after the monitor last looked. If `maxItems` is reached while new listings keep coming, the rest is left for the next run and the log says so — set `maxItems` above what you expect between two runs.

### Reference

#### Locations (`city`)

Slugs come from krisha.kz's own region tree (`/region/ajaxGetChildren/`). Districts are only defined for Almaty, Astana and Shymkent. Any other town slug that appears in a krisha.kz URL (`https://krisha.kz/prodazha/kvartiry/<slug>/`) also works. A slug krisha.kz does not know stops the run with "did you mean …" and saves nothing: krisha.kz answers such a slug with a 404 or with the listings of all Kazakhstan, so the Actor checks which location the first page really searched.

| Region / city | Slug | Districts / main cities (slug) |
|---|---|---|
| **Алматы** (city) | `almaty` | Алатауский → `almaty-alatauskij`; Алмалинский → `almaty-almalinskij`; Ауэзовский → `almaty-aujezovskij`; Бостандыкский → `almaty-bostandykskij`; Жетысуский → `almaty-zhetysuskij`; Медеуский → `almaty-medeuskij`; Наурызбайский → `almaty-nauryzbajskiy`; Турксибский → `almaty-turksibskij` |
| **Астана** (city) | `astana` | Алматы р-н → `astana-almatinskij`; Есильский → `astana-esilskij`; Нура → `astana-nura`; Байконур → `r-n-bajkonur`; Сарайшык → `astana-saraishyk`; Сарыарка → `astana-saryarkinskij` |
| **Шымкент** (city) | `shymkent` | Абайский → `shymkent-abajskij`; Аль-Фарабийский → `shymkent-al-farabijskij`; Енбекшинский → `shymkent-enbekshinskij`; Каратауский → `karatauskij`; Туран → `shymkent-turan` |
| Абай обл. | `abay-oblast` | Семей → `semej` |
| Акмолинская обл. | `akmolinskaja-oblast` | Кокшетау → `kokshetau`; Щучинск → `shhuchinsk`; Степногорск → `stepnogorsk` |
| Актюбинская обл. | `aktjubinskaja-oblast` | Актобе → `aktobe` |
| Алматинская обл. | `almatinskaja-oblast` | Боралдай → `boroldaj-burundaj`; Каскелен → `kaskelen`; Конаев → `konaev`; Талгар → `talgar` |
| Атырауская обл. | `atyrauskaja-oblast` | Атырау → `atyrau`; Кульсары → `kulsary` |
| Восточно-Казахстанская обл. | `vostochno-kazahstanskaja-oblast` | Риддер → `ridder`; Усть-Каменогорск → `ust-kamenogorsk` |
| Жамбылская обл. | `zhambylskaja-oblast` | Тараз → `taraz`; Жанатас → `zhanatas`; Шу → `shu` |
| Жетысу обл. | `jetisyskaya-oblast` | Талдыкорган → `taldykorgan` |
| Западно-Казахстанская обл. | `zapadno-kazahstanskaja-oblast` | Аксай → `aksaj`; Уральск → `uralsk` |
| Карагандинская обл. | `karagandinskaja-oblast` | Балхаш → `balhash`; Караганда → `karaganda`; Темиртау → `temirtau`; Шахтинск → `shahtinsk`; Сарань → `saran` |
| Костанайская обл. | `kostanajskaja-oblast` | Костанай → `kostanaj`; Лисаковск → `lisakovsk`; Рудный → `rudnyj` |
| Кызылординская обл. | `kyzylordinskaja-oblast` | Байконур → `bajkonur`; Кызылорда → `kyzylorda` |
| Мангистауская обл. | `mangistauskaja-oblast` | Актау → `aktau`; Жанаозен → `zhanaozen` |
| Павлодарская обл. | `pavlodarskaja-oblast` | Павлодар → `pavlodar`; Экибастуз → `ekibastuz`; Аксу → `aksu` |
| Северо-Казахстанская обл. | `severo-kazahstanskaja-oblast` | Петропавловск → `petropavlovsk` |
| Туркестанская обл. | `juzhno-kazahstanskaja-oblast` | Туркестан → `turkestan`; Арысь → `arys`; Кентау → `kentau` |
| Улытау обл. | `ulitayskay-oblast` | Жезказган → `zhezkazgan`; Сатпаев → `satpaev` |

Abroad (`propertyType: zarubezhnoj-nedvizhimosti`): `gruzija`, `kipr`, `grecija`, `italija`, `rossija`, `kyrgyzstan`, `vetnam`.

#### Accepted spellings (`city`)

Besides the slugs above, `city` accepts (case, `ё`/`е` and Kazakh letters do not matter):

- **Russian names** as written in the table, or with the words spelled out: `Бостандыкский район`, `Алматинская область`, `р-н Байконур`; `г.` / `город` / `city` are ignored (`г. Алматы`).
- **Kazakh and Latin names, old names**: `Нур-Султан`, `Nur-Sultan`, `Akmola` → `astana`; `Alma-Ata`, `Алмата` → `almaty`; `Қарағанды`, `Karagandy` → `karaganda`; `Өскемен`, `Oskemen` → `ust-kamenogorsk`; `Oral` → `uralsk`; `Semey` → `semej`; `Petropavl` → `petropavlovsk`; `Kapchagay`, `Qonaev` → `konaev`; `Chimkent` → `shymkent`; and the other main cities.
- **Regions in English**: `Almaty region`, `Akmola region`, `East Kazakhstan`, `North Kazakhstan`, `Turkestan region`, `Mangystau` …; **districts**: `Bostandyk`, `Medeu district`, `Yesil district`, `Al-Farabi district` ….
- **City + district**: `Алматы, Бостандыкский р-н` or `Almaty / Medeu` — the most specific place is searched; two places that do not belong together stop the run.
- `Весь Казахстан`, `Kazakhstan`, `all` or empty = all Kazakhstan.

Anything else that is not a slug stops the run before any request, naming the closest locations ("did you mean Караганда (karaganda)?"). A slug that is not in the table is passed to krisha.kz as typed (small towns); if the first page shows that krisha.kz did not apply it, the run stops with the same suggestions and saves nothing.

#### Property types

| Slug | Meaning | Sale | Rent |
|---|---|---|---|
| `kvartiry` | Apartments | ✓ | ✓ |
| `doma-dachi` | Houses & dachas | ✓ | ✓ |
| `komnaty` | Rooms | – | ✓ |
| `kvartiry-posutochno` | Apartments, daily | – | ✓ |
| `kvartiry-po-chasam` | Apartments, hourly | – | ✓ |
| `doma-dachi-posutochno` | Houses, daily | – | ✓ |
| `kommercheskaya-nedvizhimost` | Commercial property | ✓ | ✓ |
| `biznes` | Ready business | ✓ | – |
| `prombazy` | Industrial bases | ✓ | ✓ |
| `uchastkov` | Land plots | ✓ | ✓ |
| `garazhi` | Garages & parking | ✓ | ✓ |
| `zarubezhnoj-nedvizhimosti` | Property abroad | ✓ | ✓ |

#### Filter → krisha.kz parameter map

| Input | krisha.kz `das[...]` | Codes |
|---|---|---|
| `rooms` | `das[live.rooms][]` | 1,2,3,4, `5.100` (=5+) |
| `priceFrom/To` | `das[price][from/to]` | ₸ |
| `areaFrom/To` | `das[live.square]` / `das[com.square]` | m² |
| `kitchenAreaFrom/To` | `das[live.square_k]` | m² |
| `floorFrom/To` | `das[flat.floor]` | |
| `notFirstFloor`, `notLastFloor` | `das[floor_not_first]`, `das[floor_not_last]` | 1 |
| `buildingFloorsFrom/To` | `das[house.floor_num]` | |
| `yearFrom/To` | `das[house.year]` | |
| `buildingType` | `das[flat.building]` | brick 1, panel 2, monolith 3, other 0 |
| `bathroom` | `das[flat.toilet]` | separate 1, combined 2, twoOrMore 3, none 4 |
| `ownerOnly` | `das[who]` | 1 |
| `fromAgentsOnly` | `das[_sys.fromAgent]` | 1 |
| `hasPhoto` | `das[_sys.hasphoto]` | 1 |
| `newBuildingOnly` | `das[novostroiki]` | 1 |
| `mortgageAvailable` | `das[mortgage]` | 1 |
| `notDormitory` | `das[flat.priv_dorm]` | 2 |
| `exchangePossible` | `das[has_change]` | 1 |
| `furniture` | `das[live.furniture]` | full 1, partial 2, none 3 |
| `petsAllowed`, `kidsAllowed` | `das[who_match][4]`, `das[who_match][5]` | 4, 5 |
| `houseType` | `das[house.type_object]` | detached 1, partOfHouse 2, dacha 3 |
| `wallMaterial` | `das[house.building_opts]` | 1–15 in the order listed above |
| `renovation` | `das[house.renewal]` | 1–6 |
| `heating` | `das[cmtn.heating]` | central 1, gas 2, solidFuel 3, liquidFuel 4, electric 7, mixed 5, none 6 |
| `sewage` | `das[cmtn.sewage]` | central 1, canConnect 2, septic 3, none 4 |
| `landAreaFrom/To` | `das[land.square]` | sotka |
| `commercialUse` | `das[com.use_case]` | any 1, office 2, retail 3, warehouse 4, auto 5, catering 6, beauty 7, agriculture 8, hospitality 9, medical 11, education 12, entertainment 13 |
| `commercialLocation` | `das[com.location]` | businessCenter 1, residential 2, mall 3, market 4, standalone 5 |
| `withTenants`, `asBusiness` | `das[com.is_tenants]`, `das[estate.is_buss]` | 1 |
| `complexId` | `das[map.complex]` | complex id |
| `sort` | `sort_by` | newest = default (`add_date-desc`), cheapest `price-asc`, expensive `price-desc` |

### Examples

**Daily market snapshot — 2-room apartments in Almaty under 45 M ₸**

```json
{ "dealType": "prodazha", "propertyType": "kvartiry", "city": "almaty", "rooms": ["2"], "priceTo": 45000000, "maxItems": 500 }
```

**Agency lead-gen — new owner-posted rentals in Bostandyk district, checked hourly**

```json
{ "dealType": "arenda", "propertyType": "kvartiry", "city": "almaty-bostandykskij", "rooms": ["1", "2"], "priceTo": 400000, "ownerOnly": true, "furniture": "full", "sinceHours": 2, "detail": true, "maxItems": 100 }
```

**Investor screen — new builds with mortgage, 2020+, monolith, not ground floor**

```json
{ "city": "astana", "newBuildingOnly": true, "mortgageAvailable": true, "yearFrom": 2020, "buildingType": "monolith", "notFirstFloor": true, "sort": "cheapest", "maxItems": 300 }
```

**Commercial sourcing — warehouses with tenants in Almaty region**

```json
{ "propertyType": "kommercheskaya-nedvizhimost", "city": "almatinskaja-oblast", "commercialUse": "warehouse", "withTenants": true, "areaFrom": 500, "detail": true, "maxItems": 100 }
```

**Paste a search — owner-posted 1–2-room rentals in Esil district under 350 000 ₸, cheapest first**

```json
{ "searchUrl": "https://krisha.kz/arenda/kvartiry/astana-esilskij/?das[live.rooms][]=1&das[live.rooms][]=2&das[price][to]=350000&das[who]=1&sort_by=price-asc", "maxItems": 100 }
```

**Houses — gas-heated detached houses with 6+ sotka near Almaty**

```json
{ "propertyType": "doma-dachi", "city": "kaskelen", "houseType": "detached", "heating": "gas", "landAreaFrom": 6, "priceTo": 90000000, "maxItems": 200 }
```

### Output

One dataset item per listing. Example (trimmed, `detail: false`):

```json
{
  "id": "1015668341",
  "title": "2-комнатная квартира · 45.2 м² · 5/5 этаж",
  "url": "https://krisha.kz/a/show/1015668341",
  "price": 35000000, "currency": "KZT", "priceText": "35 000 000 ₸", "pricePerM2": 774336,
  "rooms": 2, "area": 45.2, "floor": 5, "floors": 5,
  "address": "Бостандыкский р-н, Толеу Басенова", "district": "Бостандыкский р-н", "street": "Толеу Басенова", "cityName": "Алматы",
  "complex": null, "yearBuilt": 1985, "buildingType": "кирпичный", "condition": "не новый, но аккуратный ремонт", "ceilingHeight": 2.6,
  "description": "кирпичный дом, 1985 г.п., состояние: … ПРОДАЁТСЯ ЕВРОДВУШКА В БОСТАНДЫКСКОМ РАЙОНЕ! …",
  "seller": "specialist", "sellerVerified": true, "hot": true, "photosCount": 12,
  "image": "https://krisha-photos.kcdn.online/webp/cb/…/1-full.jpg",
  "publishedAt": "2026-09-13", "views": null,
  "city": "almaty", "dealType": "prodazha", "propertyType": "kvartiry", "searchTotal": 10429,
  "fetchedAt": "2026-09-12T23:43:27.131Z"
}
```

| Field | Description |
|---|---|
| `id`, `url` | krisha.kz listing id and canonical URL |
| `title` | Listing title (rooms · area · floor) |
| `price`, `currency`, `priceText` | Price in ₸ (monthly for rent); `null` when "price on request" |
| `pricePerM2` | Price per m² as shown by krisha.kz (commercial cards), otherwise `price / area`, rounded |
| `pricePeriod` | `month`, `day` or `hour` for rentals; `null` for sales |
| `rooms`, `area`, `floor`, `floors` | Parsed from the title |
| `address`, `district`, `street`, `cityName` | Address line split into district (`… р-н`) and street; city as shown on the card |
| `complex` | Residential complex name when the listing belongs to one |
| `yearBuilt`, `buildingType`, `condition`, `ceilingHeight` | Parsed from the card summary (Russian values as on the site) |
| `description` | Card preview text (truncated by the site) |
| `seller` | `owner`, `specialist` (agent), `company` (agency), `developer` (new-building complex) |
| `isDeveloper` | `true` for new-building developer cards (`seller: "developer"`); their `price` is the starting price shown as "от …" |
| `sellerVerified` | Identity-verified badge |
| `hot` | Pinned in krisha's paid "hot" block at the top of page 1 (shown regardless of sort) |
| `photosCount`, `image` | Number of photos and first photo URL |
| `publishedAt` | Publish date `YYYY-MM-DD` in Kazakhstan time (UTC+5, as the site shows it; day precision from the card) |
| `views` | Site view counter (only with `includeViews: true`; otherwise `null`) |
| `city`, `dealType`, `propertyType` | Echo of the resolved search scope |
| `searchTotal` | Total number of listings krisha.kz reports for this search (market size) |
| `fetchedAt` | ISO timestamp |
| `changeType` | Monitoring only: `new` or `price_changed` |
| `previousPrice`, `priceChange`, `priceChangePct` | Monitoring only: last price the monitor saw, difference in ₸ (negative = cheaper) and in % (2 decimals); `null` for new listings |
| `detailError` | `detail: true` only: why the listing page could not be read (the row keeps its card data); `not opened: …` when krisha.kz refused every listing page of the run; absent when the page was read |
| `recentlyPublished` | Monitoring only, `new` rows: `true` = published since the monitor's last complete run (its id is newer than every listing it knew), `false` = an older listing seen for the first time (raised by the seller or newly matching your filters); `null` on the first run and for price changes |

The dataset has three views: **Overview**, **Details** (`detail: true` fields) and **Monitoring: new & repriced** (change type, price, previous price, Δ ₸, Δ %).

#### Market summary (`SUMMARY` record)

After every run the default key-value store gets a `SUMMARY` record (free — not a dataset item). It describes the listings returned by this run — in monitoring mode the new and repriced ones — and every statistic carries its sample size `n` (listings without a price or area are skipped, never counted as zero). The log prints a one-line version: `Market: 30 listing(s) · median 54M ₸ (n=30, range 28.5M–351.7M) · median 995k ₸/m² (n=30) · owners 7% of 30`.

```json
{
  "basis": "listings returned by this run",
  "search": { "url": "https://krisha.kz/prodazha/kvartiry/almaty-bostandykskij/?das%5Blive.rooms%5D%5B%5D=2", "sort": "newest", "…": "…" },
  "searchTotal": 4077, "pagesScanned": 2, "searchStoppedBy": "maxItems",
  "delivered": 30, "stoppedBy": null, "status": "30 listing(s) saved of 4077 matching on krisha.kz.",
  "listings": 30, "pricePeriod": null, "otherPeriodExcluded": 0,
  "price": { "n": 30, "min": 28500000, "p25": 46000000, "median": 54000000, "mean": 68627913, "p75": 67625000, "max": 351713800 },
  "pricePerM2": { "n": 30, "min": 692308, "p25": 866982, "median": 995400, "mean": 1062079, "p75": 1164479, "max": 2540000 },
  "byRooms": [ { "rooms": "2", "count": 29, "medianPrice": 54000000, "nPrice": 29, "medianPricePerM2": 992647, "nPricePerM2": 29 } ],
  "byDistrict": [ { "district": "Бостандыкский р-н", "count": 30, "medianPrice": 54000000, "nPrice": 30, "medianPricePerM2": 995400, "nPricePerM2": 30 } ],
  "sellers": { "n": 30, "owner": 2, "agency": 25, "developer": 3, "ownerShare": 0.067, "agencyShare": 0.833, "developerShare": 0.1 },
  "monitor": null
}
```

- `byDistrict` groups by the card's district, or the city when there is none (top 50 groups). `agency` = agents + agencies; shares are over listings with a known seller type.
- Rentals: `pricePeriod` is `month` / `day` / `hour`; if a search mixes periods, price statistics use the most common one and `otherPeriodExcluded` counts the rest.
- `searchStoppedBy` — why paging ended: `maxItems`, `maxPages`, `noMoreResults`, `sinceHours`, `alreadySeen` (monitoring stop rule), `pageError` (a later search page failed; `pageError` says which — the run keeps what it saved), `spendingLimit`, `timeout` or `aborted`.
- `delivered` — rows saved (and charged) by this run; `stoppedBy` — `null`, or `limit` / `timeout` / `aborted` when your spending limit, the run timeout or an abort cut the run short (the status message then starts with "Stopped at your spending limit: …" or "Stopped before the run timeout: …"); `status` — the final status message.
- `detail` (with `detail: true`): `{ opened, failed, savedWithoutDetail, leftUnopened, stop, minutes }` — `savedWithoutDetail` listings were saved with their search-card fields only because krisha.kz refused every listing page of the run; `leftUnopened` listings were found but not opened (spending limit, timeout or a block) and were **not saved or charged**; `wafRetries` — how many times krisha.kz's firewall answered 403/429/468/5xx (each such answer is retried while attempts last); `warnings` — input notes (filters dropped for this property type, proxy notes).
- `route`: how the run read krisha.kz — `kzGateway` `{ configured, requests, pages, fallbacks, solved, disabled }` for Yadroo's server in Kazakhstan (pages it delivered, requests it handed to the usual way, browser checks it passed, and why it was switched off for the rest of the run — `null` when it was not), plus `searchPagesViaGateway` / `listingPagesViaGateway`. Pages not delivered that way were read the usual way (`speed`, `wafRetries`); the status message names the server only when it dropped out during the run.
- `droppedNotMatchingFilters`: `null`, or how many cards krisha.kz showed that do not match your room / price / area filters and were dropped (never charged) — `{ dropped, developerCards, byFilter, examples }`. krisha mixes new-building developer cards into the results regardless of the room filter.
- In monitoring mode `monitor` holds `{ key, store, run, firstRun, trackPriceChanges, new, recentlyPublished, priceChanged, unchanged, trackedSilently, heldBack, tracked, settled }` — `heldBack` > 0 means `maxItems`, the spending limit or the timeout cut the run short and the rest comes next run.

#### Detail mode

With `detail: true` each item additionally has: `descriptionFull`, `parameters` (object keyed by krisha field names: `flat.balcony`, `flat.parking`, `flat.security`, `live.furniture`, `flat.facilities`, `who_match`, …), `lat`, `lon`, `mapUrl`, `addressParts` (`{city, district, street, house_num, corner_street}`), `photos[]`, `ownerName`, `userType` (`owner` / `specialist` / `company` / `complex`), `complexId`, `isEstateVerified`, and `publishedAt` from the listing page. Phone numbers are behind a click-to-reveal captcha on krisha.kz and are **not** collected.

### Use it from code / agents

```bash
curl -X POST "https://api.apify.com/v2/acts/yadroo~krisha-kz/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"city":"almaty","rooms":["2"],"priceTo":45000000,"maxItems":50}'
```

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/krisha-kz').call({ city: 'astana', newBuildingOnly: true, maxItems: 100 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/krisha-kz").call(run_input={"dealType": "arenda", "city": "almaty-medeuskij", "ownerOnly": True, "sinceHours": 24})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

MCP: add `https://mcp.apify.com` to Claude / Cursor / any MCP client and call the `yadroo/krisha-kz` tool with the same JSON input.

### Speed and pricing

**Through Yadroo's server in Kazakhstan (first route, since 2026-11-09).** Since November 2026 krisha.kz answers its listing pages with a browser check to every automated request — from Apify's servers, residential proxies and home connections in Kazakhstan alike — while search pages still answer. Every krisha.kz page of a run is therefore read first through Yadroo's own server in Kazakhstan, which passes that check and reads the pages for all runs together, 2 at a time, about one per second: 40 listings with `detail: true` took 0.8 min (≈ 1.2 s per listing, every row with its detail fields; measured 2026-11-09), the first listing page of a run up to ~25 s while the check is passed. A page the server cannot read (busy, unreachable, krisha.kz refusing it) is read the usual way below; after 3 server failures in a row the run reads every remaining page the usual way and the status message says so. The server is used in both modes and at no extra cost.

**The usual way** (the server unavailable). Search pages are quick (~1 s each), so runs without `detail` are fast in every mode. With `detail: true` the run opens one listing page per row, 1.5 s after the previous one ended, plus the WAF's retries: about **6.5 s per listing** (measured 2026-10-02; FAQ → Rate limits). Fast mode opens them with several IPs at once, each at that same pace. Pick the mode with the `proxyConfiguration` input:

| Mode | How | 150 listings, `detail: true` | 500 listings, `detail: true` | Price per listing |
|---|---|---|---|---|
| **Normal** (default) | proxy off | ≈ 17 min (measured) | ≈ 55 min (close to the 1-hour default timeout) | **$0.003** |
| **Fast, Apify Proxy** | proxy on → Apify Proxy, group RESIDENTIAL (8 IPs) | ≈ 3 min (measured) | ≈ 10 min (estimated) | **$0.0045** |
| **Fast, Apify Proxy datacenter** | proxy on → any other Apify Proxy group (4 IPs: datacenter IPs are shared) | ≈ 5 min (estimated) | ≈ 18 min (estimated) | **$0.0045** |
| **Fast, your proxies** | proxy on → your proxy URLs, one per IP | like Apify Proxy with 8 or more URLs; one URL = normal speed | | **$0.003** |

Measured in the Apify cloud on 2026-10-02 (builds 0.1.9–0.1.10) with 2-room apartments for sale in Almaty, `sort: newest`, `detail: true`: 150 listings in 16.6 min normally (≈ 6.5 s per listing, the WAF's retries included) and in 3.0–3.2 min in fast mode on RESIDENTIAL; every row had its detail fields.

- **One price per listing in each mode.** A fast run on Apify Proxy charges the *fast-mode listing* event **instead of** the normal *listing* event, not on top of it; the extra $0.0015 pays for the proxy traffic (≈ 70 KB per listing, measured — the WAF's challenge answers add to it). While Yadroo's server in Kazakhstan is available at the start of a run, its listing pages do not go through the proxy, so a fast run is charged the normal *listing* price ($0.003) for every listing — also for listings the proxy takes over if the server drops out mid-run. With your own proxies the traffic is yours, so the normal price stays. Without `detail` the proxy is not used and the normal price applies. Run start: $0.02 in every mode.
- **Same pace per IP.** Each IP opens its next listing page 1.5 s after the previous one ended, like a normal run; 8 IPs at once on RESIDENTIAL, 4 on datacenter groups (a small shared datacenter pool could otherwise hand two sessions the same IP). An IP the WAF keeps refusing (5 tries in a row) is replaced by a new one (up to 3 times per IP slot); a listing that fails on 3 IPs keeps its card data with `detailError`.
- **Which proxy.** Apify Proxy group RESIDENTIAL worked in our tests. Your own proxies: `http://` or `https://` URLs (SOCKS is not supported), one URL per IP; a "rotating" gateway URL counts as one IP. `SUMMARY.speed` shows the mode, IPs used and the charged event.

**Discounts:** Bronze −5 %, Silver and above −10 % on the listing price (normal and fast); the start event ($0.02) is the same on every plan; platform usage and, in fast mode on Apify Proxy, the proxy traffic are included.

**Spending limit:** a run never costs more than your "Maximum cost per run": it stops at the limit and ends with "Stopped at your spending limit: N rows delivered". With `detail: true` it opens only as many listing pages as the limit pays for.

Typical runs (normal mode): 40 listings ≈ $0.14; 500-listing market snapshot ≈ $1.52. Monitoring pays only for new / repriced rows: an hourly `onlyNew` run with 3 new listings ≈ $0.029, a run with nothing new = $0.02. `detail: true` costs the same per item but takes about 6.5 s per listing longer; in monitoring mode only the new / repriced listings are opened. The `SUMMARY` record and the monitoring state are free.

### Limits & FAQ

- **Rate limits** — through Yadroo's server in Kazakhstan: listing pages 2 at a time at about one per second for all runs together (≈ 1.2 s per listing in a run, 50 listings/min, measured 2026-11-09). The usual way: ~0.7 s between search pages and 1.5 s after each listing page. krisha.kz is behind a WAF that randomly answers `468` to a share of requests; the Actor retries each page up to 6 times with growing backoff, so detail mode takes about 6.5 s per listing (measured 2026-10-02; `SUMMARY.wafRetries` counts the retries). If a listing page still fails, the item is kept with `detailError`. If most listing pages fail (5 or more, over half of those tried), krisha.kz is blocking: the run stops opening pages, keeps every row it saved, ends SUCCEEDED and says so in the status; the listings it did not open are not saved or charged.
- **Freshness** — data is read live from krisha.kz at run time; `publishedAt` on cards is day-precise and in Kazakhstan time ("сегодня" / "19 сен." are resolved against the Almaty calendar, so late-evening UTC runs date today's listings correctly). `views` (with `includeViews`) are live counters.
- **Filters on the results** — krisha.kz injects new-building developer cards into search results that ignore the room filter (a 3-room card in a 2-room search). Every card is re-checked against `rooms`, `priceFrom`/`priceTo` and `areaFrom`/`areaTo` where the card shows the value; non-matching cards are dropped (not charged) and counted in the log and in `SUMMARY.droppedNotMatchingFilters`. A developer card's price is a starting price ("от …"), so only `priceTo` can rule it out.
- **Blocks / errors** — every page goes through Yadroo's server in Kazakhstan first; what follows is the usual way, used for a page the server could not read. If krisha.kz refuses the first search page (403/429/468/5xx or no answer after 6 tries), the run waits 45 s and tries again; if it still refuses, or the page layout is not recognized, the run fails with a clear "start again in a few minutes" message instead of returning empty items (nothing is saved or charged except the run start). In fast mode (proxy on, `detail: true`) a search page the run's server cannot read (no answer after 3 tries, or refused) is read through your proxy instead, and so are the following search pages: a new proxy IP after each failure, with pauses growing from 5 s to 60 s (up to 6 IPs, about 3 minutes); only if those fail too does the run fail, naming both paths (`SUMMARY.speed.searchPages` shows which path the search pages took). A location krisha.kz does not know fails within seconds with "did you mean …" (see Reference → Accepted spellings). If a later search page fails, the run keeps what it saved, ends SUCCEEDED and names the page in the status and in `SUMMARY.pageError`.
- **Max items** — 5000 per run (up to 300 pages; checked live: page 400 still returns fresh listings). With `detail: true` budget about 1.2 s per listing through Yadroo's server in Kazakhstan, or 6.5 s the usual way — the default run timeout is 1 hour, so a normal run the usual way holds about 500. Rows are saved as the run goes. With `detail: true` the run collects only as many listings as it can open before the timeout and says so in the status ("Only N of up to M listings were collected …"); near the timeout it stops starting new pages, keeps what it saved and ends SUCCEEDED with "Stopped before the run timeout: N rows saved" (listings found but not yet opened are not saved or charged). Split very large jobs by district or price range, or use fast mode (see [Speed and pricing](#speed-and-pricing)).
- **View counts** — off by default (`includeViews`): krisha.kz's robots.txt disallows the counter endpoint `/ms/*`.
- **Phones** — not extracted (captcha-protected on the site).
- **Roadmap** — complex catalog mode (all listings inside a ЖК by name), map-bounds search.

***

Made by **Yadroo**. Sibling actors: [kolesa-kz](https://apify.com/yadroo/kolesa-kz) (cars), [kaspi-kz-products](https://apify.com/yadroo/kaspi-kz-products) (marketplace prices), [hh-kz-vacancies](https://apify.com/yadroo/hh-kz-vacancies) (jobs), [autoscout24-cars](https://apify.com/yadroo/autoscout24-cars) (EU cars).

# Actor input Schema

## `dealType` (type: `string`):

prodazha = for sale, arenda = for rent (monthly; use propertyType kvartiry-posutochno for daily rent).

## `propertyType` (type: `string`):

krisha.kz category slug. Rent-only: komnaty, kvartiry-posutochno, kvartiry-po-chasam, doma-dachi-posutochno. Sale-only: biznes. A value off this list is refused by Apify before the run (README → Reference lists them all).

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

krisha.kz location: a city, region or district — slug or name. Slugs: almaty, astana, shymkent, karaganda, aktobe, almatinskaja-oblast, almaty-bostandykskij, astana-esilskij… Russian, Kazakh and Latin names work too (Алматы, Бостандыкский район, Алматинская область, Нур-Султан, Karagandy, Almaty region); an unknown name stops the run at once with "did you mean". Empty = all Kazakhstan. Full list: README → Reference.

## `searchUrl` (type: `string`):

Paste the address of a krisha.kz search page after setting filters in the browser, e.g. https://krisha.kz/arenda/kvartiry/astana/?das\[live.rooms]\[]=1. Its section, property type, location, filters and sort are used instead of dealType, propertyType, city and sort; filters set below are added on top (the URL wins on the same filter). A listing or complex page is refused.

## `complexId` (type: `integer`):

Restrict to one residential complex (ЖК). The id is the number in the complex URL on krisha.kz, e.g. https://krisha.kz/complex/almaty/1234 → 1234.

## `rooms` (type: `array`):

Room counts to include: "1", "2", "3", "4", "5+" (five and more; "5" means the same), and for houses up to "10". Any other value fails the run with the list of allowed values (it is never ignored). Empty = any.

## `priceFrom` (type: `integer`):

Minimum price in tenge (monthly rent for arenda).

## `priceTo` (type: `integer`):

Maximum price in tenge.

## `areaFrom` (type: `integer`):

Minimum total area (for commercial property → premises area).

## `areaTo` (type: `integer`):

Maximum total area.

## `kitchenAreaFrom` (type: `integer`):

Apartments only.

## `kitchenAreaTo` (type: `integer`):

Apartments only.

## `floorFrom` (type: `integer`):

Apartments only.

## `floorTo` (type: `integer`):

Apartments only.

## `notFirstFloor` (type: `boolean`):

Exclude ground-floor apartments.

## `notLastFloor` (type: `boolean`):

Exclude top-floor apartments.

## `buildingFloorsFrom` (type: `integer`):

Minimum number of floors in the building.

## `buildingFloorsTo` (type: `integer`):

Maximum number of floors in the building.

## `yearFrom` (type: `integer`):

Building constructed in this year or later.

## `yearTo` (type: `integer`):

Building constructed in this year or earlier.

## `buildingType` (type: `string`):

brick = кирпичный, panel = панельный, monolith = монолитный, other = иной. Leave unset for any.

## `bathroom` (type: `string`):

Toilet/bathroom layout. Leave unset for any.

## `ownerOnly` (type: `boolean`):

Only listings posted by the property owner (`das[who]=1`). Great for lead generation.

## `fromAgentsOnly` (type: `boolean`):

Only listings from verified Krisha Agents (`das[_sys.fromAgent]=1`).

## `hasPhoto` (type: `boolean`):

Only listings with photos.

## `newBuildingOnly` (type: `boolean`):

Primary market (новостройки) only. Leave off for secondary + primary.

## `mortgageAvailable` (type: `boolean`):

Seller states the apartment qualifies for a mortgage.

## `notDormitory` (type: `boolean`):

Exclude apartments in former dormitories (общежитие).

## `exchangePossible` (type: `boolean`):

Seller accepts exchange (обмен).

## `furniture` (type: `string`):

Rent (arenda) only. Leave unset for any.

## `petsAllowed` (type: `boolean`):

Rent only: landlord accepts pets.

## `kidsAllowed` (type: `boolean`):

Rent only: landlord accepts families with kids.

## `houseType` (type: `string`):

Leave unset for any.

## `wallMaterial` (type: `string`):

Leave unset for any.

## `renovation` (type: `string`):

Leave unset for any.

## `heating` (type: `string`):

Leave unset for any.

## `sewage` (type: `string`):

Leave unset for any.

## `landAreaFrom` (type: `integer`):

Houses, land plots, garages. 1 sotka = 100 m².

## `landAreaTo` (type: `integer`):

Maximum land area in sotka (100 m²).

## `commercialUse` (type: `string`):

Leave unset for any.

## `commercialLocation` (type: `string`):

Leave unset for any.

## `withTenants` (type: `boolean`):

Premises sold/rented with existing tenants (income-producing).

## `asBusiness` (type: `boolean`):

Premises offered together with the business.

## `extraParams` (type: `object`):

Escape hatch for any krisha.kz filter not listed above, e.g. {"das\[flat.phone]": "1", "das\[garage.object_type]\[1]": "1"}. Copy the das\[...] keys from the krisha.kz URL after applying a filter in the browser; a key that does not start with das\[ fails the run (it is never silently dropped).

## `sort` (type: `string`):

Order of results as on krisha.kz. Paid 'hot' listings are always shown first on every page.

## `sinceHours` (type: `integer`):

Keep only listings published within the last N hours (krisha shows publish dates with day precision, so 24 = today+yesterday boundary, 48 = last two days…). With sort=newest pagination stops as soon as a page is entirely older — ideal for hourly monitoring. Empty = no time filter.

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

Stop after this many listings (pagination is automatic, ~20 listings per page). With detail: true each listing takes about 1.2 s through Yadroo's server in Kazakhstan, or 6.5 s the usual way (a 1-hour run then holds about 500 — use fast mode or split bigger jobs).

## `maxPages` (type: `integer`):

Hard cap on search pages fetched (safety limit).

## `detail` (type: `boolean`):

Fetch every listing page to add: full description, all parameters (balcony, parking, security, ceiling…), GPS coordinates, structured address, all photos, owner name & type, complex id, verified-estate flag, exact publish date. One extra request per listing, read through Yadroo's server in Kazakhstan, which passes krisha.kz's browser check (about 1.2 s each, measured 2026-11-09); if that server is unavailable, about 6.5 s each the usual way — fast mode (proxy) then opens several at once.

## `includeViews` (type: `boolean`):

Attach the site's view counter to each listing (one batch request per 25 listings). Off by default: the counter endpoint (/ms/views/…) is disallowed by krisha.kz's robots.txt — turn it on only if you accept that. Off = views is null.

## `dedupe` (type: `boolean`):

Drop repeated ids (paid listings are repeated in the 'hot' block on every page).

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

Return only listings that previous runs of the same search have not returned yet. The first run returns everything it finds and saves it as the baseline; later runs return only newcomers (changeType = "new"; recentlyPublished = true for listings published since the last run, false for older ones raised to the top). With sort = newest, paging stops once two pages in a row hold only known listings. The memory learns only listings a run really saved.

## `trackPriceChanges` (type: `boolean`):

Together with 'Only new listings': also return known listings whose price changed since they were last seen, with changeType = "price_changed", previousPrice, priceChange (₸) and priceChangePct. Price changes can be on any page, so these runs scan up to 'Max pages' instead of stopping early — lower 'Max pages' to limit depth. Turns on 'Only new listings' automatically.

## `monitorKey` (type: `string`):

Name of the saved state. Empty = derived from the search filters, so each distinct search has its own memory. Set the same name in two tasks to share one memory, or a new name (e.g. almaty-2room-v2) to start a fresh baseline. Letters, digits, dash, underscore and dot.

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

Off (default) = normal run, $0.003 per listing. On = fast mode for detail: true when Yadroo's server in Kazakhstan cannot read the listing pages: several IPs open them at once, each at the normal pace (150 listings: ~3 min instead of ~17). Apify Proxy: $0.0045 per listing instead of $0.003 (not both), or $0.003 while that server is available; 8 IPs on RESIDENTIAL, 4 on datacenter groups. Own proxy URLs (one per IP, up to 10): normal price. Without detail the proxy is not used.

## Actor input object example

```json
{
  "dealType": "prodazha",
  "propertyType": "kvartiry",
  "city": "almaty",
  "rooms": [],
  "notFirstFloor": false,
  "notLastFloor": false,
  "ownerOnly": false,
  "fromAgentsOnly": false,
  "hasPhoto": false,
  "newBuildingOnly": false,
  "mortgageAvailable": false,
  "notDormitory": false,
  "exchangePossible": false,
  "petsAllowed": false,
  "kidsAllowed": false,
  "withTenants": false,
  "asBusiness": false,
  "extraParams": {},
  "sort": "newest",
  "maxItems": 40,
  "maxPages": 50,
  "detail": false,
  "includeViews": false,
  "dedupe": true,
  "onlyNew": false,
  "trackPriceChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

## `overview` (type: `string`):

No description

## `summary` (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 = {
    "city": "almaty",
    "rooms": [],
    "extraParams": {},
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yadroo/krisha-kz").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 = {
    "city": "almaty",
    "rooms": [],
    "extraParams": {},
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("yadroo/krisha-kz").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 '{
  "city": "almaty",
  "rooms": [],
  "extraParams": {},
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call yadroo/krisha-kz --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yadroo/krisha-kz"
        }
    }
}
```

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/YqHWcSFupU8rnDzI3/builds/DVYC9do4s53ecTxa7/openapi.json
