Otomoto.pl Scraper By Mileage, Fuel & Gearbox avatar

Otomoto.pl Scraper By Mileage, Fuel & Gearbox

Pricing

from $5.99 / 1,000 results

Go to Apify Store
Otomoto.pl Scraper By Mileage, Fuel & Gearbox

Otomoto.pl Scraper By Mileage, Fuel & Gearbox

Otomoto.pl Scraper by Mileage, Fuel & Gearbox extracts vehicle listings from Otomoto.pl using mileage, fuel type, and gearbox filters. Collect prices, specs, seller details, locations, and car data for market research, price tracking, competitor analysis, and lead generation.

Pricing

from $5.99 / 1,000 results

Rating

0.0

(0)

Developer

Scrapier

Scrapier

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Share

Otomoto.pl Scraper — Filter Car Adverts by Mileage, Fuel & Gearbox

Otomoto.pl Scraper By Mileage, Fuel & Gearbox pulls vehicle adverts from Otomoto.pl, Poland's largest car marketplace, and narrows them with Otomoto's own mechanical-spec filters — odometer band, fuel, gearbox, engine power, body shape, capacity, doors, seats and drive — applied server-side before a single advert page is fetched. Every response is structured JSON: the full advert record plus flat, typed spec columns, ready to sort in a spreadsheet, feed into a pricing model, or pass straight to an LLM. Point it at a brand, a pasted Otomoto URL, or a spec band, and it returns adverts that already match.

What is Otomoto.pl Scraper By Mileage, Fuel & Gearbox?

It is a search-and-detail scraper for Otomoto.pl: give it a category, an optional brand/model and location, and up to twenty vehicle-spec filters, and it walks Otomoto's own listing pages, opens every matching advert, and returns one row per advert. What sets it apart from a plain brand/price/year search is that the odometer, fuel, gearbox, engine power, body, capacity, door, seat and drive filters are sent to Otomoto as real search[...] query parameters and applied on Otomoto's own servers — so a narrow spec makes the run cheaper, not slower, because the detail-page fan-out only touches adverts that already match. No Otomoto account or login is required; the Actor reads the same public pages a browser would.

Key capabilities:

  • Odometer (mileage) band search, in kilometres, as a real Otomoto server-side filter
  • Fuel and gearbox multi-select filters, returning the union of the values picked
  • Engine power, engine capacity, door count, minimum seats and drive-type filters
  • Full-text brand/model search plus town or voivodeship location targeting
  • Eleven sort orders, several of them Otomoto's own server-side keys
  • A startUrls mode that accepts pasted listing or single-advert URLs and skips the filter form entirely

What data can you get with Otomoto.pl Scraper By Mileage, Fuel & Gearbox?

Every run returns vehicle adverts as JSON, each carrying the full Otomoto advert record, a flattened mechanical-spec block, pricing detail, seller information, and a filter audit trail.

Result typeExtracted fieldsPrimary use case
Vehicle advertid, type, status, title, url, sourceUrl, primaryImageUrl, images, createdAt, originalCreatedAt, updatedAt, mainFeatures, badges, description, isParts, isUsedCar, verifiedCar, category, adFeatures, valueAddedServices, scrapedAtBuilding a sourcing shortlist or a catalogue feed
Mechanical spec (flat)mileageKm, fuelTypeCode, fuelTypeLabel, gearboxCode, transmissionLabel, enginePowerKM, engineCapacityCcm, bodyTypeCode, bodyTypeLabel, doorCount, seatCount, driveTypeSorting and pivoting stock in a spreadsheet without unpacking a dictionary
Pricingprice, priceList, priceDropPrice-vs-mileage regression, price-drop tracking
Sellerseller, packagesIdentifying dealer vs. private-seller stock
Equipment and raw parametersequipment, details, detailsGroups, parametersDictFeature-level filtering beyond the flat spec columns
Filter auditvehicleFiltersAppliedProving which filters actually reached Otomoto and how many adverts it declared
Unavailable advert (free row)type, sourceUrl, httpStatus, unavailableReason, scrapedAtTracking sold or delisted stock without losing the URL

