Krisha.kz Real Estate Scraper | Kazakhstan Property
Pricing
from $0.87 / 1,000 listings
Krisha.kz Real Estate Scraper | Kazakhstan Property
Collect property listings from Krisha.kz (Kazakhstan): title, rooms, area, floor, price, currency, city, address, photo and listing link. No login, walk any search or category page.
Pricing
from $0.87 / 1,000 listings
Rating
0.0
(0)
Developer
Vitalii Bondarev
Maintained by CommunityActor stats
0
Bookmarked
12
Total users
3
Monthly active users
16 days ago
Last modified
Categories
Features
Share
Krisha.kz Real Estate Scraper
This Actor collects public property listings from Krisha.kz search and category pages in Kazakhstan and returns structured rows with titles, property types, rooms, areas, floors, prices, locations, images, and listing URLs. It needs no Krisha.kz login or API key; billing is $0.0009 per listing-result event and $0.00005 per apify-actor-start event on the Free tier, the default 2048 MB run uses two start events, and each Free-plan run returns at most 25 listings.
What you get
A dataset row is produced for each unique listing returned from the requested result pages. A source-derived field is null when the source does not provide its value; isNegotiable, scrapedAt, and parse_confidence are always present.
| Field | Type | Meaning | Null or empty behavior |
|---|---|---|---|
listingId | string | Krisha.kz listing identifier | null when no listing ID is found in the card or URL |
uuid | string | Card or photo UUID | null when the card does not provide it |
title | string | Listing title | null when the card does not provide a title |
propertyType | string | Normalized property type | apartment, house, land, or null for other card types |
rooms | integer | Room count parsed from the title | null unless the title contains an N-комнат value; it depends on the card type |
areaM2 | number | Area in square metres | null when the card does not provide an area; decimal values are supported |
landSotka | number | Land size in соток | null unless the title contains land-size text such as соток; decimal values are supported |
floor | integer | Property floor | null when the card does not provide a floor value; it depends on the card type |
totalFloors | integer | Total building floors | null when the card does not provide a total-floor value |
price | integer | Parsed numeric price. Some cards show a starting price (priceText begins with от); then price is that starting amount and nothing else marks it. | null for the bare text Договорная or price text without digits |
currency | string | Price currency code | null when no numeric price is available; defaults to KZT when digits appear without a recognized currency symbol |
priceText | string | Original price text from the card | null when the card does not provide price text |
isNegotiable | boolean | Whether the card marks the price as negotiable | Always true or false; never null |
address | string | Address from the listing card | null when the card does not provide an address |
city | string | City from the card statistics line | null when the card does not provide a city |
postedText | string | Posting-date text shown on the card | null when unavailable; source text has no year |
description | string | Description field from the list-page result | null for every result from list pages; the key is still present in every dataset row and export |
imageUrl | string | Listing image URL | null when the card does not provide an image |
url | string | Listing detail URL | null when the card does not provide a detail URL |
query | string | Start URL that produced the row | Not empty for emitted rows |
scrapedAt | ISO 8601 string | UTC timestamp created during the run | Always present |
parse_confidence | number | Share from 0 to 1 of the five core fields listingId, title, url, price, and city that are present | Always present and rounded to two decimals |
propertyType is limited to apartment, house, land, or null. The output has no field that marks a listing as sale or rent. Supported price symbols are converted to codes such as KZT, USD, EUR, and RUB.
For the bare price text Договорная, price and currency are null and isNegotiable is true. Non-digit characters are removed when the integer price is parsed; for example, a price text such as 1,5 млн ₸ would become 15, so check priceText for unusual cards. Text fields keep the language of the Krisha.kz page you request; the sample and recipes use the Russian pages. propertyType, rooms, floor, totalFloors and landSotka are read from Russian words in the card title (комнат, квартир, дом, коттедж, участок, этаж, сот), so a title that lacks those words gives null for them.
Sample output
The following two records are taken from a successful dataset sample produced from https://krisha.kz/prodazha/kvartiry/ with pagesToFetch: 3 and maxItems: 5.
[{"listingId": "1016119428","uuid": "5b56fada-3c12-43d6-adf0-70af982a1e10","title": "2-комнатная квартира · 41 м² · 4/5 этаж","propertyType": "apartment","rooms": 2,"areaM2": 41,"landSotka": null,"floor": 4,"totalFloors": 5,"price": 35000000,"currency": "KZT","priceText": "35 000 000 ₸","isNegotiable": false,"address": "Алмалинский р-н, Нурмакова 75 — Карасай Батыра","city": "Алматы","postedText": "5 окт.","description": null,"imageUrl": "https://krisha-photos.kcdn.online/webp/5b/5b56fada-3c12-43d6-adf0-70af982a1e10/21-full.jpg","url": "https://krisha.kz/a/show/1016119428","query": "https://krisha.kz/prodazha/kvartiry/","scrapedAt": "2026-10-05T13:32:00Z","parse_confidence": 1},{"listingId": "1012969209","uuid": "bc0bff17-2887-4133-8b4a-2464cbe2b4dd","title": "2-комнатная квартира · 70 м² · 6/10 этаж","propertyType": "apartment","rooms": 2,"areaM2": 70,"landSotka": null,"floor": 6,"totalFloors": 10,"price": 32900000,"currency": "KZT","priceText": "32 900 000 ₸","isNegotiable": false,"address": "Сарыарка р-н, Сейфуллина 5","city": "Астана","postedText": "5 окт.","description": null,"imageUrl": "https://krisha-photos.kcdn.online/webp/bc/bc0bff17-2887-4133-8b4a-2464cbe2b4dd/35-full.jpg","url": "https://krisha.kz/a/show/1012969209","query": "https://krisha.kz/prodazha/kvartiry/","scrapedAt": "2026-10-05T13:32:00Z","parse_confidence": 1}]
Pricing
This Actor uses live pay-per-event billing. A listing-result event is charged once per listing returned, and an apify-actor-start event is charged once per GB of run memory, with a minimum of one event.
Live event rates
Prices below are per event in USD. The applicable rate depends on the Apify pricing tier.
| Apify tier | apify-actor-start | listing-result |
|---|---|---|
| Free | $0.000050 | $0.000900 |
| Bronze | $0.0000495 | $0.000891 |
| Silver | $0.000049 | $0.000882 |
| Gold | $0.0000485 | $0.000873 |
| Platinum | $0.000048 | $0.000864 |
| Diamond | $0.0000475 | $0.000855 |
You pay only for the events listed below. This Actor does not use the Pay per event + usage option, so the platform usage of your runs (compute, proxy traffic and storage) is not billed to you separately.
Worked calculations
The Actor's default run memory is 2048 MB, so the default run is charged 2 apify-actor-start events. Changing the memory changes the number of apify-actor-start events.
A full Free-plan run of 25 listings costs:
25 × $0.000900 + 2 × $0.000050 = $0.0226
The Free-plan cap means that 1,000 or 10,000 listings are not returned by one Free run. At the Bronze tier rate, using the default 2048 MB memory:
- 1,000 listings:
1,000 × $0.000891 + 2 × $0.0000495 = $0.891099 - 10,000 listings:
10,000 × $0.000891 + 2 × $0.0000495 = $8.910099
These are totals for the Bronze tier at the stated listing counts, not the result of one Free-plan run.
The Apify Free plan includes $5 of platform credit each month. At the Free-plan rate, the $5 monthly credit covers 221 full runs (5,525 listings).
How it works
- The Actor accepts one or more Krisha.kz listing, category, or filtered-search URLs.
- It fetches each result page independently, adding
?page=for pages after the first. - It parses server-rendered
a-cardlisting blocks from the result-page HTML. - It normalizes title, price, location, property facts, media, source URL, query URL, scrape time, and parse confidence into a fixed row structure.
- It removes duplicates across the run using the listing ID when available. When no ID is available, it uses the title and address combination as a fallback key.
- It pushes parsed rows to the Apify dataset during the run and charges one
listing-resultevent per listing returned. - It writes an
OUTPUTrecord containingtotalListings,urlsRun, andpagesPerUrl.
Rows reach the dataset after the corresponding result page has been parsed, in batches as needed. Rows already pushed before an abort, timeout, or failure remain in the dataset; rows not yet pushed are absent.
The source pages are reached without a Krisha.kz login or API key. The default proxy configuration uses Apify's RESIDENTIAL proxy group with country KZ.
Input parameters
| Input | Type | Default | Details |
|---|---|---|---|
startUrls | Array of strings | https://krisha.kz/prodazha/kvartiry/ if empty | Krisha.kz listing, category, or search URLs only; other sites are not supported and are expected to return no rows. Each URL is paginated independently. |
pagesToFetch | integer | 3 | Number of result pages to walk per URL. Accepted range: 1 to 1000. |
maxItems | integer | 100 | Maximum listings returned across URLs and pages. 0 removes the cap, subject to the Free-plan preview cap and available pages. Minimum: 0. URLs are walked in the order given, so earlier URLs use the cap first. |
proxyConfiguration | object | Apify RESIDENTIAL, country KZ | Proxy configuration used to reach the public Krisha.kz pages. |
disableUsageStats | boolean | false | Set to true to turn off the run summary described in Usage statistics. |
The default proxyConfiguration is:
{"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "KZ"}
Example inputs
Apartment sale listings
{"startUrls": ["https://krisha.kz/prodazha/kvartiry/"],"pagesToFetch": 3,"maxItems": 100,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "KZ"}}
Apartment rentals in Almaty
{"startUrls": ["https://krisha.kz/arenda/kvartiry/almaty/"],"pagesToFetch": 10,"maxItems": 250,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "KZ"}}
Walk several result pages of one URL
{"startUrls": ["https://krisha.kz/prodazha/kvartiry/"],"pagesToFetch": 20,"maxItems": 0,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "KZ"}}
Combine sale and rental searches
{"startUrls": ["https://krisha.kz/prodazha/kvartiry/","https://krisha.kz/arenda/kvartiry/almaty/"],"pagesToFetch": 5,"maxItems": 300,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "KZ"}}
The output has no sale/rent flag or price-period field. Use the query field to tell the two searches apart, and do not average price across them. If a listing appears in both searches, de-duplication keeps the first query value.
maxItems is a ceiling. The number of rows is also bounded by pagesToFetch times the cards on each result page (the apartment-sale results page used to test this Actor held 23 cards), so raise pagesToFetch when you need more rows. On the Free plan every recipe returns at most 25 listings.
How to use
- Open this Actor in your Apify account and create a new run.
- Add one or more Krisha.kz URLs to
startUrls, using the recipes above as a starting point. - Set
pagesToFetchandmaxItemsaccording to the pages and listings you want. - Keep the default proxy configuration unless your run requires another supported Apify proxy setup.
- Start the run and use the resulting Apify dataset for the listing rows.
Limits and edge cases
- On the Apify Free plan, each run returns at most 25 listings across URLs and pages. This is a preview cap; paid Apify plans have no such cap.
maxItemsaccepts values from0upward.0removes the configured cap, but it does not remove the Free-plan cap of 25 listings per run.pagesToFetchaccepts values from1through1000for each start URL.- Any
pageparameter in a start URL is ignored. Each URL is walked from page 1, and later pages use thepagequery parameter. - Each start URL is walked independently. Earlier URLs can use the shared
maxItemscap before later URLs are reached. - Duplicate listings are removed across the run using
listingId, with a title-and-address fallback when no ID is available. - A page that fetches successfully but parses no records ends that URL normally; the run log shows
parsed 0 record(s)for that page. - A page fetch uses a 45-second timeout. The Actor makes up to three attempts for a page when a transport error or detected page-access issue occurs.
- HTTP statuses
401,403,429, and503, a response body shorter than 3,000 characters, or a response that contains neithera-cardnordata-idare treated as page-access failures. - A results page with no listing cards still carries the
data-idmarkers of the site menu, so it is not treated as a blocked page: it ends that URL normally, without retries. Only a response that matches the previous point is retried three times and then treated as a blocked page; that stop reason is written to the run log only. - A blocked page ends the run as Succeeded, possibly with 0 rows or a short dataset. The Actor skips the remaining pages of that URL and moves to the next URL.
OUTPUTin the run's default key-value store recordstotalListings,urlsRun, andpagesPerUrl, but not the block or fetch-error reason. - A proxy connection error while fetching a page is retried up to three times and then handled like a blocked page (run Succeeded, possibly with 0 rows). An error raised outside the page fetch, for example while creating the proxy configuration or reading the input, ends the run as Failed. Rows pushed before a timeout, abort, or failure remain in the dataset; later rows are not added.
- The parser tolerates missing card cells and returns
nullvalues for fields that are not available. A malformed page can produce an empty result for that page. - The Actor reads listing cards from result pages only; it does not open each listing's detail page, so fields that exist only on the detail page are not included.
postedTextis retained as source text, whilescrapedAtis generated as a UTC timestamp for the Actor run.- Results depend on what Krisha.kz returns for the requested URL, pagination, and page-access conditions.
- For rental searches,
priceis the amount shown on the card, but no price period is captured. For the bare textДоговорная,priceandcurrencyarenullandisNegotiableistrue. If the price text also contains digits,priceholds them, andisNegotiableis stilltruewhen the wordдоговорнаяappears. - A
priceTextthat begins withотis a starting price;priceholds that amount without a flag. - If a price contains digits but no recognized currency symbol,
currencydefaults toKZT. Non-digit characters are removed whenpriceis converted to an integer. parse_confidenceis the fraction of the five core fieldslistingId,title,url,price, andcitythat are present, rounded to two decimals. A negotiable-price listing can therefore have a maximum value of0.8whenpriceis missing.descriptionisnullfor every result from list pages. The key is still present in every dataset row and in exports, but the Console overview table does not show it.
Integrations
Apify dataset
Listing rows are pushed to the Actor's Apify dataset during the run. The dataset contains the normalized fields described in What you get and can be exported as JSON, CSV, or Excel from the Apify Console or API.
Apify run output
The Actor writes an OUTPUT record to the run's default key-value store:
{"totalListings": 0,"urlsRun": 0,"pagesPerUrl": 0}
totalListings is the number of rows pushed. The record is written after the last start URL has been processed; a run that fails, times out or is aborted before that has no OUTPUT record. urlsRun is the number of non-empty start URLs in the input (1 when the default URL is applied), including URLs skipped because maxItems was already reached. pagesPerUrl is the requested pagesToFetch value, not necessarily the number of pages actually fetched.
Related actors
| Actor | What it does |
|---|---|
| Idealista Scraper | Collects Spain real estate listings, prices, and square-metre information. |
| OnTheMarket Scraper | Collects UK property data, prices, and days listed. |
| Zoopla Scraper | Collects UK property listings, prices, and agent information. |
FAQ
Does the Actor require a Krisha.kz login or API key?
No. The Actor reads public Krisha.kz result pages and needs no Krisha.kz login or API key. You only configure the run in your Apify account.
Which Krisha.kz URLs can I use?
Use Krisha.kz listing, category, or filtered-search URLs copied from the site. Example URLs from the input schema include https://krisha.kz/prodazha/kvartiry/ and https://krisha.kz/arenda/kvartiry/almaty/; other sites are not supported and are expected to return no rows.
How does pagination work?
pagesToFetch controls the number of result pages per URL, from 1 to 1000. Any page parameter in a start URL is ignored, so each URL begins at page 1; later pages use the page query parameter.
Why did the Actor return fewer listings than expected?
Possible causes include a low pagesToFetch (rows are bounded by pagesToFetch times the cards on each result page, so maxItems is only a ceiling), maxItems, duplicate listings, a result page with no parsed cards, a card with neither a listing ID nor a title (skipped), or a page that remains unavailable after three attempts. On the Free plan, each run also has a preview cap of 25 listings, even when maxItems is higher or set to 0.
Why is description null?
description is null for every result from list pages. The key is still present in every dataset row and in exports, but the Console overview table does not show it.
What happens when a source field is missing?
The parser keeps the row and sets the unavailable field to null where applicable. Missing card cells can therefore reduce field coverage without stopping the whole run. A card with neither a listing ID nor a title is skipped. Missing card cells can therefore reduce field coverage without stopping the whole run.
Does propertyType show whether a listing is for sale or rent?
No. propertyType can be apartment, house, land, or null, but the output has no sale/rent field. For mixed searches, use query to identify the start URL that produced the row.
Does maxItems: 0 remove the configured cap?
It removes the configured maxItems cap and allows the Actor to walk the requested pages. It does not remove the Free-plan cap of 25 listings per run, and the Actor also stops when there are no more parsed records or when a page cannot be processed.
Can I use the returned listing URLs to open individual properties?
Yes. The output includes a url field for each listing. The Actor reads result pages and extracts those links; it does not fetch the individual detail pages.
What proxy configuration is recommended?
The default input uses Apify's RESIDENTIAL proxy group with country KZ. You can provide another supported proxyConfiguration value when needed.
Does using this public data comply with applicable law?
The Actor collects public data from Krisha.kz result pages. Whether a particular use is permitted depends on the source's terms and applicable law for your use case, so review them before using the data. This Actor does not provide a legal guarantee.
Usage statistics
At the end of each run this Actor creates a short summary of how the run went and sends it over HTTPS to a server run by the Actor's developer. It is used to monitor reliability and improve this Actor. A copy is saved as USAGE_STATS in your own Apify key-value store, so you can see the exact record created for your run.
Set disableUsageStats to true in the input to opt out. Nothing is sent then; your USAGE_STATS record only says that statistics were disabled.
The summary contains at most these items (an item this Actor does not track is left out):
- schema version, Actor name and build number;
- UTC start and finish hour (not a precise timestamp);
- run duration, number of results and time to the first result, each as a coarse range;
- whether the result was empty, the end status, and an error type from a fixed list;
- memory setting and counts of charged events;
- names of the input fields you set, and the selected option for fields that offer a fixed list of choices (for example a country or a sort order);
- the size range of list inputs, the requested result count as a range, how much of it was delivered, whether it was reached, and the average number of results per input entry as a range;
- coarse shares of filled fields, failed rows and duplicate rows, and the range of distinct field names in the output;
- how the run was started (for example API, Console or schedule), whether it was aborted, timed out or stopped at your charge limit, and how many times it was restarted;
- the range of input targets that succeeded or failed, and the most common failure reason from a fixed list;
- your Apify user ID, whether Apify marks your account as paying, and one category from a fixed Actor list;
- two 8-character fingerprints (short hashes): one of the input field names you set, and one of your input values without the proxy settings. The same input always gives the same fingerprint, which lets us count repeated runs of one input.
Apart from those fingerprints, the summary holds no input text, search terms, URLs, domains, email addresses, names, proxy credentials, tokens, scraped records, output items, raw error messages or stack traces. It is used only for aggregated reliability and repeat-use statistics. We do not sell or share this data, and we do not try to identify people from it.