Yandex Realty Scraper
Pricing
from $4.20 / 1,000 results
Yandex Realty Scraper
Get Russian real estate listings from Yandex Realty: price with real change history, exact address with GPS and metro walk time, area, rooms, floor, building detail, seller info, and photos. Filter by city, price, and rooms, paste a search URL, or look up specific offers by ID.
Pricing
from $4.20 / 1,000 results
Rating
0.0
(0)
Developer
Norm Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share

Yandex Realty Scraper
Get Russian real estate listings from Yandex Realty (realty.yandex.ru) with no login and no API key: price with real price-change history, exact address with GPS and metro walk time, area, rooms, floor, building and renovation detail, seller info, photos, and the full listing description. Search by city, deal type, and category with real server-side filters, paste any search URL built on the site itself, or look up specific offers by ID.
Here is one real row:
{"offer_id": "7035113340557210816","offer_type": "SELL","category": "APARTMENT","url": "https://homeapp.ru/apartment/5844479","price": 25600000,"currency": "RUR","price_per_meter": 345946,"price_trend": "DECREASED","previous_price": 26000000,"has_price_history": true,"rooms_total": 3,"area_sqm": 74,"floor": 12,"floors_total": 12,"address": "улица Адмирала Лазарева, 40","latitude": 55.54426,"longitude": 37.52325,"metro_station": "Улица Горчакова","metro_time_minutes": 7,"metro_transport": "ON_FOOT","seller_type": "AGENCY","seller_name": "Homeapp","total_images": 18,"scraped_at": "2026-09-12T00:00:00.000Z"}
What it does
Reads realty.yandex.ru's own server-rendered pages directly and normalizes every listing into a flat row.
- Search filters the whole catalog: city, buy or rent, property type, room count, price range, and area range.
- Search URL lets you paste any search-results link built on realty.yandex.ru's own site - every filter it supports, not just the ones exposed below.
- Look up resolves exact offer IDs (or full offer URLs), one row per offer, additionally including a real dated price-history series that search rows don't carry.
- Any search can also fetch each result's price history in the same run (
includePriceHistory) instead of needing a separatelookupcall per offer ID afterwards.
Missing source values are returned as null, never invented.
Why this scraper
- Real price history, without a separate
lookupstep. Fetch it directly from a search withincludePriceHistory- a full dated series of every past price for a listing. Billed as its own event, same as other Actors in this category, because it genuinely costs more: measured directly on two real runs of the same query, turning it on made the run 5.6x slower and pull 13x more data (one extra full page fetch per row). - A price range that reaches further than the site's own 25-page pagination limit. realty.yandex.ru caps one filtered search at 25 pages no matter how many listings match - confirmed live. This Actor automatically splits an oversized price range in half (using the real sampled prices already fetched, not a blind numeric midpoint) and searches each half independently, so a broad city-wide search can still reach a large row count instead of silently stopping at the first ~500.
- Full listing detail in one request - exact address, GPS coordinates, metro station with real walk time, building year/type/parking/heating, renovation state, and the complete description, not just the headline numbers.
- Paste-a-URL flexibility. Anything you can filter for on realty.yandex.ru's own site, you can run here.
- No API key, no login, no browser. Reads only what a normal visitor's page load reads - confirmed captcha-free across every real request made while building this Actor.
How it compares
Checked directly against both other Yandex Realty scrapers on Apify (their own declared pricing and README, not a guess):
| Capability | This actor | zen-studio/yandex-realty-scraper | sian.agency/yandex-realty-scraper |
|---|---|---|---|
| Apartments, houses, rooms, land, garages, commercial | yes | yes | yes |
| Search by city/price/rooms/area filters | yes | yes | yes |
| Paste a custom search URL | yes | not documented | yes |
| Price history | fetch it from a search directly (includePriceHistory), no separate run | separate paid add-on (own run/mode) | not documented |
| Phone/contact number extraction | not included | yes (paid add-on) | not documented |
| Automatic handling of the site's 25-page search limit | yes (price-range splitting) | yes (geographic splitting) | not documented |
The one honest gap: phone/contact reveal is a client-side action behind what looks like a session/token flow on Yandex's own site - not attempted here rather than faked or guessed at.
Use cases
- Investment sourcing. Filter and rank listings by price, area, and price-per-m² across a whole city or price band.
- Market research. Track how many listings and at what price a city/category/room-count combination carries over time.
- Relocation and rental search. Pull every match for a city with real metro-distance and building detail, beyond what a manual browse would cover.
- Price-change tracking. Use
has_price_history/price_trendfrom a search sweep, or the full dated series from alookupcall, to watch specific listings. - Lead generation. Compile seller/agency lists by city and category.
- Portfolio/appraisal feeds. Structured price, area, and location data ready for a valuation model or a map.
Quickstart
Search: 2-3 room apartments for sale in Moscow, 15-30M RUB.
{ "mode": "search", "citySlug": "moskva", "dealType": "kupit", "category": "kvartira", "roomsTotal": [2, 3], "priceMin": 15000000, "priceMax": 30000000, "maxItems": 200 }
Search URL: paste any link built on realty.yandex.ru's own filters.
{ "mode": "url", "searchUrl": "https://realty.yandex.ru/sankt-peterburg/snyat/kvartira/?roomsTotal=1", "maxItems": 100 }
Look up specific offers, including full price history:
{ "mode": "lookup", "offerIds": ["7035113340557210816", "https://realty.yandex.ru/offer/123456789012/"] }
Search, but with each result's price history fetched too - no separate lookup call needed:
{ "mode": "search", "citySlug": "moskva", "category": "kvartira", "roomsTotal": [2], "maxItems": 50, "includePriceHistory": true }
Input reference
| Field | Applies to | Description |
|---|---|---|
maxItems | all | Ceiling on rows written. |
mode | all | search, url, or lookup. |
citySlug | search | Yandex's own city URL segment, e.g. moskva, sankt-peterburg, kazan. |
dealType | search | kupit (buy) or snyat (rent). |
category | search | kvartira, dom, komnata, uchastok, garazh, or kommercheskaya-nedvizhimost. |
roomsTotal | search | Array of 1-5 (5 = "5+"). Empty means any. |
priceMin / priceMax | search | Price range, RUB. |
areaMin / areaMax | search | Area range, m². |
sort | search | DATE_DESC for newest first (verified); other values pass through as-is. |
includePriceHistory | search, url | Also fetch each result's price history (one extra request per row - off by default). |
searchUrl | url | A full search-results URL from realty.yandex.ru. |
offerIds | lookup | Offer IDs or full offer URLs. |
Output reference (selected)
| Field | Description |
|---|---|
offer_id / offer_type / category / url | Identity. |
price / currency / price_per_meter / price_trend / previous_price | Pricing. |
rooms_total / area_sqm / living_space_sqm / kitchen_space_sqm / floor / floors_total | Layout. |
address / latitude / longitude / metro_station / metro_time_minutes | Location. |
building_year / building_type / parking_type / heating_type / renovation | Building. |
seller_type / seller_name | Who's listing it. |
description / total_images / image_urls | Content. |
price_history | Look-up mode only: { date, price }[], null on a search row. |
price_out_of_requested_range | true when a search row's live price no longer fits the priceMin/priceMax you asked for (see FAQ), false when it does, null when no price filter was set or the row isn't from a filtered search. |
query / error | Set on an unresolved look-up row. |
scraped_at | ISO 8601 collection timestamp. |
Run via API and CLI
curl -X POST "https://api.apify.com/v2/acts/USERNAME~yandex-realty-scraper/run-sync-get-dataset-items?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"mode":"lookup","offerIds":["7035113340557210816"]}'
$apify call USERNAME/yandex-realty-scraper --input '{"mode":"search","citySlug":"moskva","category":"kvartira","maxItems":500}'
Fetch results
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"
Billing and limits
- Pay per result. Billed per row written.
- No charge on failure. A run that produces zero rows fails with a message and is not billed.
- An unresolved look-up offer ID still writes one
error: "not found"row and is billed as a base row. - A row flagged
price_out_of_requested_range: true(see FAQ) is still a real, fully-detailed row and is billed normally - it's kept and flagged rather than silently dropped. includePriceHistorybills a separate event per row it's actually fetched for (nothing charged on a failed fetch - that row'sprice_historyis just leftnull). It's a real, separate cost: measured directly, turning it on made an otherwise-identical run 5.6x slower and pull 13x more data, one extra full page fetch per row.- Free Apify plans run the built-in 10-row sample only.
FAQ and troubleshooting
Do I need a Yandex account or API key? No. realty.yandex.ru's own public pages are read directly, with no key and no login.
Why did my search return zero rows? No listing matched the filters, or citySlug doesn't
match a real Yandex city segment - browse realty.yandex.ru directly and copy the segment right
after the domain to confirm it.
Why can a broad search take longer than expected? realty.yandex.ru itself caps one filtered
search at 25 reachable pages (500 rows), no matter how many listings actually match. A search that
needs more than that automatically splits its price range and searches each half separately,
which takes real extra requests - the honest tradeoff for reaching a larger maxItems instead of
silently stopping at ~500.
Can this get phone numbers? No. Revealing a number on realty.yandex.ru is a client-side action behind what looks like a session/token flow, not a plain page read - not attempted here rather than faked.
Why is price_history null on search rows? It's only present on a single offer's own page
(lookup mode). Search-result rows don't carry it at all in the source - confirmed live, not a
gap in how this Actor reads it. Set includePriceHistory: true to have a search run fetch it for
every result automatically, instead of needing a separate lookup call per offer ID afterwards.
Why is rooms_total empty for some listings? Studios and non-residential categories (land,
garages, some commercial listings) genuinely have no room count in the source.
Why does currency say "RUR" instead of "RUB"? That's the real value Yandex's own API
returns (an older-style code still used internally) - passed through as-is, not corrected to a
guess.
Why does a row have a price outside the priceMin/priceMax I set? realty.yandex.ru's own
search index can lag a listing's live price by minutes to hours. Verified directly: one real
listing swung between 22.4M and 26.4M RUB five times in six days (agencies appear to do this
deliberately, to surface under more price-filter searches over time as the market re-indexes).
Yandex's own filter can still match the listing at a price that was true when it was indexed,
while the live price shown by the time this Actor reads it has already changed again. Rather than
silently dropping that row (or silently keeping it with no explanation), it's kept and flagged
price_out_of_requested_range: true - check price_trend/previous_price on the same row for
the change that caused it. Measured at scale: about 2-3% of rows in a filtered search.
How current is the data? Read live from realty.yandex.ru on every run. It is not cached.
Is this an official Yandex tool? No. Independent, not affiliated with Yandex. It reads only publicly available pages.
Local development
bun installbun test # offline: normalisation, URL building, splitting logic (real fixtures)bun run src/main.ts # reads storage/key_value_stores/default/INPUT.json