Server-side mechanical-spec filters and flat spec columns

This is the capability the base Otomoto scraper does not have: nine additional vehicle-spec filters — odometer band, fuel, gearbox, engine power, body shape, engine capacity, door count, minimum seats and drive type — sent to Otomoto as real search[filter_float_mileage:from], search[filter_enum_fuel_type], search[filter_enum_gearbox] and similar parameters, so Otomoto itself discards non-matching adverts before the Actor ever opens a detail page. Every advert also comes back with the same spec lifted onto flat, typed top-level columns instead of a nested parametersDict a user would otherwise have to unpack. A value that Otomoto's own advert omits is null, never 0 and never an empty string, so a missing spec never masquerades as a real measurement. A vehicleFiltersApplied object on every row records what was requested, the exact query parameters sent, and the filter names and advert count Otomoto echoed back:

{
"mileageKm": 118500,
"fuelTypeCode": "diesel",
"fuelTypeLabel": "Diesel",
"gearboxCode": "manual",
"transmissionLabel": "Manualna",
"enginePowerKM": 190,
"engineCapacityCcm": 1995,
"bodyTypeCode": "combi",
"bodyTypeLabel": "Kombi",
"doorCount": 5,
"seatCount": 5,
"driveType": "rear-wheel",
"vehicleFiltersApplied": {
"searchMode": "search",
"requested": { "maxMileage": 120000, "fuelType": ["diesel"], "transmission": ["manual"] },
"otomotoQueryParams": [
{ "key": "search[filter_float_mileage:to]", "value": "120000" },
{ "key": "search[filter_enum_fuel_type]", "value": "diesel" },
{ "key": "search[filter_enum_gearbox]", "value": "manual" }
],
"otomotoAppliedFilters": ["filter_float_mileage:to", "filter_enum_fuel_type", "filter_enum_gearbox"],
"otomotoTotalCount": 4745,
"ignoredBecauseStartUrlsWereUsed": null
}
}

Unavailable adverts as free accounting rows

An advert that was sold or removed between discovery and the detail fetch does not silently disappear from the run. It comes back as a row with type: "unavailable", httpStatus (typically 404 or 410) and unavailableReason: "advert_removed_or_expired", and this row is never charged. Filter it out of downstream processing with row["type"] != "unavailable"; keep it if the workflow needs to know what left the market.

Why not build this yourself?

