# Avito Scraper & New-Listing Monitor (avito.ru, Russia) (`neverempty/avito-listings-monitor`) Actor

Avito.ru listings by region, category or search term: price in RUB, city, address, photos, promoted flag and business seller flag. Watch mode returns only listings created since your last check and price drops, never old ads bumped back up. No seller names or phones.

- **URL**: https://apify.com/neverempty/avito-listings-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** E-commerce, Real estate, Automation
- **Stats:** 3 total users, 2 monthly users, 85.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 listing returneds

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 Scraper & New-Listing Monitor

Get listings from **Avito.ru**, Russia's largest classifieds site, by region, category or search term, or by pasting a list URL. Run it on a schedule in **watch mode** and each run returns only the **listings created since your last check** and **price drops**, not old ads that sellers bumped back to the top.

- Apartments in Moscow, cars in Kazan, iPhones anywhere in Russia: any list page on avito.ru.
- Price as a number in **RUB**, plus the period Avito shows (for example `в месяц` for monthly rent) and Avito's own "price was lowered" flag.
- City, address and coordinates, category, photos, the time shown on the card, promotion flags (XL, highlight, boosts) and a business seller flag when Avito shows one.
- **No seller names, phone numbers or e-mails.** Phone numbers and e-mails written inside titles and descriptions are replaced with `[phone removed]` / `[email removed]`.
- You pay per listing returned. No start fee. Searches that return nothing, unknown regions or categories, and refused requests come back as **free rows that say why**.

### Input

| Field | What to put in |
|---|---|
| `locations` | Region or city part of the address: `moskva`, `sankt-peterburg`, `ekaterinburg`, `moskovskaya_oblast`, or `all` (whole of Russia). |
| `categories` | Category part after the region: `kvartiry`, `avtomobili`, `telefony/mobilnye_telefony`. Copy it from the address bar. |
| `searchQueries` | Words to search, in Russian or Latin letters. |
| `searchUrls` | Or paste an Avito list URL, such as `https://www.avito.ru/moskva/kvartiry`. |
| `maxResultsPerSearch` | Up to 1500 (Avito serves at most 30 pages of 50 per search). |
| `minPrice` / `maxPrice` | Price range in rubles, applied to the pages read. |
| `excludePromoted` | Leave out paid promoted listings. |
| `onlyNew` | Watch mode (see below). |

Example: `{"locations": ["moskva"], "categories": ["kvartiry"], "maxResultsPerSearch": 30}` returns the first 30 apartment listings in Moscow.

### Watch mode: new listings and price drops

Turn on `onlyNew` and schedule the same input (for example every hour).

1. The first run returns what it reads and remembers it (`changeType: "first-check"`).
2. Every later run returns only listings **created after the watch started** that you have not received (`changeType: "new"`), and listings whose price went down (`changeType: "price-drop"` with `previousPrice` and `priceChange`).
3. A check that finds nothing returns one free row `no-new-listings` and is charged as one small `search-checked` event.

"New" is decided by Avito's listing number, which grows as listings are created. An old listing that the seller paid to bump up again is not reported as new.

**Coverage:** Avito orders lists by relevance with paid promotions mixed in. Sorting by date is not allowed by Avito's robots.txt, so this Actor does not use it. A watch reads the first `watchPages` pages (4 by default, 200 listings). Keep the search narrow (a city, a category, more words) so those pages cover the whole list. The first check tells you how many listings the search has.

### Output

One row per listing:

```json
{
  "status": "ok",
  "changeType": null,
  "listingId": "8426673033",
  "title": "Квартира-студия, 26,5 м², 12/14 эт.",
  "price": 20500000,
  "currency": "RUB",
  "pricePeriod": null,
  "priceWasLowered": false,
  "city": "Москва",
  "categoryName": "Квартиры",
  "shownAt": "2026-10-06T12:37:00.000Z",
  "isPromoted": true,
  "promotions": ["bbip", "xl"],
  "sellerType": "agency",
  "url": "https://www.avito.ru/moskva/kvartiry/kvartira-studiya_265_m_1214_et._8426673033",
  "positionInSearch": 2,
  "listingsInSearch": 112462,
  "searchLocation": "moskva",
  "searchCategory": "kvartiry"
}
```

- `sellerType` is `business` (the seller has a business page on Avito), `agency` or `company` when Avito shows it, otherwise `null`. `null` does not mean a private seller.
- `city` is the listing's own city. Avito sometimes mixes listings from other regions into a regional search (it labels the list "first from <city>"), so check `city` if that matters to you.
- `shownAt` is the time the card shows ("3 hours ago"), which moves when a seller bumps the listing up. It is not the creation date.
- When Avito sends a search term to a matching category, `resolvedUrl` shows the list actually read.

