# Avito.ru Scraper - Classifieds, Prices, Sellers & Contacts (`abotapi/avito-ru-scraper`) Actor

Scrape Avito.ru classifieds across real estate, cars, jobs, services and more. Extract 42 fields including prices, addresses, GPS, photos, descriptions and seller details. Supports optional phone reveal, keyword and URL search, incremental tracking, resume and API export.

- **URL**: https://apify.com/abotapi/avito-ru-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Real estate, Developer tools
- **Features:** Limited permissions
- **Stats:** 447 total users, 55 monthly users, 97.9% runs succeeded, 3 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 1,000 results

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

## Avito.ru Scraper: Listings, Prices, Photos & Seller Details

Avito.ru Scraper turns Avito, Russia's largest classifieds portal, into structured data. Pull up to 42 fields per listing, including price, full address, GPS coordinates, metro station, photo gallery, posting date, seller type and verification badges, across apartments, houses, cars, jobs, services, electronics and every other category. Build a search from region and category filters, or paste Avito URLs directly, then export to JSON, CSV or Excel, or read the results through the API.

### Why This Scraper?

- **Up to 42 fields per listing**: price, full address, metro station and walking distance, photo gallery, posting date, seller type and verification badges.
- **Two ways to find listings.** Build a search from region, category and filters, or paste Avito URLs and the actor walks pagination forward from wherever the URL starts.
- **Every category on Avito.** Apartments, houses, rooms, garages, commercial property, land, cars, motorcycles, trucks, boats, auto parts, jobs, services, resumes, electronics, home and garden, hobbies, animals, clothing and more.
- **Rich results with no extra fetch.** The default lean mode returns the search-results card fields: title, price, full description, photo gallery, address, metro and seller badges, with no detail-page visit.
- **Optional detail-page enrichment.** Turn on `fetchDetails` for the full attribute table, GPS coordinates, seller stats, view counts, a price-change signal and the category breadcrumb path.
- **Optional seller phone reveal.** Turn on `fetchPhones` to also reveal each pushed listing's seller phone number, the same phone panel a visitor opens.
- **Built for schedules.** Incremental mode returns only new and changed listings on recurring runs, and `resumeFromRunId` continues one interrupted run without re-collecting or re-billing what it already has.

### Use Cases

- **Real estate market research:** track apartment and house prices, availability and days-on-market across regions.
- **Car marketplace analysis:** monitor used-car listings, pricing and model availability by region.
- **Job market research:** collect vacancy and resume postings across categories and regions.
- **Classifieds aggregation and price comparison:** mirror or compare listings across categories for a resale or comparison tool.
- **Lead generation:** turn on Incremental mode to catch new or price-changed listings on every scheduled run.

### Data You Get

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