Otomoto.pl has no public search or listings API — every field this Actor returns has to come from parsing the __NEXT_DATA__ JSON payload Otomoto's own Next.js frontend embeds in each server-rendered page, and that payload's shape, its filter parameter names, and its category slugs move over time (several of the base scraper's original category slugs now 404 and redirect to renamed sections). A DIY script also has to work out, by trial and error, which sort keys Otomoto's server actually honours versus which ones it silently ignores, which HTTP statuses mean "this advert is gone" versus "we are being blocked," and how far to escalate proxies before giving up. This Actor already encodes those findings — measured directly against the live site — plus a per-URL retry budget and an automatic none → datacenter → residential proxy ladder, so a scraping project starts from a working baseline instead of a blank HTTP client.

How to scrape Otomoto.pl with Otomoto.pl Scraper By Mileage, Fuel & Gearbox?

  1. Open Otomoto.pl Scraper By Mileage, Fuel & Gearbox on the Apify Store and click Try for free (or find it in your Apify Console if you already use it).
  2. Enter a brand in query (e.g. bmw, or bmw seria 3 for a model), or leave it blank to search a whole category. Optionally add a location (Polish town or voivodeship).
  3. Set the vehicle-spec filters that matter for the search — minMileage/maxMileage, fuelType, transmission, minEnginePower/maxEnginePower, bodyType, minEngineCapacity/maxEngineCapacity, doorCount, minSeats, driveType — or paste ready-made Otomoto URLs into startUrls instead.
  4. Set maxItems and click Start.
  5. Open the Dataset tab when the run finishes and export the results as JSON, CSV, Excel, or any other format Apify's dataset export supports.

How to run multiple queries in one job

startUrls accepts an array, so a single run can mix several already-built Otomoto listing URLs and single-advert URLs — each listing URL is walked for its own matching adverts, up to the shared maxItems budget, and duplicate advert URLs across entries are collected only once. There is no separate keyword-list input for the filter-form mode: to run several distinct brand/spec combinations, either build one Start URL per combination or run the Actor once per combination. concurrency (default 10, maximum 20) controls how many Otomoto pages this run fetches in parallel.

⬇️ Input

Nothing is required. Either paste one or more Otomoto URLs into startUrls, or leave it empty and build a search from category, query, location and the vehicle-spec fields below. When startUrls is non-empty it overrides every other filter, and the run log names each filter it had to ignore.

ParameterRequiredTypeDefault / constraintsDescription
startUrlsNoarray of stringsdefault []Full Otomoto.pl listing or single-advert URLs. Overrides every filter below.
categoryNostring (enum)default "cars"Otomoto section: cars, vans, trucks, motorcycles, trailers, campers, construction, agricultural, parts.
queryNostringdefault ""Brand, or brand plus model separated by a space, in Otomoto's own Polish naming (e.g. bmw seria 3).
locationNostringdefault ""Polish town or voivodeship name.
sortNostring (enum)default "relevance_web"Result order — see the sort table below.
maxItemsNointegerdefault 10; min 1; max 100000Hard cap on charged advert rows.
minPriceNointegermin 0Minimum price in PLN.
maxPriceNointegermin 0Maximum price in PLN.
minProductionYearNointegermin 1900; max 2030Earliest production year.
maxProductionYearNointegermin 1900; max 2030Latest production year.
minMileageNointegermin 0Lowest odometer reading (km) to accept.
maxMileageNointegermin 0Highest odometer reading (km) to accept.
fuelTypeNoarray of strings (enum)default []One or more of: petrol, diesel, petrol-lpg, petrol-cng, hybrid, plugin-hybrid, electric, etanol, hidrogen. Union of picks.
transmissionNoarray of strings (enum)default []Gearbox: manual, automatic.
minEnginePowerNointegermin 0Lowest engine power to accept, in KM (Polish metric horsepower).
maxEnginePowerNointegermin 0Highest engine power to accept, in KM.
bodyTypeNoarray of strings (enum)default []One or more of: sedan, combi, compact, suv, coupe, cabrio, minivan, city-car, mini. Union of picks.
minEngineCapacityNointegermin 0Smallest engine displacement (cm³) to accept.
maxEngineCapacityNointegermin 0Largest engine displacement (cm³) to accept.
doorCountNoarray of strings (enum)default []One or more of: 2, 3, 4, 5, 6. Union of picks.
minSeatsNointegermin 0Minimum number of seats.
driveTypeNoarray of strings (enum)default []One or more of: front-wheel, rear-wheel, all-wheel-permanent, all-wheel-auto, all-wheel-lock. Union of picks.
concurrencyNointegerdefault 10; min 1; max 20Parallel Otomoto page requests.
requestDelayNointegerdefault 0; min 0; max 30Extra pause before each request, in seconds, plus a small random jitter.
proxyConfigurationNoobjectdefault {"useApifyProxy": false}Apify Proxy settings. Default is no proxy; the Actor escalates to datacenter, then residential, automatically if Otomoto blocks it.

Sort values: relevance_web (default, real server key), created_at:desc (newest first, real server key), created_at:asc (oldest first, applied client-side over the rows this run collected — Otomoto has no server-side key for it), price:asc / price:desc (remapped server-side to filter_float_price:asc/:desc, Otomoto's own working price keys), year:desc / year:asc (applied client-side, no server-side year sort exists), filter_float_price:asc / filter_float_price:desc (Otomoto's own price keys), filter_float_mileage:asc (Otomoto's own mileage-ascending key), created_at_first:desc (first-published, newest first).

{
"category": "cars",
"query": "bmw",
"maxMileage": 120000,
"fuelType": ["diesel"],
"transmission": ["manual"],
"bodyType": ["combi"],
"minEnginePower": 150,
"maxEnginePower": 190,
"sort": "filter_float_mileage:asc",
"maxItems": 25
}

Common pitfall: fuelType, transmission, bodyType, doorCount and driveType are multi-select fields that expect one value per list entry. A comma-joined value such as "diesel,electric" in a single string is not the same input — Otomoto's own server answers that exact string with HTTP 200 and zero adverts, which looks identical to "no car matches," so the Actor rejects a comma inside a value loudly before the run starts rather than returning a silently empty result.

⬆️ Output

Results are pushed to the Actor's default dataset as typed, normalized JSON — one object per row, one row per advert (plus one uncharged row per advert that could not be reached). The schema is consistent across runs: every key listed below is present on every row, null where Otomoto's own advert does not carry that value. Download the dataset as JSON, CSV, Excel, XML, RSS or HTML directly from the Apify Console, or pull it with the API or apify_client.

Scraped results

[
{
"id": "6WAaFhQ2",
"type": "advert",
"status": "active",
"title": "BMW Seria 3 320d Kombi FV23% Serwisowany",
"url": "https://www.otomoto.pl/osobowe/oferta/bmw-seria-3-320d-kombi-ID6WAaFhQ2.html",
"sourceUrl": "https://www.otomoto.pl/osobowe/oferta/bmw-seria-3-320d-kombi-ID6WAaFhQ2.html",
"price": 78900,
"priceList": { "value": "78900", "currency": "PLN", "labels": null, "isUnderBudget": false },
"primaryImageUrl": "https://ireland.apollo.olxcdn.com/v1/files/example1.webp",
"images": [
"https://ireland.apollo.olxcdn.com/v1/files/example1.webp",
"https://ireland.apollo.olxcdn.com/v1/files/example2.webp"
],
"createdAt": "2026-07-29T09:12:04Z",
"originalCreatedAt": "2026-07-15T11:03:22Z",
"updatedAt": "2026-08-02T18:40:11Z",
"mainFeatures": ["Serwisowany w ASO", "Bezwypadkowy", "Pierwszy właściciel"],
"badges": ["LOW_MILEAGE"],
"description": "Do sprzedania BMW Seria 3 320d Kombi, stan bardzo dobry...",
"isParts": false,
"isUsedCar": true,
"verifiedCar": true,
"seller": { "id": "9182734", "type": "PRIVATE", "name": "Marek", "phone": "+48600000000" },
"packages": ["STANDARD"],
"equipment": ["klimatyzacja", "tempomat", "czujniki-parkowania"],
"details": [{ "key": "mileage", "value": "118500" }],
"detailsGroups": ["Wyposażenie", "Osiągi"],
"parametersDict": {
"mileage": { "label": "mileage", "values": [{ "value": "118500", "label": "118 500 km" }] },
"fuel_type": { "label": "fuel_type", "values": [{ "value": "diesel", "label": "Diesel" }] }
},
"category": { "code": "PERSONAL", "id": "29", "label": "Osobowe", "uriPath": "osobowe" },
"adFeatures": null,
"valueAddedServices": null,
"priceDrop": null,
"scrapedAt": "2026-08-04T10:15:02Z",
"mileageKm": 118500,
"fuelTypeCode": "diesel",
"fuelTypeLabel": "Diesel",
"gearboxCode": "manual",
"transmissionLabel": "Manualna",
"enginePowerKM": 190,
"engineCapacityCcm": 1995,
"bodyTypeCode": "combi",
"bodyTypeLabel": "Kombi",
"doorCount": 5,
"seatCount": 5,
"driveType": "rear-wheel",
"vehicleFiltersApplied": {
"searchMode": "search",
"requested": { "maxMileage": 120000, "fuelType": ["diesel"], "transmission": ["manual"] },
"otomotoQueryParams": [{ "key": "search[filter_float_mileage:to]", "value": "120000" }],
"otomotoAppliedFilters": ["filter_float_mileage:to", "filter_enum_fuel_type", "filter_enum_gearbox"],
"otomotoTotalCount": 4745,
"ignoredBecauseStartUrlsWereUsed": null
}
},
{
"id": "4RtE9k1L",
"type": "advert",
"status": "active",
"title": "BMW 320d Touring Automatyczna Skoda 2020",
"url": "https://www.otomoto.pl/osobowe/oferta/bmw-320d-touring-ID4RtE9k1L.html",
"sourceUrl": "https://www.otomoto.pl/osobowe/oferta/bmw-320d-touring-ID4RtE9k1L.html",
"price": 92500,
"priceList": { "value": "92500", "currency": "PLN", "labels": null, "isUnderBudget": true },
"primaryImageUrl": "https://ireland.apollo.olxcdn.com/v1/files/example3.webp",
"images": ["https://ireland.apollo.olxcdn.com/v1/files/example3.webp"],
"createdAt": "2026-07-30T14:02:00Z",
"originalCreatedAt": "2026-07-30T14:02:00Z",
"updatedAt": "2026-07-30T14:02:00Z",
"mainFeatures": ["Faktura VAT"],
"badges": null,
"description": "BMW 320d Touring, automat, salon Polska.",
"isParts": false,
"isUsedCar": true,
"verifiedCar": false,
"seller": { "id": "5561234", "type": "DEALER", "name": "Auto-Handel Kowalski", "phone": "+48700000000" },
"packages": ["EXTENDED", "TOP"],
"equipment": ["nawigacja", "podgrzewane-fotele"],
"details": [{ "key": "mileage", "value": "89200" }],
"detailsGroups": ["Wyposażenie"],
"parametersDict": {
"mileage": { "label": "mileage", "values": [{ "value": "89200", "label": "89 200 km" }] }
},
"category": { "code": "PERSONAL", "id": "29", "label": "Osobowe", "uriPath": "osobowe" },
"adFeatures": null,
"valueAddedServices": ["HIGHLIGHT"],
"priceDrop": { "amount": 2500, "percentage": 3 },
"scrapedAt": "2026-08-04T10:15:07Z",
"mileageKm": 89200,
"fuelTypeCode": "diesel",
"fuelTypeLabel": "Diesel",
"gearboxCode": "manual",
"transmissionLabel": "Manualna",
"enginePowerKM": 190,
"engineCapacityCcm": 1995,
"bodyTypeCode": "combi",
"bodyTypeLabel": "Kombi",
"doorCount": 5,
"seatCount": null,
"driveType": null,
"vehicleFiltersApplied": {
"searchMode": "search",
"requested": { "maxMileage": 120000, "fuelType": ["diesel"], "transmission": ["manual"] },
"otomotoQueryParams": [{ "key": "search[filter_float_mileage:to]", "value": "120000" }],
"otomotoAppliedFilters": ["filter_float_mileage:to", "filter_enum_fuel_type", "filter_enum_gearbox"],
"otomotoTotalCount": 4745,
"ignoredBecauseStartUrlsWereUsed": null
}
},
{
"id": null,
"type": "unavailable",
"status": null,
"title": null,
"url": "https://www.otomoto.pl/osobowe/oferta/bmw-320d-sold-IDzzZZ9999.html",
"sourceUrl": "https://www.otomoto.pl/osobowe/oferta/bmw-320d-sold-IDzzZZ9999.html",
"price": null,
"priceList": null,
"primaryImageUrl": null,
"images": null,
"createdAt": null,
"originalCreatedAt": null,
"updatedAt": null,
"mainFeatures": null,
"badges": null,
"description": null,
"isParts": null,
"isUsedCar": null,
"verifiedCar": null,
"seller": null,
"packages": null,
"equipment": null,
"details": null,
"detailsGroups": null,
"parametersDict": null,
"category": null,
"adFeatures": null,
"valueAddedServices": null,
"priceDrop": null,
"httpStatus": 410,
"unavailableReason": "advert_removed_or_expired",
"scrapedAt": "2026-08-04T10:15:09Z",
"mileageKm": null,
"fuelTypeCode": null,
"fuelTypeLabel": null,
"gearboxCode": null,
"transmissionLabel": null,
"enginePowerKM": null,
"engineCapacityCcm": null,
"bodyTypeCode": null,
"bodyTypeLabel": null,
"doorCount": null,
"seatCount": null,
"driveType": null,
"vehicleFiltersApplied": {
"searchMode": "search",
"requested": { "maxMileage": 120000, "fuelType": ["diesel"], "transmission": ["manual"] },
"otomotoQueryParams": [{ "key": "search[filter_float_mileage:to]", "value": "120000" }],
"otomotoAppliedFilters": ["filter_float_mileage:to", "filter_enum_fuel_type", "filter_enum_gearbox"],
"otomotoTotalCount": 4745,
"ignoredBecauseStartUrlsWereUsed": null
}
}
]

type: "unavailable" rows are pushed uncharged (no row_result event); only type: "advert" rows are billed. Exclude the free rows from downstream processing with a filter such as item["type"] == "advert".

How can I use the data extracted with Otomoto.pl Scraper By Mileage, Fuel & Gearbox?

  • Used-car sourcing and procurement teams: filter by maxMileage, fuelType, transmission and bodyType to build a buy list of exactly the spec a trade partner or export order needs, without manually reading hundreds of adverts.
  • Insurance and risk analysts: set a hard maxEnginePower ceiling to pull the stock segment that sits under a young-driver or fleet policy's power threshold, using the engine-power band Otomoto itself filters on.
  • Market researchers: export price, mileageKm, enginePowerKM and engineCapacityCcm together to regress price against mechanical condition across a brand or region.
  • AI engineers and LLM developers: issue a query with the vehicle-spec filters as parameters, receive structured JSON back, and pass the advert and spec fields to a model as grounded context for a pricing or recommendation agent.

How do you monitor vehicle adverts over time?

Otomoto adverts change: prices drop, odometer readings climb as sellers re-list, and stock disappears when a car sells. Running this Actor on a schedule against the same search or the same startUrls list turns a single snapshot into a monitoring feed. Compare two runs and diff price and priceDrop for markdown alerts, mileageKm for a re-listing with a suspiciously changed odometer, status and the presence of a type: "unavailable" row for stock that left the market, and updatedAt to confirm whether an advert was genuinely refreshed or is just sitting unsold. Because the vehicle-spec filters are applied by Otomoto itself before any detail page is fetched, a scheduled monitoring run over a narrow spec band (say, diesel manual estates under 120,000 km) stays cheap even at daily frequency, since Otomoto discards the rest of the catalogue before the Actor spends a single detail-page request on it.

A practical loop: schedule a run once or twice a day against a saved search or startUrls list, keep the previous run's dataset, and alert when a tracked advert's price drops, its mileageKm moves in a way inconsistent with normal use, or it flips to type: "unavailable". Set this up with Apify's built-in Schedule feature on the Actor, or trigger runs externally with apify_client and diff the resulting datasets yourself.

Integrate Otomoto.pl Scraper By Mileage, Fuel & Gearbox and automate your workflow

Otomoto.pl Scraper By Mileage, Fuel & Gearbox works with any language or tool that can call the Apify API, so it drops into an existing pipeline the same way any other Apify Actor does.

REST API with Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_API_TOKEN>")
run = client.actor("YOUR_USERNAME/otomoto-pl-scraper-by-mileage-fuel-and-gearbox").call(
run_input={
"category": "cars",
"query": "bmw",
"maxMileage": 120000,
"fuelType": ["diesel"],
"transmission": ["manual"],
"maxItems": 50,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["type"] == "advert":
print(item["title"], item["price"], item["mileageKm"])

Scheduled monitoring and delivery

The Actor has no built-in webhook of its own, but Apify's platform-level features cover both ends of a monitoring pipeline: attach an Apify Schedule to run it on a recurring basis, and attach an Apify webhook on the run's ACTOR.RUN.SUCCEEDED event to notify another system, or simply poll the dataset with apify_client after each scheduled run.

Yes — Otomoto.pl's adverts are publicly accessible pages that any visitor can browse without logging in, and this Actor returns only what a browser already renders. This Actor collects vehicle listings, prices and mechanical specifications — product-catalogue data, not personal profiles — so the framework that applies is Otomoto's own Terms of Service and the database-rights law of the jurisdiction you operate from, not GDPR; scraping a product catalogue does not by itself trigger GDPR obligations. The one exception is the seller field: when a seller is a private individual rather than a dealer, that record can carry a name and phone number, which is personal data under GDPR/CCPA regardless of the rest of the row — handle exported seller fields with the same care as any other personal contact list. One-off research and repeated operational monitoring carry different risk profiles at scale. Consult your legal team for commercial use cases involving bulk data storage.

Frequently asked questions

Can I search by Polish town or voivodeship?

Yes. location accepts a Polish town (e.g. Warszawa, Kraków) or a voivodeship (e.g. Małopolskie). A town search uses Otomoto's own catchment radius around that town, so nearby localities are included; a voivodeship is an exact administrative match. An unresolvable name fails the run rather than silently returning national results.

How do I sort results by mileage or price?

Use the sort parameter. filter_float_mileage:asc and the two filter_float_price values are real Otomoto server-side keys. year:desc, year:asc and created_at:asc have no server-side equivalent on Otomoto and are instead applied client-side over the rows this run actually collected, not the site's whole result set — the run log states which mode was used for the sort you picked.

How does this Actor handle Otomoto's anti-bot measures?

It starts every run with no proxy (Otomoto has not been observed to block a direct Apify container exit), and escalates automatically through datacenter and then residential proxy tiers, sticking at the higher tier once reached, if it is genuinely blocked. Each URL gets its own retry budget of three attempts before escalation, and a sold or removed advert (HTTP 404/410) is classified as gone rather than as a block, so one dead ad cannot burn the retry budget or force an unnecessary proxy upgrade.

Does this Actor filter adverts by mileage, fuel and gearbox?

Yes. minMileage/maxMileage map to Otomoto's search[filter_float_mileage:from/:to], fuelType maps to search[filter_enum_fuel_type], and transmission maps to search[filter_enum_gearbox] — all applied on Otomoto's own servers. The same spec also comes back on every row as mileageKm, fuelTypeCode/fuelTypeLabel and gearboxCode/transmissionLabel.

How many adverts does this Actor return per query?

Up to maxItems (default 10, maximum 100000) charged advert rows, or fewer if Otomoto's own result set — recorded in vehicleFiltersApplied.otomotoTotalCount — is smaller. A narrow spec combination (diesel, manual, estate, under 120,000 km) legitimately returns far fewer adverts than a broad one; a short result set is not a sign the run failed.

What happens to a sold or removed advert mid-run?

It is returned as a free, uncharged accounting row with type: "unavailable", the HTTP status Otomoto answered with, and unavailableReason: "advert_removed_or_expired" — it never silently disappears from the dataset, and it is never billed.

What happens if I search for a brand or model Otomoto doesn't recognise?

The run fails and names the exact word Otomoto rejected, rather than returning a result. Otomoto itself answers an unknown brand or model with HTTP 200 and the entire unfiltered catalogue, so treating that as a valid result would silently hand back the wrong data; this Actor checks Otomoto's own applied-filter echo and fails loudly instead.

How do I monitor mileage and price changes on the same adverts over time?

Run the Actor on an Apify Schedule against the same search or startUrls list, keep each run's dataset, and diff price, priceDrop, mileageKm and status between runs; a flip to type: "unavailable" means the advert left the market.

Does this work with Claude, ChatGPT and other AI agent frameworks?

It is callable as an HTTP endpoint through the Apify API or apify_client by any agent framework capable of making an API call, which lets an agent issue a query, receive structured JSON back, and ground its answer in current Otomoto listings. There is no dedicated MCP server documented for this Actor.

Can I use this without managing proxies or an Otomoto account?

Yes. No Otomoto login is ever required, and the default proxyConfiguration runs with no proxy at all, escalating automatically only if Otomoto genuinely blocks the run. You only need an Apify account and, for programmatic use, an Apify API token.

Your feedback

Found a bug, or a field Otomoto added that this Actor doesn't surface yet? Open an issue from the Actor's page in Apify Console (the Issues tab) or reach out through the Scrapier publisher profile on the Apify Store — reports like these are what keep the vehicle-spec vocabulary current as Otomoto changes its own filters.