Otomoto.pl Scraper
Pricing
from $4.99 / 1,000 results
Otomoto.pl Scraper
Otomoto.pl Scraper Scrape vehicle listings from Otomoto.pl, including make, model, price, year, mileage, fuel type, transmission, location, seller details, specifications, images, and listing URLs. Export data to JSON, CSV, Excel, or XML for automotive research and market analysis.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
Scraper Engine
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Otomoto.pl Scraper — Price, Specs, Photos and Seller Data
Otomoto.pl Scraper extracts vehicle adverts from Otomoto.pl, Poland's largest car marketplace, and returns them as structured JSON — price, photos, full specification (parametersDict, equipment, details) and seller details for every advert. Search by category, brand/model, town or voivodeship, price band and production year, or paste advert URLs directly. No login, no browser rendering, no HTML parsing on your end. Run it now from the Apify Console or the API, or read on for the full field list.
What is Otomoto.pl Scraper?
Otomoto.pl Scraper is an Apify Actor that reads the vehicle-advert data Otomoto.pl server-renders into each page's __NEXT_DATA__ payload and turns it into one structured JSON row per advert. It requires no Otomoto.pl account or login — every field it returns comes from a page any visitor can open. It is built for data teams, marketplace analysts and AI engineers who need Polish vehicle-listing data without maintaining their own scraper.
What Otomoto.pl vehicle advert data is publicly available to scrape?
Every field on a live Otomoto.pl advert page is visible to any visitor with no account and no login — Otomoto.pl does not gate advert content behind a sign-in wall. What is genuinely absent is data Otomoto.pl itself never publishes in the page payload, not data hidden behind a login.
| Data Category | Publicly Available | Not Published by Otomoto.pl |
|---|---|---|
| Price, currency, price labels, price-drop | shown on the advert page | — |
Title, description, specification (parametersDict, equipment, details) | shown on the advert page | — |
| Photos (primary + full gallery) | shown on the advert page | — |
| Seller name, type, location, dealer page URL, working hours | shown on the advert page | dealer package entitlement flags (benefits) are excluded on purpose — see the fields table |
| Listing badges (e.g. low mileage) | shown on the listing card | not repeated on the advert page itself — null when an advert is reached without a listing card |
| Category node (code, id, label, path) | shown on the advert page | — |
Otomoto.pl Scraper only returns publicly visible data — what any visitor sees. Nothing behind a login wall.
What data can I extract with Otomoto.pl Scraper?
Otomoto.pl Scraper returns identity fields, pricing and condition flags, and full specification, seller and media data for every advert. These are the exact keys transform_advert() writes to each row.
Identity & listing fields
| Field Name | Description |
|---|---|
id | Otomoto.pl's internal advert id |
type | "advert" for a real vehicle row, "unavailable" for a free accounting row |
status | Otomoto.pl's own advert status string (e.g. "ACTIVE") |
title | Advert headline |
url | Canonical advert URL as Otomoto.pl currently publishes it |
sourceUrl | The URL this row was actually fetched from |
category | { code, id, label, uriPath } for the vehicle category node |
description | Full HTML advert description |
mainFeatures | The key specs Otomoto.pl shows on the listing card (year, mileage, engine size, fuel) |
badges | Listing-card badges such as LOW_MILEAGE; null when there was no listing card to read them from |
Price & condition fields
| Field Name | Description |
|---|---|
price | Integer price in PLN (coerced from the site's value) |
priceList | { value, currency, labels, isUnderBudget, netValue/netPrice/grossPrice when present } — value stays a string, as Otomoto.pl sends it, even though price is the integer coercion of the same number |
priceDrop | Populated only when the seller actually cut the price; null otherwise |
isUsedCar | Boolean, used vs. new |
isParts | Boolean, parts advert vs. vehicle advert |
verifiedCar | Boolean, Otomoto.pl's own verified-vehicle flag |
Specification, seller & media fields
| Field Name | Description |
|---|---|
seller | Full seller block (dealer or private): name, type, location, dealer page URL, external website, working hours, number of active adverts — minus benefits, a 70+ entry dealer-package entitlement list that describes the seller's subscription tier, not the seller, and is stripped on purpose |
packages | Dealer package identifiers active on the advert |
equipment | Full equipment list grouped by category |
details | Raw detail rows (key, value, label) |
detailsGroups | The group headers details rows belong to |
parametersDict | The complete parameters dictionary — year, mileage, fuel, gearbox, engine capacity, power, body type, and every other parameter Otomoto.pl publishes for the category |
primaryImageUrl | First photo URL |
images | Every photo URL on the advert |
adFeatures | Raw feature array Otomoto.pl attaches to the advert |
valueAddedServices | Raw value-added-service array Otomoto.pl attaches to the advert |
createdAt | Publish timestamp |
originalCreatedAt | First-publish timestamp (before any repost) |
updatedAt | Last-update timestamp |
scrapedAt | This run's start time, UTC — identical across every row of one run |
httpStatus | Present only on type: "unavailable" rows — the HTTP status Otomoto.pl answered |
unavailableReason | Present only on type: "unavailable" rows — why the advert could not be read |
A field Otomoto.pl stops sending is written as null, never as 0, "" or an empty list — an empty array in a row means Otomoto.pl genuinely sent an empty array.
Why not build this yourself?
Otomoto.pl (OLX Group) publishes no official API for third-party advert search, so the only path is reading the page itself — and the page has several traps that are easy to miss on a first build. Otomoto.pl answers HTTP 200 with an unfiltered, catalogue-wide result set for an unrecognised brand, model or town instead of an error, so a naive scraper silently returns the wrong data. Five of the category URL slugs (motorcycles, trailers, construction, agricultural, campers) have moved since the site's last redesign, and the standalone campers category was retired outright. Several sort keys are accepted by the search form but genuinely inert server-side. A removed advert answers HTTP 410 with a valid page, which a naive block-detector misreads as a proxy block and burns its retry budget on a dead URL instead of on a real one. Otomoto.pl Scraper carries all of this handling already, plus per-URL retry budgets and an automatic none → datacenter → residential proxy escalation, so you get a validated result set instead of debugging silent scope drift.
How to use Otomoto.pl Scraper
Otomoto.pl Scraper runs on Apify — no separate signup or credentials beyond an Apify account.
- Open Otomoto.pl Scraper on the Apify Store and click Try for free (or Run, if you already have it in your account).
- Leave every field at its default to pull the first page of the
carscategory, or setcategory,query,location,minPrice/maxPriceandminProductionYear/maxProductionYearto narrow the search. No parameter is required. - Set
sort,maxItems,concurrency,requestDelayandproxyConfigurationif the defaults don't fit your run. - Click Start and watch the run log — it states the actual Otomoto.pl sort key used and any category-slug migration applied.
- Open the Dataset tab and export as JSON, CSV, Excel, or pull it via the Apify API.
How to scale to bulk vehicle advert extraction
Paste multiple listing pages or individual advert URLs into the startUrls array to scrape several searches or specific adverts in one run — a non-empty startUrls overrides every search filter. For a single search, raise maxItems (up to 100,000) instead: the actor paginates automatically and stops once it has collected that many unique adverts or the result set ends. There is no separate "batch" input; multiple distinct searches means multiple runs, or multiple listing URLs in startUrls.
What can you do with Otomoto.pl vehicle advert data?
- 📊 A market analyst benchmarking used-car pricing uses
price,parametersDict(year, mileage) andcategoryto build a price-per-mileage curve by brand and model. - 🏢 Dealer inventory monitoring teams use
seller.numberOfActiveAds,packagesandupdatedAtto track a competing dealer's stock turnover over time. - 🌍 Import/export sourcing teams filter by
minProductionYear/maxProductionYearandlocation, then useequipmentandparametersDictto shortlist matching vehicles before contacting the seller. - 🔬 Researchers studying the used-vehicle market use
priceDropandcreatedAt/originalCreatedAtto measure how quickly adverts reprice or churn. - 🤖 AI engineers feed
description,mainFeaturesandparametersDictinto a RAG pipeline or agent tool to answer natural-language questions about vehicle stock without writing a parser.
How does Otomoto.pl Scraper handle rate limits and blocking?
Requests start with no proxy — Otomoto.pl's source comments document zero HTTP 403s and zero blocks across dozens of direct container requests, measured 2026-08-03. If Otomoto.pl does start blocking, the actor escalates itself through a sticky ladder — none → datacenter → residential — rotating the exit IP before each retry, with a fresh 3-attempt retry budget per URL (not shared across the run, so one hard page never drains the budget for the rest). Concurrency is capped by the concurrency input via a semaphore, and requestDelay adds an optional pause plus jitter before every request. A removed or sold advert (HTTP 410/404) is classified separately from a block and never touches the proxy ladder at all — it becomes a free type: "unavailable" row instead of a retry.
⚠️ A search Otomoto.pl did not actually run — an unrecognised brand, model, or unresolvable town — makes the run fail loudly with the rejected term named, rather than silently handing back an unfiltered result set.
⬇️ Input
All fields are optional — leave everything at its default to pull the first page of the cars category, or set startUrls to scrape specific pages directly.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
startUrls | No | array | Otomoto.pl listing or advert URLs. Non-empty, this overrides every filter below. A sold/removed advert becomes a free, uncharged row instead of disappearing. | ["https://www.otomoto.pl/osobowe/volvo"] |
category | No | string (enum) | Vehicle section: cars, vans, trucks, motorcycles, trailers, campers, construction, agricultural, parts. Default "cars". English aliases are translated to Otomoto.pl's current slug. | "cars" |
query | No | string | Brand, or brand + model separated by a space, in Otomoto.pl's own Polish naming. Default "". | "bmw seria 3" |
location | No | string | A Polish town or a voivodeship. Default "" (whole of Poland). | "Warszawa" |
sort | No | string (enum) | relevance_web, created_at:desc, created_at:asc, price:asc, price:desc, year:desc, year:asc, filter_float_price:asc, filter_float_price:desc, filter_float_mileage:asc, created_at_first:desc. Default "relevance_web". | "filter_float_price:asc" |
minPrice | No | integer | Minimum price in PLN. Minimum 0. | 50000 |
maxPrice | No | integer | Maximum price in PLN. Minimum 0. | 150000 |
minProductionYear | No | integer | Earliest production year. Range 1900–2030. | 2019 |
maxProductionYear | No | integer | Latest production year. Range 1900–2030. | 2024 |
maxItems | No | integer | Hard cap on charged adverts. Range 1–100000. Default 10. | 50 |
concurrency | No | integer | Parallel Otomoto.pl page fetches. Range 1–20. Default 10. | 10 |
requestDelay | No | integer | Extra seconds before each request, plus jitter. Range 0–30. Default 0. | 0 |
proxyConfiguration | No | object | Apify Proxy settings. Default {"useApifyProxy": false} — the actor escalates on its own if genuinely blocked. | {"useApifyProxy": false} |
Example input
{"category": "cars","query": "bmw seria 3","location": "Warszawa","sort": "filter_float_price:asc","minPrice": 50000,"maxPrice": 150000,"minProductionYear": 2019,"maxProductionYear": 2024,"maxItems": 50,"concurrency": 10,"requestDelay": 0,"proxyConfiguration": { "useApifyProxy": false }}
⬆️ Output
Every run writes one typed JSON row per advert to the Actor's dataset, with the same field names on every run. Export it as JSON, CSV, Excel, or read it straight from the Apify API — no parsing required.
Example output
{"id": "6149832101","type": "advert","status": "ACTIVE","title": "Volvo XC 40 B4 mHEV Ultimate Dark","url": "https://www.otomoto.pl/osobowe/oferta/volvo-xc-40-ID6IbdLC.html","sourceUrl": "https://www.otomoto.pl/osobowe/oferta/volvo-xc-40-ID6IbdLC.html","price": 189900,"priceList": {"value": "189900","currency": "PLN","labels": ["Faktura VAT"],"isUnderBudget": false},"primaryImageUrl": "https://ireland.apollo.olxcdn.com/v1/files/example-primary.jpg","images": ["https://ireland.apollo.olxcdn.com/v1/files/example-primary.jpg","https://ireland.apollo.olxcdn.com/v1/files/example-2.jpg"],"createdAt": "2026-07-29T09:11:04Z","originalCreatedAt": "2026-06-14T12:02:55Z","updatedAt": "2026-08-02T18:41:07Z","mainFeatures": ["2023", "31 500 km", "1 969 cm3", "Hybryda"],"badges": ["LOW_MILEAGE"],"description": "<p>Samochod w idealnym stanie, pierwszy wlasciciel, bezwypadkowy.</p>","isParts": false,"isUsedCar": true,"verifiedCar": true,"seller": {"type": "PROFESSIONAL","name": "Volvo Auto Bruno","sellerUrl": "https://volvoautobruno.otomoto.pl/inventory","website": "https://www.volvoautobruno.pl","numberOfActiveAds": 84,"location": { "city": "Warszawa", "postalCode": "00-877" }},"packages": ["dealer_4th_package"],"equipment": [{ "key": "audio_and_multimedia", "label": "Audio i multimedia", "values": [{ "key": "apple_carplay", "label": "Apple CarPlay" }] }],"details": [{ "key": "year", "value": "2023", "label": "Rok produkcji" }],"detailsGroups": [{ "key": "basic_information", "label": "Podstawowe informacje" }],"parametersDict": {"year": { "label": "year", "values": [{ "value": "2023", "label": "2023" }] }},"category": { "code": "osobowe", "id": "29", "label": "Osobowe", "uriPath": "/osobowe" },"adFeatures": ["EXTENDED_WARRANTY"],"valueAddedServices": [],"priceDrop": null,"scrapedAt": "2026-08-04T09:12:03Z"}
How does it work?
Otomoto.pl server-renders every listing and advert page's data into a <script id="__NEXT_DATA__"> block, so Otomoto.pl Scraper fetches the page with a plain HTTP client and reads that JSON block directly — no headless browser, no rendered-page screenshots, no CSS selectors to break when Otomoto.pl redesigns a page. Requests go out with no proxy by default and escalate to a datacenter-then-residential ladder only if a genuine block is detected, so most runs never touch a proxy at all. Because the field names come from Otomoto.pl's own internal data payload rather than from parsing visible HTML, the output schema stays the same even when Otomoto.pl changes its page layout — the scraper only breaks if Otomoto.pl changes the payload shape, which is checked for on every run. Only publicly visible advert data is returned; nothing behind a login is read.
Integrations
Otomoto.pl Scraper runs on Apify, so it works with anything that can call the Apify API or the apify-client SDKs — no separate signup, no proprietary auth scheme.
Calling Otomoto.pl Scraper programmatically
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("<ACTOR_ID>").call(run_input={"category": "cars","query": "volvo","location": "Krakow","maxItems": 20,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["price"])
Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request to POST https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=<APIFY_API_TOKEN>.
No-code tools (n8n, Make)
In n8n, use the HTTP Request node pointed at the run-sync-get-dataset-items endpoint above, with your input as the JSON body — no custom code node needed. In Make, an HTTP > Make a request module against the same endpoint returns the dataset rows directly to the next step in your scenario.
⚖️ Is it legal to scrape Otomoto.pl vehicle adverts?
Scraping publicly available vehicle-advert data is generally lawful — this Actor reads only pages any visitor can open, with no login and no access to gated account features. Otomoto.pl vehicle adverts are business/product listing data — prices, specifications, seller-published business details — not personal profile data, so GDPR's data-subject provisions do not attach to the compiled dataset itself. Otomoto.pl's own Terms of Service and database-rights protections still govern how you may use and redistribute what you collect, so review them for your use case. Where a private (non-dealer) seller's name or location appears in the seller block, treat that specific value as personal data if you store it beyond a short-lived analysis window. Consult legal counsel if your use case involves bulk storage of personal data.
❓ Frequently asked questions
What Otomoto.pl vehicle advert fields does Otomoto.pl Scraper return?
price, parametersDict, equipment, seller and images are the highest-value fields — see What data can I extract above for the complete list of every field the actor writes.
Does Otomoto.pl Scraper require an Otomoto.pl account or login?
No. The source reads the public __NEXT_DATA__ payload embedded in each listing and advert page — no Otomoto.pl account, login or API key is used or required.
How many vehicle adverts can I extract in one run?
Up to maxItems (maximum 100,000), capped further by however many adverts actually match the search — the actor never returns more rows than the smaller of maxItems and Otomoto.pl's own declared result count for that search.
What happens if an advert is removed or sold before the scrape finishes?
It becomes a free, uncharged row instead of a silent gap: type: "unavailable", with httpStatus and unavailableReason set from Otomoto.pl's own response. It never touches the proxy escalation ladder, since a removed advert is not a block. Filter these out downstream with type == "advert" if you only want billable rows.
Can I scrape multiple Otomoto.pl vehicle adverts at once?
Yes. Pass multiple listing pages or individual advert URLs in the startUrls array to fetch several sources in one run, or raise maxItems on a single search to collect more adverts from it — both run inside one Actor call.
Does Otomoto.pl Scraper work with Claude, ChatGPT and other AI agent tools?
Yes, as an HTTP endpoint. Any agent framework that can call POST https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items can trigger a run and read back typed JSON rows directly.
What makes Otomoto.pl Scraper's data reliable for the search you actually asked for?
It validates the search before trusting it: after the first listing request, it checks Otomoto.pl's own appliedFilters and appliedLocation against what you asked for, and fails the run loudly — naming the rejected brand, model or town — rather than silently handing back an unrelated, unfiltered result set.
Does Otomoto.pl Scraper return data in a format LLMs can use directly?
Yes. Every row is typed, normalized JSON with consistent field names across runs — no HTML, no selectors to write. Pass it straight to an LLM, index it into a vector store, or use it as an agent tool's output.
What happens when Otomoto.pl changes its layout or anti-bot system?
The output schema is designed to stay stable regardless of visible-page redesigns, since fields come from Otomoto.pl's internal data payload rather than from parsed HTML. No specific update turnaround is promised.
Can I use Otomoto.pl Scraper without managing proxies or browser infrastructure?
Yes. The default run uses no proxy at all, and the actor escalates automatically to a datacenter, then residential, proxy only if Otomoto.pl genuinely blocks it — you never configure or rotate proxies yourself unless you choose to override the starting tier.
Which Otomoto.pl vehicle advert fields work best for AI training data and RAG indexing?
For RAG, index description, mainFeatures and parametersDict — the highest-information text and structured-spec fields. For training data, id, price, category and parametersDict return as consistently typed primitives across every advert.
💬 Your feedback
Found a bug or missing a field on Otomoto.pl Scraper? Open an issue from the Actor's page on the Apify Store or message the developer directly through Apify Console — reports like these are how the scraper stays working as Otomoto.pl changes its site.