| Field | Example |
| --- | --- |
| `id` / `url` | `"0000000000"` / `"https://www.avito.ru/moskva/kvartiry/listing-title-slug_0000000000"` |
| `title` | `"Sample listing title in Russian"` |
| `price` / `priceText` / `currency` | `12345678` / `"12 345 678 ₽"` / `"RUB"` |
| `category` / `subcategory` / `region` / `city` | `"kvartiry"` / `"prodam"` / `"moskva"` / `"moskva"` |
| `address` / `street` | `"Sample building, Sample street 4"` / `"Sample street"` |
| `metro` / `metroDistanceMin` | `"Sample metro station"` / `10` |
| `description` | full listing description text, returned by default |
| `photoUrls` / `photoCount` | array of photo URLs / `5` (card rows carry the search-page thumbnails; with detail pages on, `photoUrls` is the full image gallery from the listing page — video slides are skipped — and `photoCount` is its length) |
| `badges` / `isVerified` | `["Sample badge text"]` / `true` |
| `sellerName` / `sellerType` | `"Sample Agent"` / `"agency"` |
| `sellerRating` / `sellerReviewsCount` | `null` / `null` (Avito's listing page does not carry the seller's rating; these stay empty unless the page supplies it) |
| `sellerSince` | `"февраля 2011"` (when enabled; empty for private sellers, who hide it) |
| `sellerPhone` / `sellerPhoneType` / `sellerPhoneNote` | `"+79012345678"` / `"Временный номер"` / the site's own note (when `fetchPhones` is on; the panel exposes mobile numbers only, so other number shapes stay empty; company-shop listings need a login at the source and stay empty; most professional listings carry a rotating temporary number, so the note is shipped verbatim) |
| `viewsCount` | `0` (when enabled) |
| `attributes` | key/value attribute table, for example rooms or floor (when enabled) |
| `lat` / `lng` / `priceIncreased` | `55.75201` / `37.54841` / `false` (when enabled) |
| `categoryPath` | `["Главная", "Недвижимость", "Квартиры", "Купить"]` (when enabled) |
| `postedDate` / `postedAt` | `"1 января"` / `"2026-10-10T22:44:00+03:00"` (`postedAt` when enabled; the localized posting stamp read as Moscow time, empty when it cannot be read) |
| `priceHistoryCount` / `priceWasLowered` | `3` / `false` (when enabled) |
| `pricePrevious` / `normalizedPrice` | `""` / `"368 056 ₽ за м²"` (when enabled; previous price is empty unless the seller lowered it) |
| `categoryId` / `locationId` / `hasVideo` / `videoUrl` | `24` / `637640` / `false` / `""` (when enabled; the ids are Avito's own) |
| `geoReferences` | `[{"name": "Sample station", "distance": "400 м", "walkTime": "6-10 мин."}]` (nearby stations with distance and walking time, when enabled) |
| `isDeliveryAvailable` / `layoutImageUrls` | `false` / array of floor-plan image URLs (when enabled; the array is empty when the listing has none) |
| `marketValuation` | `{"estimated": 5300000, "lowest": 4808100, "highest": 5531900, "verdict": "good"}` (Avito's own price estimate, when enabled and shown for the listing) |
| `sellerKey` / `sellerUrl` | `"4d07885f1fffd48ca6a8dc0e159bec5c"` / `"https://www.avito.ru/brands/sample-agency"` (agency or developer profile; empty for private sellers) |

The lean default already returns most of the fields above. Turn on `fetchDetails` to add `attributes`, `lat`, `lng`, `sellerRating`, `sellerReviewsCount`, `sellerSince`, `viewsCount`, `priceIncreased`, `categoryPath`, `postedAt`, `priceHistoryCount`, `geoReferences` and the other detail fields in the table above. Text fields (`priceText`, `postedDate`, `sellerSince`, `categoryPath`, `title`, `description`) are returned in Russian as shown on Avito.

### How to Use

1. Pick a **mode**: `search` (build a query from region, category and filters) or `url` (paste Avito links directly).
2. For search mode, set the **region** and **category**, then narrow with price, deal type, sort order or a free-text query.
3. Set **Max listings** (and optionally **Max pages**) to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Apartments for sale in Moscow, price capped:**

```json
{
  "mode": "search",
  "regions": ["moskva"],
  "category": "kvartiry",
  "dealType": "prodam",
  "minPrice": 1000000,
  "maxPrice": 9000000,
  "sortBy": "price_asc",
  "maxListings": 250,
  "proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

**Cars anywhere in Russia, free-text search:**

```json
{
  "mode": "search",
  "regions": ["rossiya"],
  "category": "avtomobili",
  "query": "tesla model 3",
  "sortBy": "date_desc",
  "maxListings": 150,
  "proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

**Rentals in two cities, private sellers only, full detail:**

```json
{
  "mode": "search",
  "regions": ["moskva", "sankt-peterburg"],
  "category": "kvartiry",
  "dealType": "sdam",
  "ownerOnly": true,
  "maxPrice": 80000,
  "fetchDetails": true,
  "maxListings": 200,
  "proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/avito-ru-scraper").call(run_input={
    "mode": "search",
    "regions": ["moskva"],
    "category": "kvartiry",
    "proxy": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"]},
})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(listing["title"], listing["price"], listing["url"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/avito-ru-scraper').call({
  mode: 'search',
  regions: ['moskva'],
  category: 'kvartiry',
  proxy: { useApifyProxy: true, apifyProxyGroups: ['RESIDENTIAL'] },
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

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

#### Direct URLs and forward paging

Paste one or more Avito search or category URLs in `urls` (URL mode). Pagination starts at whatever page the URL points to and walks forward, so a link to page 5 continues from page 5 onward. Filter fields are ignored in this mode.

Leave `urls` untouched and a URL-mode run scrapes one example per URL shape below (the field's default; this is a change from earlier versions, where an empty list stopped the run). Only search and category URLs are scraped; single-listing, seller-profile and non-avito URLs are skipped with a warning in the log, and a run with no usable URL stops with an error instead of finishing empty. `m.avito.ru` links are converted to `www.avito.ru`.

| URL shape | Example | Behaviour |
|---|---|---|
| Category + deal type | `https://www.avito.ru/moskva/kvartiry/prodam` | Walks every result page |
| Paginated listing | `https://www.avito.ru/moskva/kvartiry/prodam?p=2` | Starts at page 2 and walks forward |
| Free-text search | `https://www.avito.ru/moskva?q=iphone` | Walks every result page |
| Single listing `/<city>/<category>/<title>_<id>` | | Skipped with a warning |
| Seller profile `/user/<id>/profile` | | Skipped with a warning |

In filter mode, `regions` accepts plain city names (for example `Москва` or `Moscow`) for common cities as well as Avito slugs such as `moskva`; an unknown name stops the run with an error.

#### Resume and recurring updates

Two different things share the same input section:

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID, and this run skips every listing that run already collected, so you do not pay twice.
- **Incremental mode** (`incrementalMode`) is for running the same search or URL set again and again, for example daily. Each listing is classified `NEW`, `UPDATED` (with `changedFields`), `REAPPEARED`, `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), or `EXPIRED` (only after a run that scanned every tracked region or URL to a confirmed end of results, and only with `emitExpired` on). `stateKey` names or shares the stored state; left empty, the actor derives one automatically from the mode, regions or URLs, category and filters, so different searches never mix state. A listing is `UPDATED` when a real listing field changes (price, title, description, address, seller, photo count, attributes and similar). These never count as changes, though they are still returned: `photoUrls` (avito serves the same photos from rotating image-server addresses; added or removed photos still show up through `photoCount` on card rows and after the one-time gallery migration described below), the live counters `viewsCount`, `todayViews` and `sellerReviewsCount`, the relative posting dates `postedDate` and `postedDateFull`, `postedAt` (the site renders the stamp in the connection's local timezone, so a run through an exit in another timezone would otherwise re-read every listing as updated; the posting time itself never changes for an existing listing), `layoutImageUrls` (floor-plan images, served from the same rotating image-server addresses as the photos) and `marketValuation` (the site's own price estimate, which the site recalculates on its own; it is not a change the owner made). With detail pages on, a listing whose detail fetch was refused this run is compared against its baseline without the detail-only fields (attributes, coordinates, category path and the like), so a refused page can never re-read an unchanged listing as updated, and the stored detail data is carried forward; a listing tracked before its first successful detail read converges to the richer shape once, without billing. The description is compared ignoring the Latin/Cyrillic look-alike letter swaps the site applies to it each time it re-scrambles the description (the text you receive is returned exactly as the site served it), so a description only counts as changed when its wording really changes. List any other fields you don't want treated as changes in `ignoreFieldsForChanges`; dotted paths such as `attributes.floor` ignore a nested field. Ignored fields are still returned in the output.

### 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` (filters) or `url` (direct URLs). |
| `regions` | array | `["moskva"]` | Region slugs, search mode only. Use `rossiya` for all of Russia. |
| `category` | string | `kvartiry` | Top-level category slug (apartments, cars, jobs, services, and more). |
| `dealType` | string | `prodam` | `any`, `prodam` (sale) or `sdam` (rent). Property categories only. |
| `query` | string | (none) | Free-text query, matches title and description. |
| `minPrice` | integer | (none) | Minimum price in rubles. |
| `maxPrice` | integer | (none) | Maximum price in rubles. |
| `sortBy` | string | `default` | `default`, `date_desc`, `price_asc` or `price_desc`. |
| `ownerOnly` | boolean | `false` | Restrict to private (non-agency) sellers. |
| `urls` | array | sample | Avito search or category URLs, URL mode only. |
| `maxPages` | integer | (none) | Optional cap on result pages walked per region or URL. Leave empty to walk every page. |
| `maxListings` | integer | `20` | Hard cap on total listings written to the dataset (`0` = unlimited; maximum `1000000`). |
| `fetchDetails` | boolean | `false` | Visit each listing's detail page for the full attribute table, GPS, seller stats and more. |
| `fetchPhones` | boolean | `false` | Reveal each pushed listing's seller phone (mobile numbers; the source's phone panel does not carry other number shapes). Off by default; delivered numbers bill the detail-enrichment event in blocks of ten (see Pricing). |
| `resumeFromRunId` | string | (none) | Continue one interrupted run or dataset without re-collecting its listings. |
| `incrementalMode` | boolean | `false` | Return only new and changed listings on recurring runs. |
| `stateKey` | string | (none) | Name or share an incremental-mode state. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) unchanged listings. |
| `emitExpired` | boolean | `false` | Also return (and bill) expired listings. |
| `ignoreFieldsForChanges` | string\[] | `[]` | Extra output fields to ignore when deciding whether a listing is `UPDATED`; dotted paths like `attributes.floor` reach nested fields (`photoUrls`, `viewsCount`, `todayViews`, `sellerReviewsCount`, `postedDate`, `postedDateFull`, `postedAt`, `layoutImageUrls` and `marketValuation` are always ignored). |
| `proxy` | object | (none; prefilled with Apify Proxy, Residential) | Connection settings. Include it when calling from the API. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each listing to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which records are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Output Example

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

```json
{
  "id": "0000000000",
  "url": "https://www.avito.ru/moskva/kvartiry/listing-title-slug_0000000000",
  "title": "Sample listing title in Russian",
  "price": 12345678,
  "currency": "RUB",
  "priceText": "12 345 678 ₽",
  "category": "kvartiry",
  "subcategory": "prodam",
  "region": "moskva",
  "city": "moskva",
  "address": "Sample building, Sample street 4",
  "street": "Sample street",
  "metro": "Sample metro station",
  "metroDistanceMin": 10,
  "postedDate": "1 января",
  "description": "Full listing description text.",
  "photoUrls": ["https://img.avito.st/sample/1.jpg"],
  "photoCount": 1,
  "badges": ["Sample badge text"],
  "isVerified": true,
  "sellerName": "Sample Agent",
  "sellerType": "agency",
  "sellerRating": null,
  "sellerReviewsCount": null,
  "sellerSince": "февраля 2011",
  "viewsCount": 0,
  "attributes": { "Sample attribute key": "Sample value" },
  "lat": 55.75201,
  "lng": 37.54841,
  "priceIncreased": false,
  "categoryPath": ["Главная", "Недвижимость", "Квартиры", "Купить"],
  "postedAt": "2026-10-10T22:44:00+03:00",
  "priceHistoryCount": 3,
  "priceWasLowered": false,
  "pricePrevious": "",
  "normalizedPrice": "368 056 ₽ за м²",
  "categoryId": 24,
  "locationId": 637640,
  "hasVideo": false,
  "videoUrl": "",
  "geoReferences": [{ "name": "Sample station", "distance": "400 м", "walkTime": "6-10 мин." }],
  "isDeliveryAvailable": false,
  "layoutImageUrls": [],
  "marketValuation": { "estimated": 5300000, "lowest": 4808100, "highest": 5531900, "verdict": "good" },
  "sellerKey": "4d07885f1fffd48ca6a8dc0e159bec5c",
  "sellerUrl": "https://www.avito.ru/brands/sample-agency"
}
```

#### Dataset views

The dataset has four views in the Console: **Listings Overview** (core card fields), **Photos**, **Listing Detail** (attributes, GPS, seller stats, enabled by `fetchDetails`; the seller phone fields land here when `fetchPhones` is on) and **Changes** (incremental mode: change status and `changedFields`).

### Plan Requirement

Avito's access protection rejects most automated traffic with an "access restricted" page (HTTP 429), including plain requests from unknown IPs and many datacenter exits. Datacenter proxies can work (a small test run returned every listing it asked for) but are slower and less reliable, with more session refreshes and retries; runs without a proxy are refused. Use the prefilled proxy settings (Apify Proxy, Residential group): the actor prepares a browsing session before fetching pages, and residential is the recommended setting, but it is not a guarantee, because Avito can still refuse individual exits. Reliability varies by run; the actor rotates exits and retries, and the run fails with a clear message rather than returning an empty result when nothing gets through.

What you may see in the run log and status message:

- *"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."* Your plan does not include the selected proxy. The backup connection is used instead and may be refused too. When it serves data the log adds "Served over the backup connection (the default connection was unavailable)."
- *"The proxy connection keeps failing - switching to a backup connection for the rest of this run."* Repeated connection errors on your proxy settings.
- *"The site is rate-limiting this connection class (sustained HTTP 429 across fresh exits) ... Please retry later."* The run failed, nothing is billed. Retry later or with a different proxy country.
- *"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 ..."* The run failed, nothing is billed. If the backup connection was reachable but loaded no page, the message starts "No results: residential proxies are unavailable on this run ..." instead.
- *"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."* The run failed, nothing is billed.
- *"No listings found for the given input. Try different filters."* The search genuinely matched nothing.

### FAQ

#### How much does it cost?

You pay per listing returned, plus a per-run start charge, and a separate charge for each listing enriched when `fetchDetails` is on (one extra page per listing). With `fetchPhones` on, delivered phone numbers bill the same detail-enrichment event in blocks of ten: the first ten numbers delivered in a run add one event, the next ten add one more, and so on. Numbers that could not be revealed (the source requires a login for company shops, or the exit's reveal limit was hit) are never counted. Unchanged listings are suppressed and not billed unless `emitUnchanged` is on; expired listings are billed only with `emitExpired` on. The **Pricing** tab shows the current rates for your plan tier. Use **Max listings** to cap the cost of any run.

#### Is it legal to scrape Avito?

This actor collects only publicly available listing data. You are responsible for how you use it: follow Avito's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts like price and address are generally factual data, but photos may be subject to third-party rights.

#### 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 returns only new, updated and reappeared listings, and unchanged ones are not billed unless you turn on **Emit unchanged**.

#### Why does `dealType` have no effect on some categories?

`dealType` only applies to property categories: apartments, houses, rooms, garages, commercial property and land. It is ignored for cars, jobs, electronics and every other category.

#### Why did my run finish with no listings?

If the filters match nothing, the run finishes with an empty dataset and a status message, and nothing is billed. If no connection could reach Avito at all, the run fails with a message that says so instead of reporting an empty search, and nothing is billed. If your Apify plan does not include proxy access, the run continues on a backup connection, and the log says so; if the backup connection can't get through either, a paid Apify plan with proxy access is required.

#### 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 or Airtable.

### 🔗 Want more classifieds data?

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

<table>
<tr><td>🏷️ <a href="https://apify.com/abotapi/mudah-my-scraper"><b>Mudah.my Cars, Property, Jobs &amp; Marketplace Scraper</b></a><br>Scrape Mudah.my listings across every category: cars, motorcycles, property, mobiles...</td><td>🚗 <a href="https://apify.com/abotapi/willhaben-at-scraper"><b>Willhaben.at Scraper</b></a><br>From $1/1K. Scrape Willhaben.at listings into clean JSON with 40+ structured fields...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/subito-it-scraper"><b>Subito.it Scraper</b></a><br>Scrape Subito.it listings across cars, real estate, marketplace, jobs, and more. Search...</td><td>🏷️ <a href="https://apify.com/abotapi/gumtree-uk-scraper"><b>Gumtree.com Scraper</b></a><br>Scrape Gumtree.com classifieds across motors, property, jobs, services, pets and goods...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/wildberries-marketplace-scraper"><b>Wildberries Scraper</b></a><br>Scrape Wildberries marketplace: product search with prices (wallet vs retail), discounts...</td><td>🚗 <a href="https://apify.com/abotapi/craigslist-classifieds-scraper"><b>Craigslist Scraper</b></a><br>Scrape Craigslist postings in any of 700+ cities worldwide: price, title, posting text...</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/avito-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`):

Pick how you want to find listings. 'Search by filters' resolves a region + category + filters into a search URL automatically. 'Direct URLs' takes one or more avito.ru URLs you have already copy-pasted from your browser.

## `regions` (type: `array`):

Region slugs (Search mode only). Examples: 'moskva', 'sankt-peterburg', 'rossiya' (all of Russia). Multiple regions are scraped sequentially. Default: moskva.

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

Top-level category. Pick the kind of listings you want.

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

Sale or Rent. Only applies to property categories (apartments, houses, rooms, garages, commercial, land). Ignored for other categories. Avito only exposes two top-level deal types per category; the slugs are 'prodam' (sale) and 'sdam' (rent, long-term).

## `query` (type: `string`):

Optional text query (matches titles and descriptions). E.g. 'tesla', 'iPhone 15', 'студия у метро'.

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

Minimum price in rubles. Leave empty for no minimum.

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

Maximum price in rubles. Leave empty for no maximum.

## `sortBy` (type: `string`):

How to order results.

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

If true, exclude agency / professional sellers, return only private (С/Собственник) postings.

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

Avito.ru search/category URLs to scrape (URL mode only). Multi-URL supported; left untouched, the field scrapes one example per URL shape (category listing, paginated listing, free-text search). Single-listing, seller-profile and non-avito URLs are skipped with a warning; m.avito.ru links are accepted. Filter-mode fields are ignored. Pagination starts at the page in the URL and walks forward.

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

Optional bound on result pages walked per region/URL. Avito returns ~50-60 listings per page. Leave empty to walk every result page (the run size is controlled by Max listings, which this field defers to).

## `maxListings` (type: `integer`):

Hard global cap on total listings written to the dataset across ALL searches (every region in search mode, every URL in URL mode). The actor stops as soon as this number is reached. Set 0 for unlimited (subject to maxPages); values above 1,000,000 are not accepted.

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

Lean mode is the default (false): the SERP card alone already returns 27 of 42 fields — full description, address, metro, photos, badges, rooms, area, floor — and runs ~8x faster and far cheaper. Enable (true) to additionally fetch each listing's detail page for the 21-key attributes dict (floor, ceilings, balcony type, parking, etc.), full photo gallery, view counts, seller stats, GPS coordinates, price-change signal, and category breadcrumb path — the remaining 15 fields, for 42 total. Enrichment fetches one extra page per listing, so it is much slower and more expensive on high-volume scrapes.

## `fetchPhones` (type: `boolean`):

Off by default. Turn on to also try to reveal each pushed listing's seller phone number. Works by loading the same phone panel a visitor would open, so roughly every second exit IP serves about two numbers before that exit's per-IP limit, and the actor rotates exits on its own. Private sellers and agency/developer listings carry a rotating temporary number (the kind Avito shows logged-out visitors, disclosed per row in the phone note); numbers for company shops require a login at the source and return empty. The source's phone panel exposes mobile numbers only, so other number shapes return empty. Delivered numbers bill the Detail page enrichment event in blocks of ten delivered (see the Pricing tab).

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

Default: Apify Proxy with the RESIDENTIAL pool — the most reliable option for this site, which refuses many datacenter and unknown source IPs. When RESIDENTIAL is on and no country is pinned, the actor rotates the exit country per session across a Russia + EU pool for the best success rate. To pin a single country, set Country in this section. Datacenter groups work but warn at start and are slower and less reliable (more session refreshes); runs without a proxy are refused by the site.

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

Optional. ID of a previous run of this actor (or a dataset ID). Listings already in that dataset are skipped, so this run returns only NEW listings (a delta). Combine both runs' datasets for the full set. Max listings then counts only the new listings. For recurring monitoring of the same search, use Incremental mode below instead.

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

Turn this on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. A listing counts as UPDATED when a real listing field changes (price, title, description, address, seller, photo count, attributes and similar); the view counters (viewsCount, todayViews), sellerReviewsCount, the relative posting dates (postedDate, postedDateFull), photoUrls, layoutImageUrls (floor-plan images on the same rotating image servers) and marketValuation (the site recalculates its own price estimate) never count as changes, though they are still returned. Add more in "Ignore fields when detecting changes" below (nested paths such as attributes.floor work too). Turn on "Emit unchanged" or "Emit expired" only when you also want those listings returned (and billed). State is kept separately for each mode/region/category/filter setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

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

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the mode, regions/URLs, category, and filter settings -- different searches then never mix state with each other.

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

Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns -- and bills -- extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

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

Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned every tracked region/URL to a confirmed end of results -- not when Max listings capped it or when Resume was used. This returns -- and bills -- extra synthetic rows, so leave it off unless you need expiry tracking.

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

Output field names that should NOT make a listing count as UPDATED. Always ignored: photoUrls (avito serves the same photos from rotating image-server addresses; photoCount still catches added or removed photos), viewsCount, todayViews, sellerReviewsCount, postedDate, postedDateFull, layoutImageUrls and marketValuation (live counters, relative date text, rotating image-server addresses and the site's recalculated price estimate; postedAt holds the stable timestamp). Add fields such as badges or description here if changes to them are not relevant to you. Use a dotted path (for example attributes.floor) to ignore a field inside a nested object or list. Ignored fields are still returned in the output.

## `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`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "regions": [
    "moskva"
  ],
  "category": "kvartiry",
  "dealType": "prodam",
  "sortBy": "default",
  "ownerOnly": false,
  "urls": [
    "https://www.avito.ru/moskva/kvartiry/prodam",
    "https://www.avito.ru/moskva/kvartiry/prodam?p=2",
    "https://www.avito.ru/moskva?q=iphone"
  ],
  "maxListings": 20,
  "fetchDetails": false,
  "fetchPhones": false,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

No description

## `photos` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (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",
    "regions": [
        "moskva"
    ],
    "urls": [
        "https://www.avito.ru/moskva/kvartiry/prodam",
        "https://www.avito.ru/moskva/kvartiry/prodam?p=2",
        "https://www.avito.ru/moskva?q=iphone"
    ],
    "fetchDetails": false,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/avito-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",
    "regions": ["moskva"],
    "urls": [
        "https://www.avito.ru/moskva/kvartiry/prodam",
        "https://www.avito.ru/moskva/kvartiry/prodam?p=2",
        "https://www.avito.ru/moskva?q=iphone",
    ],
    "fetchDetails": False,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/avito-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",
  "regions": [
    "moskva"
  ],
  "urls": [
    "https://www.avito.ru/moskva/kvartiry/prodam",
    "https://www.avito.ru/moskva/kvartiry/prodam?p=2",
    "https://www.avito.ru/moskva?q=iphone"
  ],
  "fetchDetails": false,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}' |
apify call abotapi/avito-ru-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/avito-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/km2oo0mCahDBKPOa6/builds/2yeT9P6EC1wgSfcO1/openapi.json
