# Cian RU - Property Listings, Search Filters & URLs (`abotapi/cian-ru-scraper`) Actor

Collect property listings from Cian.ru by search filters or direct URLs. Returns structured rows with listing URL, title, price, address, rooms, area, floors, photos, visible contact fields, coordinates when available, and optional detail-page enrichment.

- **URL**: https://apify.com/abotapi/cian-ru-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 54 total users, 15 monthly users, 86.5% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 dataset items

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

## CIAN Scraper: Property Listings, Prices, Photos & Contacts

CIAN Scraper turns CIAN (Cian.ru), Russia's largest real estate listing site, into a clean property data feed. Collect apartment, room, house, new building and commercial listings for sale or rent, with prices, addresses, room counts, floor and building details, coordinates, photos, descriptions and contact phone numbers included on every row. Search by location and filters, or paste Cian search result links directly, then export to JSON, CSV or Excel, or read the results through the API.

### Why This Scraper?

- **Two ways in.** Search by location and filters, or paste Cian search result URLs directly.
- **Every row comes ready to use.** Price, address, rooms, area, floor, coordinates, photos, description and contact phone numbers are included on every saved listing, no extra step.
- **An optional detail step.** Turn on Fetch listing details for fields that only live on the listing page itself: agent and agency identity, a running view count, BTI-verified build year, renovation type, and more.
- **Covers the whole market.** Flats, rooms, houses, new buildings, and commercial categories, for sale or for rent.
- **Built for monitoring.** Resume one interrupted crawl, or track a saved search across a schedule and get back only what changed.
- **A power-user escape hatch.** Pass Cian's own raw filter fields when the built-in filters aren't enough.
- **Fails loudly instead of guessing.** If nothing could be read or matched, the run stops with a clear message instead of quietly returning an empty dataset.

### Use Cases

- **Real estate agencies and brokers:** build and refresh a listings feed for a market segment, building complex, or client search.
- **Price and market research:** track price per square meter, floor, and room count trends across districts and cities.
- **Property investment monitoring:** watch a saved search over time and get back only the new, updated, or delisted properties.
- **Lead generation and outreach:** collect agent and agency names alongside contact phone numbers and listing details.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `id` | `123456789` |
| `url` | Cian link to the listing |
| `title` | `"2-комн. кв., 54 м², 5/9 эт."` |
| `jkName` | `"ЖК Северный"` (new building complex name, when the listing belongs to one) |
| `price` / `priceValue` | `"12 500 000 ₽"` / `12500000` |
| `pricePerMeter` / `currency` | `231481` / `"rur"` |
| `address` | `"Москва, Пресненский р-н, ул. Ленина, 10"` |
| `district` / `metro` / `metroTime` | `"Пресненский"` / `"Баррикадная"` / `7` |
| `metroLineId` / `metroLineColor` | `3` / `"00701A"` (line of the nearest station) |
| `roomsCount` | `2` |
| `totalArea` / `livingArea` / `kitchenArea` | `54` / `32` / `10` |
| `floorNumber` / `floorsCount` | `5` / `9` |
| `buildYear` / `materialType` | `2015` / `"monolith"` |
| `dealType` / `category` / `offerType` | `"sale"` / `"flatSale"` / `"flat"` |
| `isFromDeveloper` / `isPremium` / `isApartments` | `false` / `false` / `false` (`true` for apartment-hotel units) |
| `phoneNumbers` | `["+79991234567"]` |
| `latitude` / `longitude` | `55.7601` / `37.6103` |
| `description` / `formattedFullInfo` | `"Просторная квартира с ремонтом, рядом метро"` / `"4-комн.кв. · 6/21 этаж"` (short card summary) |
| `imageUrls` | array of photo links |
| `mainImage` / `siteUrl` | `{"full": "https://img.cian.site/a.jpg"}` (cover photo) / `"https://www.cian.ru/sale/flat/123456789/"` (same link as `url`) |
| `formattedAddress` / `formattedFullPrice` | `"Москва, Пресненский р-н, ул. Ленина, 10"` / `"12 500 000 ₽"` (as displayed on the card) |
| `ceilingHeight` | `2.8` (metres, when the listing states it) |
| `agent` / `geo` | `{"userId": 141493134, "accountType": "agency", "agencyName": "Компания PIONEER", "isAgent": true, "isBuilder": true}` / `{"coordinates": {"lat": 55.7601, "lng": 37.6103}}` |
| `creationDate` / `addedLabel` | `"2026-09-20T10:00:00+03:00"` / `"вчера, 14:40"` |
| `scrapedAt` | `"2026-09-28T08:00:00.000Z"` |

