Otomoto.pl Scraper & Nearby Towns And Regions
Pricing
from $4.99 / 1,000 results
Otomoto.pl Scraper & Nearby Towns And Regions
Otomoto.pl Scraper extracts vehicle listings, prices, mileage, specifications, seller details, locations, and other car data from Otomoto.pl. Automate car market research, price monitoring, competitor analysis, and automotive lead generation.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
API Empire
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
Otomoto.pl Scraper — Extract Vehicle Ads, Towns & Regions as JSON
Otomoto.pl Scraper & Nearby Towns And Regions pulls vehicle adverts from Poland's largest car marketplace, Otomoto.pl, across as many towns and whole voivodeships as you list in a single run, merging every catchment into one de-duplicated dataset. It returns three row types: charged vehicle adverts with pricing, specs and seller detail; free accounting rows for adverts removed before they could be read; and free geo-expansion rows carrying Otomoto's own region and town coverage lists. Every field comes back as typed JSON — no HTML, no selectors, no parsing step. After reading this, you'll know exactly which towns get swept, how the per-run item cap is split between them, and what every output field actually contains.
What is Otomoto.pl Scraper & Nearby Towns And Regions?
It is a multi-centre wrapper around an Otomoto.pl vehicle-listing scraper: instead of searching one
town, you list several towns (each with its own travel radius) and/or whole voivodeships, and the
Actor runs every centre as its own Otomoto search before merging the results into one set, deduped
on the advert URL. No Otomoto account or login is required — it reads the data Otomoto already
server-renders into each page's __NEXT_DATA__ payload.
- 🚗 Scrape vehicle adverts (cars, vans, trucks, motorcycles, trailers, campers, construction and agricultural machinery, parts) with full pricing, specs, equipment and seller detail
- 🗺️ Scrape flat seller geography — town, voivodeship, postcode and coordinates — lifted onto top-level columns for every advert
- 🧭 Scrape Otomoto's own regional and town coverage lists (opt-in, free rows) to see where stock actually concentrates before choosing your next search centre
- 📦 Export as JSON, CSV, Excel or any format the Apify dataset API supports
- 🌐 No proxy management, no headless browser, no manual pagination
What data does Otomoto.pl Scraper & Nearby Towns And Regions collect?
Every run can return up to three distinct data types, all merged into one dataset and separated by
the row's type field.
| Data Type | Key Fields | JSON Field Names |
|---|---|---|
Vehicle adverts (type: "advert") | title, price, currency, mileage/year (via parameters), equipment, seller | title, price, priceList, parametersDict, equipment, seller, category |
| Seller & geography data (on every advert row) | seller town, voivodeship, postcode, coordinates, which search centre found it | sellerCity, sellerVoivodeship, sellerPostcode, sellerLatitude, sellerLongitude, matchedSearchCentre |
Regional / town coverage (type: "geo_expansion", opt-in, free) | place name, live advert counter, ready-made Otomoto URL | expansionName, expansionAdCount, expansionUrl, expansionSlug |
Rows with type: "unavailable" are a fourth, free accounting type for adverts that were removed or
sold before their detail page could be read — see the Output section below for their shape.
Why not build this yourself?
Otomoto.pl has no general-purpose public API for reading search results — the documented API at
otomoto.pl/api/doc/ is a partner/dealer OAuth integration for businesses managing their own
listings, not a public endpoint for searching or bulk-reading the marketplace. Building this
yourself means reverse-engineering the __NEXT_DATA__ payload, tracking Otomoto's category-slug
renames (several have moved in the last measurement pass — see below), handling an unknown town
that silently returns the whole country instead of an error, de-duplicating overlapping catchments
across several towns, and building a proxy escalation ladder for when Otomoto does block a request.
This Actor already does all of that: it asserts every search centre against Otomoto's own
appliedLocation before a single detail page is fetched, aliases retired category slugs
automatically, and only escalates from no proxy to datacenter to residential when a request is
genuinely blocked — not by default.
Why do developers and teams scrape Otomoto.pl?
For AI engineers and agent builders
Vehicle-marketplace data is a natural fit for RAG pipelines and pricing agents: index adverts by
category, price, parametersDict (year, mileage, fuel type) and sellerVoivodeship so an agent
can answer "what's the cheapest BMW 3 Series within 100 km of Kraków" without touching HTML. Because
every row is typed JSON with stable field names, it can be embedded into a vector store or passed
straight into an LLM's context window as a tool result.
For market and pricing analysts
Sourcing analysts use the town + voivodeship sweep to answer "where is this model cheapest to buy in
Poland" — a question the standard single-town search can't answer without running it once per place
and merging spreadsheets by hand. matchedSearchCentre and sellerVoivodeship let you group results
by region directly in the output.
For dealers and vehicle traders
A trader restocking across several dealership catchments can list every town they'd realistically
drive to, set a travel radius, and get one de-duplicated feed instead of running the search once per
town and reconciling duplicates. foundByMultipleSearches flags adverts sitting inside more than one
catchment.
For researchers studying the used-vehicle market
The voivodeship sweep gives an exact administrative sample (not a radius approximation) for regional market studies, and every row carries only what Otomoto itself publishes — no inferred or geocoded values.
How to scrape Otomoto.pl (step by step)
- Open Otomoto.pl Scraper & Nearby Towns And Regions on the Apify Store and click Try for free (or run it from your own Apify account).
- Provide input — every field is optional. Leave
cities,voivodeships,excludeCitiesandlocationall empty to search the whole of Poland exactly as the standard Otomoto.pl Scraper does, or list one or more towns incitiesand setsearchRadiusKm. - Set your vehicle filters —
category,query(brand/model),minPrice/maxPrice,minProductionYear/maxProductionYear, andsort. - Set
maxItems— the hard cap on adverts scraped and charged across the whole run, not per town — and start the run. - Open the Output tab and export the dataset as JSON, CSV or Excel, or pull it through the Apify API.
What to do when Otomoto.pl changes its structure
The Actor is maintained, and the output schema stays stable — the field names and types documented below don't change on your end even when Otomoto renames a category or reshapes a page. No numeric turnaround time is promised for any given fix.
What changed in Otomoto.pl scraping recently?
Since Otomoto's most recent category restructuring (measured 2026-08-03), five of the standard
scraper's original category slugs no longer resolve directly: /motocykle now redirects to
/motocykle-i-quady, /naczepy-przyczepy to /przyczepy, /budowlane to /maszyny-budowlane, and
/rolnicze to /maszyny-rolnicze. The standalone /kampery category was retired entirely — campers
are now reachable only as a body-type filter inside the vans category (/dostawcze/<make>/kamper).
A DIY scraper with these slugs hardcoded will 404 or silently fetch the wrong section. This Actor
aliases every renamed category automatically and logs the migration when it fires, so category
values written against the old slugs keep working. Every vehicle category that existed before the
restructuring is still reachable today under its current slug or filter form.
⬇️ Input
Every field is optional — leave everything empty to search the whole of Poland with the cars
category, exactly like the standard Otomoto.pl Scraper.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
cities | No | Array of strings | One Polish town per line. Each becomes its own Otomoto search, merged with the others and de-duplicated. Default []. | ["Kraków", "Katowice"] |
searchRadiusKm | No | Integer | Otomoto's own search[dist] radius in km, applied to towns only (not voivodeships). Min 5, max 1000, default 100. | 100 |
voivodeships | No | Array of strings (enum, select) | Whole Polish regions to sweep — an exact administrative match, not a radius. One of the 16 voivodeship slugs. Default []. | ["malopolskie"] |
excludeCities | No | Array of strings | Drop adverts whose seller sits in one of these towns, matched with Polish diacritics folded. Applied after the detail page is fetched. Default []. | ["Nowy Sącz"] |
location | No | String | Single town or voivodeship — the classic field from the standard Otomoto.pl Scraper, merged with cities rather than overridden. Default "". | "Warszawa" |
query | No | String | Brand, or brand plus model separated by a space, in Otomoto's own Polish naming. Default "". | "bmw seria 3" |
category | No | String (enum) | cars, vans, trucks, motorcycles, trailers, campers, construction, agricultural, parts. Default "cars". | "cars" |
minPrice | No | Integer | Minimum price in PLN, minimum 0. | 40000 |
maxPrice | No | Integer | Maximum price in PLN, minimum 0. | 150000 |
minProductionYear | No | Integer | Earliest production year. Min 1900, max 2030. | 2018 |
maxProductionYear | No | Integer | Latest production year. Min 1900, max 2030. | 2025 |
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". | "price:asc" |
maxItems | No | Integer | Hard cap on adverts scraped and charged across the whole run, not per town. Min 1, max 100000, default 10. | 40 |
startUrls | No | Array of strings | Full Otomoto.pl listing or single-advert URLs. When non-empty, overrides every filter above. Default []. | ["https://www.otomoto.pl/osobowe/bmw/krakow"] |
includeGeoExpansion | No | Boolean | Adds free geo_expansion rows with Otomoto's own region/town coverage lists. Default false. | true |
concurrency | No | Integer | Parallel page fetches. Min 1, max 20, default 10. | 10 |
requestDelay | No | Integer | Extra pause per request in seconds, plus jitter. Min 0, max 30, default 0. | 0 |
proxyConfiguration | No | Object | Apify Proxy settings. Default {"useApifyProxy": false} — the Actor escalates to datacenter, then residential, on its own if genuinely blocked. | {"useApifyProxy": false} |
Example input:
{"cities": ["Kraków", "Katowice"],"searchRadiusKm": 100,"voivodeships": ["malopolskie"],"excludeCities": ["Nowy Sącz"],"location": "","query": "bmw seria 3","category": "cars","minPrice": 40000,"maxPrice": 150000,"minProductionYear": 2018,"maxProductionYear": 2025,"sort": "price:asc","maxItems": 40,"startUrls": [],"includeGeoExpansion": true,"concurrency": 10,"requestDelay": 0,"proxyConfiguration": { "useApifyProxy": false }}
Common pitfall: maxItems is a total for the whole run, not a per-town allowance. Six towns
at maxItems: 10 still fetch ten advert pages in total, split fairly across the centres — raise
maxItems deliberately when you add towns, or most of them will contribute nothing.
⬆️ Output
Every row is typed, normalized JSON with a stable schema. Charged advert rows and free accounting
rows are pushed to the same Apify dataset, distinguished by type, and can be exported as JSON, CSV
or Excel from the Output tab or pulled through the Apify API.
Scraped vehicle advert (type: "advert")
{"id": "6IbnVT","type": "advert","status": "active","title": "BMW X6 xDrive40d M Sport","url": "https://www.otomoto.pl/osobowe/oferta/bmw-x6-ID6IbnVT.html","sourceUrl": "https://www.otomoto.pl/osobowe/oferta/bmw-x6-ID6IbnVT.html","price": 289900,"priceList": {"value": "289900","currency": "PLN","labels": ["Cena brutto"],"isUnderBudget": false},"primaryImageUrl": "https://ireland.apollo.olxcdn.com/v1/files/example.jpg","images": ["https://ireland.apollo.olxcdn.com/v1/files/example.jpg","https://ireland.apollo.olxcdn.com/v1/files/example2.jpg"],"createdAt": "2026-07-28T09:12:00Z","originalCreatedAt": "2026-06-01T14:03:00Z","updatedAt": "2026-08-02T10:44:00Z","mainFeatures": ["2021", "45 200 km", "3.0 diesel", "Automatyczna"],"badges": ["LOW_MILEAGE"],"description": "BMW X6 xDrive40d, M Sport, pierwszy właściciel, serwisowany...","isParts": false,"isUsedCar": true,"verifiedCar": true,"seller": {"id": "912345","name": "Auto Salon Kraków","type": "business","location": {"city": "Kraków","postalCode": "30-001","region": "Małopolskie","canonicals": { "city": "krakow", "region": "malopolskie" },"map": { "latitude": 50.06465, "longitude": 19.94498 }}},"packages": ["EXTENDED", "TOP"],"equipment": ["Klimatyzacja automatyczna", "Skórzana tapicerka", "Czujniki parkowania"],"details": [{ "key": "mileage", "value": "45200" }],"detailsGroups": [{ "label": "Ogólne informacje", "items": ["Rok produkcji: 2021"] }],"parametersDict": {"year": { "value": "2021" },"mileage": { "value": "45200" },"fuel_type": { "value": "Diesel" }},"category": {"code": "personal-vehicles","id": "29","label": "Osobowe","uriPath": "osobowe"},"adFeatures": ["FEATURED"],"valueAddedServices": ["FREE_INSPECTION"],"priceDrop": { "previousPrice": "299900", "percentage": 3 },"scrapedAt": "2026-08-04T09:15:03Z","sellerCity": "Kraków","sellerCitySlug": "krakow","sellerVoivodeship": "malopolskie","sellerRegionLabel": "Małopolskie","sellerPostcode": "30-001","sellerLatitude": 50.06465,"sellerLongitude": 19.94498,"matchedSearchCentre": "Kraków","matchedSearchCentres": ["Kraków"],"matchedSearchType": "city","searchRadiusKmUsed": 100,"foundByMultipleSearches": false,"geoSearchesRun": 2,"expansionScope": null,"expansionName": null,"expansionAdCount": null,"expansionUrl": null,"expansionSlug": null,"sourceListingUrl": null}
Removed or sold advert (type: "unavailable", free — never charged)
Every column the advert row carries is still present so the dataset stays rectangular; unobserved
values are null, never a fabricated 0 or "".
{"type": "unavailable","sourceUrl": "https://www.otomoto.pl/osobowe/oferta/bmw-x6-ID6IbnVT.html","url": "https://www.otomoto.pl/osobowe/oferta/bmw-x6-ID6IbnVT.html","httpStatus": 410,"unavailableReason": "advert_removed_or_expired","matchedSearchCentre": "Kraków","scrapedAt": "2026-08-04T09:15:11Z"}
Regional / town coverage (type: "geo_expansion", opt-in, free — never charged)
{"type": "geo_expansion","expansionScope": "city","expansionName": "Katowice","expansionAdCount": 812,"expansionSlug": "katowice","expansionUrl": "https://www.otomoto.pl/osobowe/bmw/katowice","sourceListingUrl": "https://www.otomoto.pl/osobowe/bmw/krakow","scrapedAt": "2026-08-04T09:15:12Z"}
How does Otomoto.pl Scraper & Nearby Towns And Regions compare to other Otomoto.pl scrapers?
| Feature | This Actor | Generic single-town scraper |
|---|---|---|
| Multi-town + voivodeship sweep | ✅ Merged and de-duplicated in one run | ❌ One location per run, manual merging |
| Unknown-town handling | ✅ Fails loud before charging (appliedLocation assertion) | ❌ Often silently returns the whole country as if it were local |
| Category-slug drift | ✅ Retired slugs aliased automatically, migration logged | ❌ Hardcoded slugs break silently when Otomoto renames a section |
| Removed/sold adverts | ✅ Logged as free, uncharged rows with a reason | ❌ Often silently dropped or billed anyway |
| Output format | ✅ Typed JSON, stable schema, seller geography flattened to top-level columns | ❌ Varies; frequently needs extra parsing |
If you're building an AI agent or RAG pipeline, the output-format row is the decision-maker — parsing HTML inside an agent loop is a reliability failure mode, not a feature.
How many results can you scrape with Otomoto.pl Scraper & Nearby Towns And Regions?
maxItems is the real ceiling — default 10, minimum 1, maximum 100000, and it applies to the
whole run, not per town. When several centres are swept, the budget is split fairly across them
and whatever a thin centre can't absorb spills to the ones that still have adverts. Because
catchments can overlap heavily, the merged unique-advert count can still land under maxItems even
after every centre has contributed — the run retries up to 6 top-up rounds (each centre capped at
3× its share of maxItems) before giving up and logging a warning rather than pretending the target
was reached. You can never get more adverts than Otomoto's own totalCount for the search, and
opt-in geo-expansion rows are capped at 200 per run regardless of maxItems.
Integrate Otomoto.pl Scraper & Nearby Towns And Regions and automate your workflow
Otomoto.pl Scraper & Nearby Towns And Regions works with any language or tool that can send an HTTP
request, through the Apify API and apify-client SDKs.
REST API integration
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("your-username/otomoto-pl-scraper-and-nearby-towns-and-regions").call(run_input={"cities": ["Kraków", "Katowice"],"searchRadiusKm": 100,"category": "cars","maxItems": 40,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["price"], item["sellerCity"])
Works in Python, Node.js, Go, Ruby, cURL.
Automation platforms (n8n, Make, LangChain)
Apify's own Apify node/module (available in n8n and Make) can run this Actor by ID on a schedule and hand the resulting dataset to the rest of your workflow — no Otomoto-specific integration is required beyond pointing it at this Actor and its input JSON. Apify Schedules and webhooks cover recurring runs and completion callbacks without any third-party automation tool at all.
⚖️ Is it legal to scrape Otomoto.pl?
Scraping publicly accessible marketplace listings is generally lawful; this Actor returns only data
that is already rendered on Otomoto.pl's public pages — no login, no paywalled content, and no
private-account data. The primary output — vehicle prices, specs, categories and listing metadata —
is business/product data governed by Otomoto's own Terms of Service and database-rights law, not by
GDPR. The seller object is passed through largely as Otomoto publishes it and can include a
private individual's name or phone number when the seller is not a dealer; that subset is personal
data and GDPR/CCPA principles apply to how you store and use it. Consult legal counsel for commercial
use cases involving bulk personal data.
❓ Frequently asked questions
Does Otomoto.pl Scraper & Nearby Towns And Regions work without an Otomoto account?
Yes. It reads the __NEXT_DATA__ payload Otomoto already server-renders into listing and detail
pages, so no Otomoto login or account is required.
How often is the scraped data updated?
Every run fetches Otomoto.pl live — there is no caching layer. scrapedAt on every row is the
timestamp of that specific fetch, not a cached snapshot.
What happens when an advert is sold or removed before the run reaches it?
It is pushed as a free, uncharged type: "unavailable" row with httpStatus and
unavailableReason: "advert_removed_or_expired" instead of silently disappearing from the output.
Can I scrape private or restricted Otomoto content?
No. Only what Otomoto renders on its public listing and detail pages is returned — no login-gated seller messaging, no private-account data.
What happens if I enter a town Otomoto doesn't recognise?
The run fails for that centre rather than silently returning national results. Otomoto itself
answers an unknown town with HTTP 200 and the whole country's catalogue with a null
appliedLocation; this Actor checks appliedLocation before fetching a single detail page and names
the rejected town in the log.
What happens when two of my towns' catchments overlap?
Overlapping results are merged and de-duplicated on the advert URL, never charged twice. If the
overlap is severe enough that the unique count still falls short of maxItems after the retry
rounds, the run logs a warning naming the shortfall rather than padding the output.
Does Otomoto.pl Scraper & Nearby Towns And Regions work for AI agent workflows and LLM pipelines?
Yes — it is callable as an HTTP endpoint by any agent framework through the Apify API. Every response is typed JSON with stable field names, so it can be passed to an LLM or indexed into a vector store without an HTML-parsing step.
How does it handle Otomoto's anti-bot defenses?
Otomoto answers Apify's own datacenter IPs directly without a proxy in the vast majority of cases, so the Actor starts unproxied by default. If a request is genuinely blocked, it escalates through a sticky ladder — none → datacenter → residential — with a per-URL retry budget of 3 attempts before escalating, rather than burning a run-wide budget on a single dead advert.
Can I use Otomoto.pl Scraper & Nearby Towns And Regions without managing proxies?
Yes. Leave proxyConfiguration at its default (useApifyProxy: false) and the Actor manages its own
proxy escalation automatically when needed.
What happens when Otomoto.pl changes its structure or blocks the scraper?
The Actor is maintained and the output schema stays stable — field names and types don't change on your end. No numeric turnaround time is promised for any specific fix.
💬 Your feedback
Found a bug or missing a field? We want to know. Open an issue through the Actor's page on the Apify Store or contact API-Empire support from your Apify Console — active maintenance is how this Actor keeps working after Otomoto changes its site.