What the Avito scraper collects
Scrapes avito.ru category and search listings, full item pages and seller profiles: the price the buyer sees (with the old price and discount where Avito states them), location, condition, item parameters, photos, views and the seller's rating, reviews and tenure. Output is JSON or CSV plus a run-metadata sidecar that says whether the result is complete.
Category & search listings
Input: An avito.ru category path or a ?q= search URLOne row per card: displayed price, old price and discount where stated, region and metro location, summary parameters, seller name, type, rating and reviews, promoted flag and badges.
Item pages
Input: Item URLs, or a previous listing run's JSON via --fromEverything a listing row has, plus the description, all characteristics as params, every photo, category path, address with lat/lng, view counts, seller tenure and reply time.
Seller profiles
Input: A seller profile URL (/brands/<seller>)The seller's name, rating, reviews, tenure, subscribers and active-ad counter, plus the listing cards the profile page renders as listing rows.
From zero to Avito data in 3 steps
Install
Clone the repository and install one browser engine. Python 3.9+.
$ git clone https://github.com/2scraper/avito-scraper && cd avito-scraper $ pip install -r requirements.txt $ pip install -r requirements-playwright.txt && playwright install chromium $ cp .env.example .env
Run a scraper
Pick what you need and run it. Every flag is documented in the README.
$ python3 playwright_scraper.py --mode listing --url "https://www.avito.ru/moskva?q=iphone+15" --pages 2$ python3 playwright_scraper.py --mode item --from live/iphones.json --max-products 20 --out live/items$ python3 playwright_scraper.py --mode seller --url https://www.avito.ru/brands/<seller> --out live/sellerGet structured data
Rows land in JSON or CSV (
--format), with a.meta.jsonsidecar recording status, pages fetched and why the run stopped.
Avito data fields
29 columns per row in a predictable schema. The most useful ones:
| Field | What it holds |
|---|---|
sku | Avito's item id |
title | Listing title as printed on the card |
price | The displayed price the buyer sees, as a number |
currency | RUB |
original_price | Avito's own old price on a discounted item |
discount_pct | The site's own discount figure |
price_source | Which rendering the price came from: state (embedded JSON) or dom |
region_slug | Region from the URL, present on every row |
location | Metro station or district as printed |
summary_params | The card's one-line summary, e.g. new or used |
published_at | Publication time, where the rendering states it |
seller_name | Company or shop name; empty for private persons, whom Avito anonymises |
seller_type | company or private, where the card states it |
seller_rating | Seller's rating |
seller_reviews | Number of seller reviews |
promoted | Whether the card is a promoted placement |
[
{
"source": "avito.ru",
"scraped_at": "2026-10-06T11:43:07.634024+00:00",
"url": "https://www.avito.ru/moskva/telefony/iphone_17_256_gb_sim_esim_8212942358",
"sku": "8212942358",
"title": "iPhone 17, 256 ГБ, SIM + eSIM",
"image_url": "https://b00.img.avito.st/image/1/1.ZNuvMraAyDK5kmoz639ju6mSyjYdhcwyHeKpNh0xyZAakcwouZJq…",
"price": 64935.0,
"currency": "RUB",
"category": null,
"price_source": "dom",
"original_price": null,
"discount_pct": null,
"region_slug": "moskva",
"city": "Москва",
"location": "Багратионовская, 6–10 мин.",
"summary_params": "Новый",
"published_at": null,
"published_text": null,
"seller_name": "Продавец 1",
"seller_type": null,
"seller_id": "seller1",
"seller_url": "https://www.avito.ru/brands/seller1",
"seller_rating": 5.0,
"seller_reviews": 624,
"promoted": true,
"badges": [
"Реквизиты проверены",
"яПомогаю"
],
"delivery": null,
"page": 1,
"position": 1
},
{
"source": "avito.ru",
"scraped_at": "2026-10-06T11:43:07.639160+00:00",
"url": "https://www.avito.ru/moskva/telefony/iphone_17_pro_512_gb_8286114224",
"sku": "8286114224",
"title": "iPhone 17 Pro, 512 ГБ",
"image_url": "https://c70.img.avito.st/image/1/1.gxuaVbaAL_KM9Y3zkF_ZKYD1LfYo4ivyKIVO9ihWLlAv9ivojPWN…",
"price": 103090.0,
"currency": "RUB",
"category": null,
"price_source": "dom",
"original_price": null,
"discount_pct": null,
"region_slug": "moskva",
"city": "Москва",
"location": "Фили, 6–10 мин.",
"summary_params": "Новый",
"published_at": null,
"published_text": null,
"seller_name": "Продавец 2",
"seller_type": null,
"seller_id": "seller2",
"seller_url": "https://www.avito.ru/brands/seller2",
"seller_rating": 5.0,
"seller_reviews": 706,
"promoted": true,
"badges": [
"Реквизиты проверены"
],
"delivery": null,
"page": 1,
"position": 2
}
]First 2 of 10 rows from a real run — sample_output.json. Long values shortened here.
Handles what breaks naive Avito scrapers
The displayed price, not the stale one
On a discounted item Avito's bare price field holds the OLD price. price is always the one shown on the page and original_price is the site's own old figure; JSON, microdata and the item page agreed on 50 of 50 cards.
Firewall walls cleared in the browser's own session
The proof-of-work page clears itself in a real browser; the GeeTest v4 wall is solved through the page's own form, with the solve sent through the same IP the browser uses. The scraper refuses to pay for a solve that would not.
Substitute results are not results
A search with no matches still returns fifty «similar listings» cards. The run reports the page as empty (exit 4) instead of a complete-looking answer to a different question.
Two renderings, one schema
The same URL can come back as plain markup or with embedded JSON state. price_source records which one a row came from, and diff_runs.py does not report that difference as a price change. Promoted cards repeated across pages are deduplicated in page order.
Scraping infrastructure included
The same tested core runs every 2scraper repository, so the hard parts work the same way on every site.
CAPTCHA handling
Detects the challenge a page really serves and, with a 2Captcha key, solves it only when it blocks the data — a capped number of solves per page.
Proxy rotation
Single proxy or a pool from a file, rotated on blocks with a fresh browser per exit. Credentials stay out of argv and logs.
Fingerprints
Optional complete device identity from the 2Captcha Fingerprint API — user agent, client hints, locale and timezone that agree with each other.
Honest run metadata
Every run writes a .meta.json sidecar and distinct exit codes: complete, blocked, empty and partial are never confused, and a failed run never overwrites good data.
Diff two runs
diff_runs.py compares two complete Avito snapshots by id — new, removed and changed rows for monitoring.
What teams do with Avito data
Second-hand price tracking
Follow displayed prices, old prices and discounts for a category such as used iPhones in Moscow, run after run, compared by sku with diff_runs.py.
Regional market comparison
Scrape the same category across city paths and group by region_slug to compare supply and price levels between regions.
Dealer and shop monitoring
Track a company seller's profile: rating, review count, subscribers and active-ad counter over time.
Item-level catalogue data
Turn a listing run into full item records with every characteristic, all photos, coordinates and view counts for analysis.
Free to run. Pay only for what the site requires.
Needs a residential exit or the Scraping Browser API
There is no free path on avito.ru, measured on 2026-10-06: a plain HTTP client was refused 6 of 6 times and a local browser met the GeeTest wall on every fresh session. You need a Russian residential exit (2Captcha proxies), and the recommended transport is the Scraping Browser API, which clears the proof-of-work page by itself and keeps the clearance in a persistent profile. A 2Captcha key solves the GeeTest v4 wall through GeeTestTask, $0.00299 per solve in that measurement.
Optional 2Captcha services — captcha solving, the Scraping Browser API, residential proxies and fingerprints — work behind one key.
Good to know
- Seller mode returns only the cards a profile page renders (15 measured, of 107–353 active); the rest load on scroll and are not fetched by this version.
- city is often empty in the markup rendering; region_slug is on every row.
- Selenium cannot use the Scraping Browser API, and --concurrency above 1 is refused.
2scraper vs. hosted scraper APIs
| 2scraper | Typical hosted API | |
|---|---|---|
| Code | Open source, MIT — read and patch it | Closed |
| Cost | Free; optional services billed only when used | Subscription or per request / per result |
| Runs on | Your machine, server or CI | The vendor's infrastructure |
| Output | JSON/CSV files + run metadata | API responses |
| When the site changes | Fix it yourself or open an issue / PR | Wait for the vendor |
Avito scraper FAQ
What output formats does it write?
JSON or CSV, plus a <out>.meta.json sidecar recording status and which pages failed. A run that finds nothing writes nothing, so a good previous output is never replaced with an empty file.
Do I need a proxy and a captcha key?
Yes on this site. The README measured no plain-HTTP route and a GeeTest wall on every fresh local browser session, so a Russian residential exit and a 2Captcha key are part of the normal setup.
How does pagination work?
The scraper builds ?p=N pages and stops at the site's own last page, when a page adds no new item, or at --max-products.
Can I use sort or filter parameters in the URL?
No. avito.ru's robots.txt disallows ?s=, ?f=, ?radius= and ?view=, and the scraper refuses those URLs before fetching. Narrow by path instead: city, category, subcategory. ?q= search and ?p= pages are allowed.
Does it collect phone numbers or private sellers' names?
No. Phone numbers are behind login and are never read; private persons are anonymised by Avito itself, so their seller_name is empty and seller_type is private.
Is scraping Avito legal?
The repo reads public pages only, without logging in, and respects robots.txt. It is public data, but follow the site's terms and the law where you operate, including personal-data law such as Russia's 152-FZ for seller names.