The `mainImage`, `siteUrl`, `formattedAddress`, `formattedFullPrice`, `ceilingHeight`, `agent`, `geo`, `metroLineId`, `metroLineColor` and `isApartments` fields come from the search card itself, so they are present even with **Fetch listing details** off (a field the listing does not state is `null`).

Note: `metroTime` is the minutes to the nearest station as Cian shows it. On some cards it can be transport time rather than walking time, and the travel mode is not part of the output.

When **Fetch listing details** is on, a successfully enriched row also carries `agentName`, `agentCompanyName`, `agentType`, `agentIsPro`, `agentOffersCount`, `agentAvatarUrl`, `viewsTotal`, `viewsToday`, `houseBuildYear` (BTI-verified, often populated when the search card's own `buildYear` is empty), `houseEntrances`, `houseFlatCount`, `houseLiftsTotal`, `houseHeatSupplyType`, `houseGasSupplyType`, `houseIsEmergency`, `repairType`, `windowsViewType`, `balconiesCount`, `bathroomsCombined`, `bathroomsSeparate`, `parkingType`, `amenities`, and a `detailStatus` of `ok`. When a detail fetch fails, that row still ships with `detailStatus: "skipped"` and no extra fields, at no extra charge. Incremental mode adds `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt` to every row, only when it is switched on.

### How to Use

1. Pick a **mode**: `search` (location and filters) or `url` (paste Cian search-result links).
2. For search mode, set **Location**, **Operation**, **Category**, and any of the price, area, floor, or room filters you need.
3. Set **Max items** to control run size and cost, and turn on **Fetch listing details** if you need agent info, view counts, or BTI-verified building data.
4. Click **Start**, then download the dataset as JSON, CSV or Excel, or read it through the API.

In URL mode, Cian answers a link without a city (a plain `www.cian.ru` search link) with the page of the city nearest the connection. The actor checks that the page it received belongs to the host you pasted; if not, it discards that page and retries the link on a fresh connection. A wrong city is never scraped, but on some residential connections a region-less `www.cian.ru` link can be skipped (the geo-redirect is refused) rather than returned, so prefer a city subdomain or `region=` for reliable results. Use a city subdomain (for example `spb.cian.ru`) or a `cat.php` link with `region=` to pin another city.

**Search Moscow flats for sale under 15,000,000 RUB:**

```json
{
  "mode": "search",
  "location": "Москва",
  "operationType": "sale",
  "category": "flatSale",
  "rooms": ["2"],
  "maxPrice": 15000000,
  "maxItems": 50
}
```

**Paste a Cian search-result URL:**

```json
{
  "mode": "url",
  "urls": ["https://www.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat&region=1&p=2"],
  "maxItems": 100
}
```

**Saint Petersburg rentals with full listing details:**

```json
{
  "mode": "search",
  "location": "Санкт-Петербург",
  "operationType": "rent",
  "category": "flatRent",
  "fetchDetails": true,
  "maxItems": 30
}
```

**Power-user filter using Cian's own raw query field:**

```json
{
  "mode": "search",
  "location": "Москва",
  "operationType": "sale",
  "advancedFilters": { "repair": { "type": "terms", "value": [2, 3] } },
  "maxItems": 20
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/cian-ru-scraper").call(run_input={"mode": "search", "location": "Москва", "operationType": "sale", "maxItems": 50})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(listing["title"], listing["price"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/cian-ru-scraper').call({ mode: 'search', location: 'Москва', operationType: 'sale', maxItems: 50 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Filters and sorts (search mode)

- **Sort:** default, price low to high, price per m² low to high or high to low, area large first, newest first, walking time to metro, oldest first (`creationDateAsc`), area small first (`totalAreaAsc`).
- **Numeric filters:** price, total area, living area (`minLivingArea`, `maxLivingArea`), floor, building floors, building year (`minHouseYear`, `maxHouseYear`), ceiling height (`minCeilingHeight`, `maxCeilingHeight`).
- **Toggles:** only from owners (`isByHomeowner`), from developer (`fromDeveloper`), first floor only (`isFirstFloor`), not last floor (`notLastFloor`), with video (`hasVideo`), with floor plan (`withLayout`), short-term daily rent (`shortTermRent`).
- **Lists and windows:** `rooms`, `repair` (1 none, 2 cosmetic, 3 euro, 4 designer), `publishPeriod` (last hour, 12 hours, today, 24 hours, week, month).

In URL mode the filters and sort are read from the pasted URL instead.

#### Output views

The dataset has three views, also linked from the run's Output tab: **Overview** (the main listing columns), **Changes (incremental)** (`changeType`, `changedFields`, `firstSeenAt`, `lastSeenAt`, price) and **Detail enrichment** (phones, views, BTI build year, renovation type, `detailStatus`). Every view reads the same rows.

#### Fetch listing details

`fetchDetails` loads each saved listing's own page for fields the search results don't carry: agent and agency identity, a running view counter, BTI-verified build year, renovation type, window view, balcony and bathroom counts, parking type, and amenities. It runs only on rows already selected to be saved, after any incremental suppression and the Max items cap, so a suppressed or capped-off listing is never fetched or charged for. It is billed as a detail-enrichment charge, only for listings whose detail page was actually read successfully; a failed detail fetch still returns the base row (with `detailStatus: "skipped"`) at no extra charge.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted crawl: paste its run or dataset ID and this run skips every listing id already saved there, appending only new ones.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same saved search. Each listing is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED`, or `EXPIRED` (only after a run that scanned the entire tracked search from its first page, and only with `emitExpired`; a pasted URL that starts past page one, such as one with `p=2`, never computes `EXPIRED`). `stateKey` names or shares the stored baseline; leave it empty and identical searches share one automatically, while different ones never mix. With incremental mode off, output is exactly as before. The search filters (living area, house year, ceiling height, owner, developer, floor, video, layout, renovation, publication period, daily rent) are part of the tracked search, so two schedules that differ only in one of them keep separate baselines. Change detection always leaves out `scrapedAt` (the actor's own timestamp) and `addedLabel` (cian's relative "yesterday, 14:40" label); both are still saved in the row. Use `ignoreFieldsForChanges` to also leave out any other field (for example `imageUrls` or `description`): it stays in the output but never makes a listing `UPDATED`, and changing the list later does not cause a one-time wave of `UPDATED` rows.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` for filters, or `url` for pasted Cian links. |
| `urls` | array | 12 example URLs (see below) | Cian search-result URLs (encode filters in the URL). URL mode only; the search filters below are ignored in this mode. With the field left untouched, URL mode now scrapes the default example URLs (a behaviour change: it previously had no default). |
| `location` | string | `Москва` | Search mode only. A city name in Russian or English (Москва, Санкт-Петербург, Казань, Нижний Новгород). Moscow, Saint Petersburg and Kazan are built in; any other name is resolved through the site's own city pages. If nothing matches, the run stops with an error asking you to fix the spelling or set `regionId`; it does not silently fall back to Moscow. |
| `regionId` | integer | (none) | Search mode only. Cian region ID (Moscow is 1, Saint Petersburg is 2). When set it overrides `location`. Left empty, the region comes from `location`. |
| `operationType` | string | `sale` | Search mode only. Deal type: `sale` or `rent`. |
| `category` | string | `""` (Any) | Search mode only. Listing category, or Any to let operation and property type decide. |
| `sort` | string | `default` | Search mode only. Sort results when supported by the selected source. |
| `rooms` | array | (none) | Search mode only. Room counts for flats and rooms. |
| `includeStudio` | boolean | `false` | Search mode only. Include studio listings together with the selected room counts. |
| `minPrice` | integer | (none) | Search mode only. Minimum price in rubles. |
| `maxPrice` | integer | (none) | Search mode only. Maximum price in rubles. |
| `minArea` | integer | (none) | Search mode only. Minimum total area in square meters. |
| `maxArea` | integer | (none) | Search mode only. Maximum total area in square meters. |
| `minFloor` | integer | (none) | Search mode only. Minimum floor. |
| `maxFloor` | integer | (none) | Search mode only. Maximum floor. |
| `minFloors` | integer | (none) | Search mode only. Minimum floors in the building. |
| `maxFloors` | integer | (none) | Search mode only. Maximum floors in the building. |
| `minLivingArea` | integer | (none) | Search mode only. Minimum living area in m2. |
| `maxLivingArea` | integer | (none) | Search mode only. Maximum living area in m2. |
| `minHouseYear` | integer | (none) | Search mode only. Earliest building year. |
| `maxHouseYear` | integer | (none) | Search mode only. Latest building year. |
| `minCeilingHeight` | number | (none) | Search mode only. Minimum ceiling height in metres. |
| `maxCeilingHeight` | number | (none) | Search mode only. Maximum ceiling height in metres. |
| `isByHomeowner` | boolean | `false` | Search mode only. Only listings placed by the owner. |
| `fromDeveloper` | boolean | `false` | Search mode only. Only listings placed by the developer. |
| `isFirstFloor` | boolean | `false` | Search mode only. Only first-floor listings. |
| `notLastFloor` | boolean | `false` | Search mode only. Exclude top-floor listings. |
| `hasVideo` | boolean | `false` | Search mode only. Only listings with a video. |
| `withLayout` | boolean | `false` | Search mode only. Only listings with a layout drawing. |
| `shortTermRent` | boolean | `false` | Search mode only. With operation Rent, only daily-rental listings. |
| `repair` | array | (none) | Search mode only. Cian renovation codes (1 none, 2 cosmetic, 3 euro, 4 designer). |
| `publishPeriod` | string | \`\` | Search mode only. Only listings published in this window. |
| `advancedFilters` | object | (none) | Search mode only. Raw Cian query objects merged into the search, for power users who know Cian's own query field names. |
| `maxItems` | integer | `20` | Maximum matching rows to save (hard cap 100000 per run). Fewer rows can be returned when the selected source and filters match fewer live records. |
| `maxPages` | integer | `0` | No page limit when set to `0`. The run still stops at Max items. |
| `fetchDetails` | boolean | `false` | Load each saved listing's own detail page for richer fields not on the search card. Billed as a detail-enrichment charge. |
| `proxy` | object | Apify Proxy | Connection settings. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |
| `resumeFromRunId` | string | (none) | Continue one interrupted crawl: paste a previous run ID (or dataset ID) and this run skips listings it already saved. |
| `incrementalMode` | boolean | `false` | Remember this search's results between scheduled runs and report only what changed. |
| `stateKey` | string | (none) | Incremental mode only. Optional manual key identifying this tracked search. Left empty, one is derived automatically from mode, filters, and URLs. |
| `emitUnchanged` | boolean | `false` | Incremental mode only. Also save (and charge for) listings that did not change since the last run. |
| `emitExpired` | boolean | `false` | Incremental mode only. Also save (and charge for) a row for previously tracked listings no longer found, marked `changeType: "EXPIRED"`. Only fires after a run that scanned the full tracked search. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode only. Field names (dotted paths for nested fields) left out of change detection. They stay in every saved row. |

#### URL mode: supported URL shapes

URL mode with the `urls` field untouched scrapes these default example URLs (one per supported shape); replace them with your own. A cat.php `p=` page number is honoured as the start page.

| Shape | Example |
|---|---|
| City search path | `https://www.cian.ru/kupit-kvartiru/` |
| cat.php search, start page p=2 | `https://www.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat&region=1&p=2` |
| cat.php filtered and sorted rent search | `https://www.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=1&room1=1&minprice=50000&maxprice=100000&sort=creation_date_desc` |
| City subdomain search | `https://spb.cian.ru/kupit-kvartiru/` |
| House sale search | `https://www.cian.ru/kupit-dom/` |
| Agency page | `https://www.cian.ru/company/10127440/` |
| Agent page | `https://www.cian.ru/agents/107153484/` |

A bare path such as `/snyat-kvartiru/` on the main host is redirected by the site to a city chosen from the visitor's location, so use a city subdomain or a cat.php URL with `region=` to pin the city. Single-listing detail pages (`/sale/flat/<id>/`) are not supported: the run logs a clear warning for each and skips it.

In search mode, `location` takes a typed city name (Москва, Санкт-Петербург, Казань). Unknown names are resolved through the site's own city pages; if nothing matches, the run stops with an error telling you to fix the spelling or set Region ID (an unrecognised location now stops the run instead of silently using Moscow).

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "id": 123456789,
  "url": "https://www.cian.ru/sale/flat/123456789/",
  "sourceUrl": "https://www.cian.ru/sale/flat/123456789/",
  "title": "2-комн. кв., 54 м², 5/9 эт.",
  "jkName": null,
  "price": "12 500 000 ₽",
  "priceValue": 12500000,
  "pricePerMeter": 231481,
  "currency": "rur",
  "address": "Москва, Пресненский р-н, ул. Ленина, 10",
  "district": "Пресненский",
  "metro": "Баррикадная",
  "metroTime": 7,
  "metroLineId": 3,
  "metroLineColor": "00701A",
  "roomsCount": 2,
  "totalArea": 54,
  "livingArea": 32,
  "kitchenArea": 10,
  "floorNumber": 5,
  "floorsCount": 9,
  "buildYear": 2015,
  "materialType": "monolith",
  "dealType": "sale",
  "category": "flatSale",
  "offerType": "flat",
  "isFromDeveloper": false,
  "isPremium": false,
  "isApartments": false,
  "phoneNumbers": ["+79991234567"],
  "latitude": 55.7601,
  "longitude": 37.6103,
  "description": "Просторная квартира с ремонтом, рядом метро",
  "imageUrls": ["https://img.cian.site/a.jpg", "https://img.cian.site/b.jpg"],
  "mainImage": { "full": "https://img.cian.site/a.jpg" },
  "siteUrl": "https://www.cian.ru/sale/flat/123456789/",
  "formattedAddress": "Москва, Пресненский р-н, ул. Ленина, 10",
  "formattedFullPrice": "12 500 000 ₽",
  "ceilingHeight": 2.8,
  "agent": { "userId": 141493134, "accountType": "agency", "agencyName": "Компания PIONEER", "isAgent": true, "isBuilder": true },
  "geo": { "coordinates": { "lat": 55.7601, "lng": 37.6103 } },
  "creationDate": "2026-09-20T10:00:00+03:00",
  "addedLabel": "вчера, 14:40",
  "scrapedAt": "2026-09-28T08:00:00.000Z"
}
```

### Plan Requirement

A residential proxy is required. Datacenter connections were measured against this site and are answered with a captcha page ("Captcha - база объявлений ЦИАН") instead of listings, so the actor defaults to a Russian residential connection and cannot work on a datacenter group. Residential traffic is billed to your Apify plan, and Apify free plans do not include residential proxies. Single listing detail pages also served the captcha page on residential tests, so Fetch listing details can leave some rows with `detailStatus: "skipped"` (not charged).

What you will see in the log and run status:

- When the residential connection is unavailable, the log warns "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs." Pages served that way log "Served over the backup connection (the default connection was unavailable)." This warning and the backup connection apply only to the Apify proxy: with your own proxy URLs there is no backup, and a refused proxy ends the run with the "proxy connection was refused" message instead.
- If the account has no proxy access at all, the run stops with "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required".
- If residential is unavailable and the backup cannot load the pages, the run stops with "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Cian pages."
- If nothing loads for another reason, the run stops with "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."

You can supply your own proxy URLs under Proxy & connection.

### FAQ

#### How much does it cost?

Pay per event. The current rates are shown on the **Pricing** tab (paid Apify plans get lower tiered rates). The events and when each one is charged:

| Event | When it is charged |
| --- | --- |
| Actor start (`apify-actor-start`) | once per run, per GB of memory |
| Dataset item (`apify-default-dataset-item`) | once for each saved listing |
| Detail enrichment (`detail-enrichment`) | once per saved listing whose detail page was actually read (**Fetch listing details** on); skipped rows are not charged |

Unchanged or suppressed listings in incremental mode are not billed. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape CIAN?

This actor collects only publicly available real estate listings. You are responsible for how you use it: follow CIAN's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Contact phone numbers are published by listers and agents as part of the public listing; handle them under the privacy and telecom laws that apply to you.

#### Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then classifies every listing as new, updated, unchanged, reappeared, or expired against the previous run of the same search, and unchanged listings are not billed unless you turn that on too.

#### What is the difference between Resume from run and Incremental mode?

**Resume from run** continues ONE specific interrupted crawl: it skips listing ids already saved in a past run's dataset so that run can finish without duplicates. **Incremental mode** is for a recurring, scheduled search: it keeps its own state between separate runs and reports what changed each time. They can combine to bootstrap a monitoring baseline from an interrupted crawl's dataset, but not once that baseline already has tracked listings, in which case the run stops with a message asking you to remove Resume from run or set a different State key.

#### Why did my run fail instead of returning an empty dataset?

A run fails when it cannot read the site at all after several attempts, when none of the pasted URLs could be read, or when the search matched no listings whatsoever, since the actor treats a completely empty result as indistinguishable from a blocked run and stops with a clear message rather than guessing. Run it again, try broader filters, or try a different region. The one case where a successful run can still save nothing is Incremental mode finding every previously tracked listing unchanged.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear, Airtable, or Apify.

### 🔗 Want more real estate data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🏠 <a href="https://apify.com/abotapi/domclick-scraper"><b>Domclick RU Property Scraper</b></a><br>Extract property listings from domclick.ru, one of Russia’s largest real estate portals...</td><td>🏷️ <a href="https://apify.com/abotapi/avito-ru-scraper"><b>Avito.ru Scraper</b></a><br>From $1/1K. Scrape structured listings from Avito.ru by region, category, filters, or...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/seloger-france-scraper"><b>SeLoger Scraper</b></a><br>Scrape SeLoger.com properties for sale and rent. Search by location with price, room and...</td><td>🏠 <a href="https://apify.com/abotapi/otodom-pl-scraper"><b>Otodom.pl Scraper</b></a><br>Scrape Otodom.pl properties for sale and rent, including apartments, houses, plots...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/iproperty-com-my-scraper"><b>iProperty MY Scraper</b></a><br>Scrape property listings from iProperty.com.my for sale or rent: price, PSF, bedrooms...</td><td>🏠 <a href="https://apify.com/abotapi/reiwa-com-au-scraper"><b>REIWA Scraper</b></a><br>Scrape REIWA.com.au across sale, rental, sold, commercial, business and rural properties...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/cian-ru-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

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

Choose search filters or direct listing/search URLs.

## `urls` (type: `array`):

Cian listing URLs or search-result URLs. Used only in URL mode. Encode any filters directly in the URL, because the search filters below are ignored in URL mode.

## `location` (type: `string`):

Search mode only. Type a city name (Москва, Санкт-Петербург, Казань). It is resolved through the site's own city pages; the run stops with a clear error when no city matches.

## `regionId` (type: `integer`):

Search mode only. Optional Cian region ID. Moscow is 1, Saint Petersburg is 2. Leave empty to resolve from Location when possible.

## `operationType` (type: `string`):

Search mode only. Deal type for search mode.

## `category` (type: `string`):

Search mode only. Listing category. Choose Any to let operation and property type decide.

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

Search mode only. Sort results when supported by the selected source.

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

Search mode only. Room counts for flats and rooms.

## `includeStudio` (type: `boolean`):

Search mode only. Include studio listings together with selected room counts.

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

Search mode only. Minimum price in rubles.

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

Search mode only. Maximum price in rubles.

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

Search mode only. Minimum total area in square meters.

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

Search mode only. Maximum total area in square meters.

## `minFloor` (type: `integer`):

Search mode only. Minimum floor.

## `maxFloor` (type: `integer`):

Search mode only. Maximum floor.

## `minFloors` (type: `integer`):

Search mode only. Minimum floors in the building.

## `maxFloors` (type: `integer`):

Search mode only. Maximum floors in the building.

## `minLivingArea` (type: `integer`):

Search mode only. Minimum living area in m2.

## `maxLivingArea` (type: `integer`):

Search mode only. Maximum living area in m2.

## `minHouseYear` (type: `integer`):

Search mode only. Earliest building year.

## `maxHouseYear` (type: `integer`):

Search mode only. Latest building year.

## `minCeilingHeight` (type: `number`):

Search mode only. Minimum ceiling height in metres.

## `maxCeilingHeight` (type: `number`):

Search mode only. Maximum ceiling height in metres.

## `isByHomeowner` (type: `boolean`):

Search mode only. Only listings placed by the owner.

## `fromDeveloper` (type: `boolean`):

Search mode only. Only listings placed by the developer.

## `isFirstFloor` (type: `boolean`):

Search mode only. Only first-floor listings.

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

Search mode only. Exclude top-floor listings.

## `hasVideo` (type: `boolean`):

Search mode only. Only listings with a video.

## `withLayout` (type: `boolean`):

Search mode only. Only listings with a layout drawing.

## `shortTermRent` (type: `boolean`):

Search mode only. With operation Rent, only daily-rental listings.

## `repair` (type: `array`):

Search mode only. Cian renovation codes (1 none, 2 cosmetic, 3 euro, 4 designer).

## `publishPeriod` (type: `string`):

Search mode only. Only listings published in this window.

## `advancedFilters` (type: `object`):

Search mode only. Raw Cian query objects merged into the search, e.g. {"repair":{"type":"terms","value":\[2,3]}}. For power users who know Cian's query field names.

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

Maximum matching rows to save. Fewer rows can be returned when the selected source and filters match fewer live records.

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

No page limit when set to 0. The run stops at Max items.

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

Load each saved listing's own detail page for richer fields not on the search card: agent/agency name, total view count, BTI-verified build year, renovation type, window view, balcony count, bathroom counts, parking type, and amenities. Billed as a detail-enrichment surcharge.

## `proxy` (type: `object`):

Proxy configuration. The default works on every plan. Switch groups if you start seeing access checks.

## `resumeFromRunId` (type: `string`):

Continue ONE interrupted crawl: paste a previous run ID (or dataset ID) and this run skips listings it already saved, appending only new ones. For recurring monitoring of the SAME search across scheduled runs instead, use Incremental mode below.

## `incrementalMode` (type: `boolean`):

Remember this search's results between scheduled runs and report only what changed (NEW / UPDATED / REAPPEARED / EXPIRED) instead of re-saving everything every time. Distinct from Resume from run above, which continues one specific interrupted crawl rather than tracking a recurring search.

## `stateKey` (type: `string`):

Incremental mode only. Optional manual key identifying this tracked search. Leave empty to derive one automatically from mode/filters/URLs, so identical searches share a baseline and different ones never mix.

## `emitUnchanged` (type: `boolean`):

Incremental mode only. Also save and CHARGE for listings that did not change since the last run. Off by default so recurring runs only pay for what actually changed.

## `emitExpired` (type: `boolean`):

Incremental mode only. Also save and CHARGE a row for previously-tracked listings no longer found, marked changeType EXPIRED. Only fires after a run that scanned the full tracked search with no cap, resume, or unreadable URL truncating it early.

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode only. Field names that must NOT count as a change, e.g. imageUrls or description (dotted paths such as a.b reach nested fields). The fields stay in every saved row; they are only left out of the NEW/UPDATED comparison, so a change in them alone never produces an UPDATED row. scrapedAt and addedLabel are always ignored. Price, area, address and the other listing fields are compared unless listed here.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON. The complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Maximum saved records to export to selected MCP connectors.

## Actor input object example

```json
{
  "mode": "search",
  "urls": [
    "https://www.cian.ru/kupit-kvartiru/",
    "https://www.cian.ru/snyat-kvartiru/",
    "https://www.cian.ru/kupit-kvartiru/?p=2",
    "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?sort=price_object_order",
    "https://www.cian.ru/snyat-kvartiru-1-komn-ili-2-komn/",
    "https://www.cian.ru/snyat-ofis/",
    "https://www.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat&region=1&p=2",
    "https://www.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=1&room1=1&minprice=50000&maxprice=100000&sort=creation_date_desc",
    "https://spb.cian.ru/kupit-kvartiru/",
    "https://www.cian.ru/kupit-dom/",
    "https://www.cian.ru/company/10127440/",
    "https://www.cian.ru/agents/107153484/",
    "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?p=2",
    "https://www.cian.ru/snyat-komnatu/",
    "https://www.cian.ru/kupit-pomeshenie/",
    "https://www.cian.ru/novostrojki/",
    "https://spb.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=2&sort=creation_date_desc&minprice=30000&maxprice=60000"
  ],
  "location": "Москва",
  "operationType": "sale",
  "category": "",
  "sort": "default",
  "includeStudio": false,
  "isByHomeowner": false,
  "fromDeveloper": false,
  "isFirstFloor": false,
  "notLastFloor": false,
  "hasVideo": false,
  "withLayout": false,
  "shortTermRent": false,
  "publishPeriod": "",
  "maxItems": 20,
  "maxPages": 0,
  "fetchDetails": false,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `results` (type: `string`):

No description

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

No description

## `detail` (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 = {
    "mode": "search",
    "urls": [
        "https://www.cian.ru/kupit-kvartiru/",
        "https://www.cian.ru/snyat-kvartiru/",
        "https://www.cian.ru/kupit-kvartiru/?p=2",
        "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?sort=price_object_order",
        "https://www.cian.ru/snyat-kvartiru-1-komn-ili-2-komn/",
        "https://www.cian.ru/snyat-ofis/",
        "https://www.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat&region=1&p=2",
        "https://www.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=1&room1=1&minprice=50000&maxprice=100000&sort=creation_date_desc",
        "https://spb.cian.ru/kupit-kvartiru/",
        "https://www.cian.ru/kupit-dom/",
        "https://www.cian.ru/company/10127440/",
        "https://www.cian.ru/agents/107153484/",
        "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?p=2",
        "https://www.cian.ru/snyat-komnatu/",
        "https://www.cian.ru/kupit-pomeshenie/",
        "https://www.cian.ru/novostrojki/",
        "https://spb.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=2&sort=creation_date_desc&minprice=30000&maxprice=60000"
    ],
    "location": "Москва",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/cian-ru-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "urls": [
        "https://www.cian.ru/kupit-kvartiru/",
        "https://www.cian.ru/snyat-kvartiru/",
        "https://www.cian.ru/kupit-kvartiru/?p=2",
        "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?sort=price_object_order",
        "https://www.cian.ru/snyat-kvartiru-1-komn-ili-2-komn/",
        "https://www.cian.ru/snyat-ofis/",
        "https://www.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat&region=1&p=2",
        "https://www.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=1&room1=1&minprice=50000&maxprice=100000&sort=creation_date_desc",
        "https://spb.cian.ru/kupit-kvartiru/",
        "https://www.cian.ru/kupit-dom/",
        "https://www.cian.ru/company/10127440/",
        "https://www.cian.ru/agents/107153484/",
        "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?p=2",
        "https://www.cian.ru/snyat-komnatu/",
        "https://www.cian.ru/kupit-pomeshenie/",
        "https://www.cian.ru/novostrojki/",
        "https://spb.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=2&sort=creation_date_desc&minprice=30000&maxprice=60000",
    ],
    "location": "Москва",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/cian-ru-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "urls": [
    "https://www.cian.ru/kupit-kvartiru/",
    "https://www.cian.ru/snyat-kvartiru/",
    "https://www.cian.ru/kupit-kvartiru/?p=2",
    "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?sort=price_object_order",
    "https://www.cian.ru/snyat-kvartiru-1-komn-ili-2-komn/",
    "https://www.cian.ru/snyat-ofis/",
    "https://www.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat&region=1&p=2",
    "https://www.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=1&room1=1&minprice=50000&maxprice=100000&sort=creation_date_desc",
    "https://spb.cian.ru/kupit-kvartiru/",
    "https://www.cian.ru/kupit-dom/",
    "https://www.cian.ru/company/10127440/",
    "https://www.cian.ru/agents/107153484/",
    "https://www.cian.ru/kupit-kvartiru-1-komn-ili-2-komn/?p=2",
    "https://www.cian.ru/snyat-komnatu/",
    "https://www.cian.ru/kupit-pomeshenie/",
    "https://www.cian.ru/novostrojki/",
    "https://spb.cian.ru/cat.php?deal_type=rent&engine_version=2&offer_type=flat&region=2&sort=creation_date_desc&minprice=30000&maxprice=60000"
  ],
  "location": "Москва",
  "maxItems": 20
}' |
apify call abotapi/cian-ru-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/cian-ru-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DQEeQF3wQDDDOOvlD/builds/5GzZe8V1lunERqBj2/openapi.json