Rows with another `status` are free and explain what happened: `no-results`, `none-in-price-range`, `not-found` (unknown region or category), `site-changed-search` (Avito answered with a different list than asked for, so nothing was returned), `not-allowed-by-robots-txt`, `blocked`, `unreadable`, `incomplete`, `no-new-listings`, `more-not-returned`, `watch-coverage`, `budget-reached`, `bad-input`.

### How it reads Avito

- It reads the same list pages a browser shows and the data embedded in them. No login, no API keys, no phone-number reveal.
- It follows Avito's robots.txt (checked on every run): no sort, price, seller-type or filter parameters, no `/api/`, no `/items/phone`.
- It identifies itself with its own user agent and does not imitate a browser. It reads slowly, through Apify datacenter IP addresses. If Avito limits an IP address, it asks again from another one (up to 3 times). It never solves or bypasses a captcha or check page; if one appears, you get a free `blocked` row.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `searchQueries` (type: `array`):

What to search for, one term per line, in Russian or Latin letters (for example iphone 15, велосипед, диван). Each term is searched in every region and category below. Avito sometimes moves a term to its matching category; each row shows the list actually read. Leave empty to list whole categories.

## `locations` (type: `array`):

The region or city part of an Avito address, one per line: moskva, sankt-peterburg, ekaterinburg, moskovskaya_oblast, or all for the whole of Russia. Empty means all of Russia. If every search field is empty, the example moskva + kvartiry is used.

## `categories` (type: `array`):

The category part of an Avito address after the region, one per line: kvartiry (apartments), avtomobili (cars), telefony/mobilnye_telefony. Copy it from the address bar on avito.ru. Empty searches all categories.

## `searchUrls` (type: `array`):

Or paste the address of an Avito list page, such as https://www.avito.ru/moskva/kvartiry or https://www.avito.ru/all?q=iphone. Filters inside the path are kept. Addresses with sort, price or filter parameters (s=, pmin=, f=, user=) are refused, because Avito's robots.txt does not allow them.

## `maxResultsPerSearch` (type: `integer`):

How many listings to return for each search, from 1 to 1500. Avito shows 50 per page and at most 30 pages (1500 listings) per search. In watch mode, the most rows one check returns per search.

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

Return only listings priced at or above this many rubles. Applied to the pages read (Avito's own price filter is not allowed by its robots.txt). Listings without a shown price are left out when a price range is set. Empty means no minimum.

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

Return only listings priced at or below this many rubles. Applied to the pages read. Empty means no maximum.

## `excludePromoted` (type: `boolean`):

Avito mixes paid promoted listings (XL, highlight, x10 boosts) into every page; they are marked isPromoted. Turn this on to leave them out and keep ordinary listings only. Off by default.

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

Run the same search on a schedule. The first run returns the listings it reads and remembers them. Every later run returns only listings created since the watch started that you have not received yet, and listings whose price went down. A check that finds nothing is charged as one small search-checked event instead of rows.

## `includePriceDrops` (type: `boolean`):

In watch mode, also return listings you already received when their price went down, with the previous price and the difference. Price rises are remembered but not returned.

## `watchPages` (type: `integer`):

How many pages (50 listings each) a watch reads per search on each check, from 1 to 30. Avito does not sort by date here, so a new listing can sit on any page; use a narrow search (a city, a category, more words) so these pages cover the whole list.

## `watchName` (type: `string`):

Optional. A name for this watch (letters, digits, dot, dash, underscore). Two schedules with the same search but different names keep separate memories. Empty uses one shared default watch.

## `resetMonitoringState` (type: `boolean`):

Start this watch over: the run is treated as the first check again. Off by default.

## Actor input object example

```json
{
  "locations": [
    "moskva"
  ],
  "categories": [
    "kvartiry"
  ],
  "maxResultsPerSearch": 30,
  "excludePromoted": false,
  "onlyNew": false,
  "includePriceDrops": true,
  "watchPages": 4,
  "resetMonitoringState": false
}
```

# Actor output Schema

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

One row per Avito listing: listing ID, title, price in RUB with the period shown (per month, per day), the price-lowered flag, description, city, address and coordinates, category, the time the card shows, promotion flags, business seller flag when shown, photos, link and position. Watch mode marks rows first-check, new or price-drop (with the previous price). A search with no listings, nothing new, an unknown region or category, a page robots.txt does not allow, a refused request or a run that hit its maximum charge comes back as a free row that says why.

# 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 = {
    "locations": [
        "moskva"
    ],
    "categories": [
        "kvartiry"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/avito-listings-monitor").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 = {
    "locations": ["moskva"],
    "categories": ["kvartiry"],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/avito-listings-monitor").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 '{
  "locations": [
    "moskva"
  ],
  "categories": [
    "kvartiry"
  ]
}' |
apify call neverempty/avito-listings-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/avito-listings-monitor"
        }
    }
}
```

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/p21WEj4KT1Rya9kdA/builds/z2E7XKLavCp6gXZ8M/openapi.json
