Otomoto.pl Scraper With Dealer Contact Leads
Pricing
from $2.99 / 1,000 results
Otomoto.pl Scraper With Dealer Contact Leads
Otomoto.pl Scraper extracts car listings, prices, specifications, mileage, seller details, locations, and other vehicle data from Otomoto.pl. Automate automotive market research, competitor analysis, price tracking, and lead generation with structured data.
Pricing
from $2.99 / 1,000 results
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
1
Bookmarked
1
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Otomoto.pl Scraper — Adverts, Prices and Dealer Contact Leads
Otomoto.pl Scraper With Dealer Contact Leads pulls vehicle adverts from Poland's Otomoto.pl marketplace and attaches the seller behind each one: plaintext phone numbers, dealership name, address, storefront URL, live stock count, working hours and badges. Every row carries id, title, price, mainFeatures, seller, sellerContacts, hasPhone and scrapedAt as structured JSON. Car dealerships building call lists, lead-gen agencies, and market analysts tracking price and stock movement use it to turn a category or brand search into a ready-to-dial dataset. Point it at a category, a brand, or a list of URLs, and it returns clean, typed rows with no manual copy-paste.
What is Otomoto.pl Scraper With Dealer Contact Leads?
It is an Apify Actor that scrapes Otomoto.pl vehicle listing pages and individual advert pages, then resolves each advert's published phone number(s) through Otomoto's own contact endpoint. No Otomoto account, login, or API key is required — the Actor reads only what the public advert page and Otomoto's own keyless phone endpoint publish.
Key features:
- 🔎 Discovery by category, brand, location, price, and year — or paste specific Otomoto listing/advert URLs directly, bypassing search entirely
- ☎️ Plaintext seller phone numbers — resolved live per advert, not looked up or guessed
- 🏢 Server-side dealer / private split —
sellerTypeshrinks the run before a single advert page is fetched, not after - 📇 Full seller outreach record — dealership name, address, storefront URL, live stock count, working hours, and platform badges, all already present on the advert page
- 🧮 One row per advert or one row per seller — collapse every listing from the same business into a single lead
- 📤 Structured JSON output — export to CSV, Excel, JSON, or push straight into a CRM via the Apify API
What data can I extract with Otomoto.pl Scraper With Dealer Contact Leads?
Every advert row carries the vehicle listing fields plus the seller's outreach record, using the exact key names the Actor writes to the dataset.
| Field | Example value | Use case |
|---|---|---|
id | 6149626356 | Unique advert identifier, dedupe key |
type | "advert" | Row kind — "advert" (charged) or "unavailable" (free) |
title | "BMW X5 3.0d xDrive M Sport" | Listing title |
url | "https://www.otomoto.pl/osobowe/oferta/bmw-x5-ID6IbcJS.html" | Canonical advert URL |
price | 189900 | Integer price coercion |
priceList | { "value": "189900", "currency": "PLN" } | Otomoto's own price object (string value preserved) |
mainFeatures | ["2019", "89 000 km", "Diesel"] | Headline specs shown on the listing |
isUsedCar | true | New vs. used flag |
verifiedCar | true | Otomoto's verification badge |
createdAt / updatedAt | "2026-07-28T09:12:00Z" | Publish and last-edit timestamps |
seller | { "id": 15244680, "name": "Auto Studio Kraków", "type": "PROFESSIONAL", ... } | Raw seller block from the advert page |
sellerContacts | see below | Built outreach record |
hasPhone | true | true/false only once the phone endpoint has answered; null if not attempted |
equipment / details / detailsGroups / parametersDict | arrays / objects | Full spec sheet as Otomoto structures it |
category | { "code": "PersonalVehicles", "label": "Osobowe" } | Section the advert sits in |
scrapedAt | "2026-08-04T10:03:11Z" | Run timestamp |
📇 Seller contact leads
sellerContacts is the field that turns a car list into a call list. It is built entirely from data already present on the advert page plus phone numbers walked from Otomoto's own contact endpoint — no third-party lookup, no email guessing. It carries sellerId, sellerType (PROFESSIONAL/PRIVATE), isBusiness, dealerName, phones (array, up to 5 resolved per advert), phoneCount, storefrontUrl, website, addressLine, city, postcode, region, regionSlug, latitude/longitude, listedVehicleCount (the seller's live stock count), workingHours, sellerBadges, and onOtomotoSinceLabel. A sales team can filter on hasPhone and sort dealers by listedVehicleCount to prioritize outreach to high-volume sellers first.
🎯 Targeting data
The fields you filter and segment on are category (section), price/priceList, the production year read from parametersDict, seller.type (dealer vs. private), and sellerContacts.city/region for geographic segmentation. Combined with the input-side sellerType, minPrice/maxPrice, and minProductionYear/maxProductionYear filters, these let you narrow a national category down to a specific brand, price band, region, and seller type before a single row is charged.
How does Otomoto.pl Scraper With Dealer Contact Leads differ from the official Otomoto API?
Otomoto does publish an API, but it is not a public search/read API: its own FAQ states integration is restricted to business clients ("Z integracji API mogą korzystać wyłącznie Klienci biznesowi Otomoto") and requires an API partner-account registration (checked on otomoto.pl/news/faq-api, 2026-08-04). It is built for a dealer to post, manage, and deactivate their own listings — not to search or read other sellers' adverts, and it does not expose a competitor's phone number or contact record. There is no self-serve endpoint for "give me every BMW listing in Kraków with seller contacts."
Why not build this yourself?
Building an equivalent scraper means solving problems this Actor already handles: Otomoto's category slugs move over time (five of the original section paths now 404 and redirect to different slugs), a single-word brand+model query silently returns the entire unfiltered catalogue instead of erroring, sort keys are silently ignored when unrecognized, and a removed advert answers with a valid-looking page that has to be told apart from a genuine block. Add proxy escalation logic, and a bespoke build turns into an ongoing maintenance job. This Actor absorbs that: it validates that Otomoto actually applied the filters requested and fails loudly instead of silently returning the wrong result set, and it starts with no proxy at all, escalating to datacenter and then residential only if it is genuinely blocked.
Use the official API when you manage your own dealer inventory on Otomoto. Use this Actor when you need to read and export other sellers' adverts and contact data at scale.
How to use data extracted from Otomoto.pl?
🏢 Car dealerships and sales teams
Search a brand and region with sellerType: "private" and withPhoneOnly: true to build a call list of individual sellers who might trade in toward a dealer purchase, or run sellerType: "dealer" against a competing region to see what rival lots are stocking and at what price. The sellerContacts.phones, dealerName, and city fields go straight into a dialer or CRM import; hasPhone filters out dead lines before the file ever reaches a rep.
📊 Agencies and lead-generation services
Run the same search on a recurring schedule (Apify Schedules) for multiple clients, using oneRowPerSeller: true to collapse each dealer's full inventory into one row with sellerAdCount and sellerAdIds, so a client-facing report shows "47 dealers with X active listings" rather than raw advert counts.
🔬 Market research and price intelligence
Sweep a category with minPrice/maxPrice and minProductionYear/maxProductionYear bands to build a price distribution by year and mileage (from parametersDict), or compare sellerType: "dealer" vs. "private" volume in a region — the actual search[private_business] split Otomoto applies (measured on /osobowe/bmw: 8,229 dealer vs. 11,372 private adverts out of 19,601 unfiltered, 2026-08-03) to model where private-party supply outweighs dealer stock.
🤖 AI agents and automated pipelines
Because the Actor returns typed JSON with a stable schema, it slots into an agent tool call or RAG pipeline as a "search Otomoto for X, return sellers with phones" function — the agent supplies category, query, and sellerType, and gets back a rectangular dataset it can filter on hasPhone without further parsing.
🔼 Input sample
| Parameter | Required | Type | Description | Example value |
|---|---|---|---|---|
extractSellerContacts | No | boolean | Resolve phone numbers and build the seller outreach record. Default true. When false, sellerContacts, hasPhone, and sellerContactsFetched are all null. | true |
sellerType | No | string (enum: dealer, private, any) | Applied server-side before any advert page is fetched. Default "dealer". Ignored when startUrls is non-empty. | "dealer" |
withPhoneOnly | No | boolean | Drop advert rows where no phone number could be read. Default false. Requires extractSellerContacts: true. | false |
oneRowPerSeller | No | boolean | Collapse every advert from the same seller into one row plus sellerAdIds/sellerAdCount. Default false. | false |
startUrls | No | array | Full Otomoto.pl listing or advert page URLs. Overrides every search filter below, including sellerType. Default []. | [] |
category | No | string (enum, 9 values) | Otomoto section: cars, vans, trucks, motorcycles, trailers, campers, construction, agricultural, parts. Default "cars". | "cars" |
query | No | string | Brand, or brand plus model, space-separated. Default "". | "bmw seria 3" |
location | No | string | Polish town or voivodeship. Default "" (whole country). | "Kraków" |
sort | No | string (enum, 11 values) | Result order. Default "relevance_web". | "created_at:desc" |
minPrice | No | integer, minimum 0 | Minimum price in PLN. | 20000 |
maxPrice | No | integer, minimum 0 | Maximum price in PLN. | 90000 |
minProductionYear | No | integer, min 1900, max 2030 | Earliest production year. | 2018 |
maxProductionYear | No | integer, min 1900, max 2030 | Latest production year. | 2023 |
maxItems | No | integer, min 1, max 100000 | Hard cap on advert detail pages fetched. Default 10. | 200 |
concurrency | No | integer, min 1, max 20 | Parallel requests (advert pages and phone lookups). Default 10. | 10 |
requestDelay | No | integer, min 0, max 30 | Extra pause per request, in seconds, plus jitter. Default 0. | 0 |
proxyConfiguration | No | object | Apify Proxy settings. Default {"useApifyProxy": false}. | {"useApifyProxy": false} |
No input is required — every parameter has a default, and an empty run scrapes the first 10 car adverts by relevance.
{"extractSellerContacts": true,"sellerType": "dealer","withPhoneOnly": false,"oneRowPerSeller": false,"startUrls": [],"category": "cars","query": "bmw seria 3","location": "Kraków","sort": "created_at:desc","minPrice": 20000,"maxPrice": 90000,"minProductionYear": 2018,"maxProductionYear": 2023,"maxItems": 200,"concurrency": 10,"requestDelay": 0,"proxyConfiguration": { "useApifyProxy": false }}
⚠️ Common pitfall: query must be space-separated ("bmw seria 3"), not a single hyphenated word ("bmw-seria-3"). A multi-word query becomes two path segments on Otomoto (/osobowe/bmw/seria-3); a single hyphenated blob is read by Otomoto as one unrecognized token and would silently widen the search to the entire unfiltered catalogue. This Actor checks Otomoto's own applied-filters response and fails the run with the exact rejected word instead of returning an unfiltered result set labeled as your search.
🔽 Output sample
The dataset is typed, normalized JSON with a stable schema across every row — export to CSV, Excel, JSON, or XML directly from the Apify Console, or pull it via the API/apify_client.
{"id": 6149626356,"type": "advert","status": "active","title": "BMW X5 3.0d xDrive M Sport","url": "https://www.otomoto.pl/osobowe/oferta/bmw-x5-ID6IbcJS.html","sourceUrl": "https://www.otomoto.pl/osobowe/oferta/bmw-x5-ID6IbcJS.html","price": 189900,"priceList": {"value": "189900","currency": "PLN","labels": ["Faktura VAT"],"isUnderBudget": false},"primaryImageUrl": "https://ireland.apollo.olxcdn.com/v1/files/example.webp","images": ["https://ireland.apollo.olxcdn.com/v1/files/example.webp"],"createdAt": "2026-07-28T09:12:00Z","originalCreatedAt": "2026-07-20T14:03:00Z","updatedAt": "2026-08-01T11:45:00Z","mainFeatures": ["2019", "89 000 km", "Diesel", "Automatyczna"],"badges": ["LOW_MILEAGE"],"description": "BMW X5 3.0d xDrive M Sport, bezwypadkowy, serwisowany w ASO...","isParts": false,"isUsedCar": true,"verifiedCar": true,"seller": {"id": 15244680,"name": "Auto Studio Kraków","type": "PROFESSIONAL","location": {"address": "ul. Wielicka 12","city": "Kraków","postalCode": "30-552","region": "Małopolskie"},"sellerUrl": "https://www.otomoto.pl/osobowa/auto-studio-krakow","numberOfActiveAds": 47},"packages": ["EXTENDED", "TOP"],"equipment": [{ "code": "air-conditioning", "values": ["automatic"] }],"details": [{ "key": "year", "value": "2019" }],"detailsGroups": [{ "code": "general", "items": ["year", "mileage"] }],"parametersDict": { "year": { "value": "2019" }, "mileage": { "value": "89000" } },"category": { "code": "PersonalVehicles", "id": "29", "label": "Osobowe", "uriPath": "osobowe" },"adFeatures": ["highlighted"],"valueAddedServices": [],"priceDrop": null,"scrapedAt": "2026-08-04T10:03:11Z","sellerContacts": {"sellerId": "15244680","sellerType": "PROFESSIONAL","isBusiness": true,"dealerName": "Auto Studio Kraków","phones": ["12 345 67 89", "600 123 456"],"phoneCount": 2,"storefrontUrl": "https://www.otomoto.pl/osobowa/auto-studio-krakow","website": "https://autostudiokrakow.pl","addressLine": "ul. Wielicka 12","city": "Kraków","postcode": "30-552","region": "Małopolskie","regionSlug": "malopolskie","latitude": 50.0247,"longitude": 19.9645,"listedVehicleCount": 47,"workingHours": { "mon-fri": "9:00-17:00" },"sellerBadges": ["registration-date"],"onOtomotoSinceLabel": "Sprzedający na OTOMOTO od 2015"},"hasPhone": true,"sellerContactsFetched": true}
An advert that was sold or removed before it could be read is pushed as a free, uncharged row instead: type: "unavailable", sourceUrl, httpStatus, unavailableReason: "advert_removed_or_expired", with every contact field null. In oneRowPerSeller mode, the surviving row additionally carries sellerAdIds (all advert IDs merged into it) and sellerAdCount.
How do you filter and target specific adverts?
Category vs. free-text query. category picks the Otomoto section (cars, vans, trucks, motorcycles, trailers, campers, construction, agricultural, parts); query narrows inside it to a brand or brand-plus-model. Use category alone to sweep a whole section, add query when you know the brand.
Scope precision. location (a Polish town or voivodeship — a town uses Otomoto's own catchment radius, a voivodeship is an exact administrative match), minPrice/maxPrice (PLN), and minProductionYear/maxProductionYear narrow the result set before any advert page is fetched.
Quality thresholds. sellerType (dealer/private/any) is applied server-side via Otomoto's own search[private_business] parameter, shrinking the run before a single detail page loads; every returned advert is then re-checked row by row. withPhoneOnly drops rows where no phone number could be resolved.
Volume controls. maxItems (1–100,000, default 10) caps how many advert detail pages are fetched — in oneRowPerSeller mode the dataset can hold fewer rows than this (adverts collapse into sellers) but never more. concurrency (1–20) and requestDelay (0–30s) tune request pacing.
{ "category": "cars", "query": "bmw x5", "location": "Kraków", "sellerType": "dealer", "minProductionYear": 2019, "sort": "created_at:desc", "maxItems": 200 }
{ "category": "cars", "query": "volvo", "sellerType": "private", "withPhoneOnly": true, "oneRowPerSeller": true, "maxItems": 500 }
{ "startUrls": ["https://www.otomoto.pl/dostawcze/kamper", "https://www.otomoto.pl/osobowe/oferta/bmw-x5-ID6IbcJS.html"], "extractSellerContacts": true }
▶️ Want to try other Otomoto scrapers?
This is currently the only Otomoto.pl Actor in the SimpleAPI catalog. If your workflow needs contact-lead extraction from a different platform, these SimpleAPI scrapers cover a similar ground:
| Scraper | What it extracts |
|---|---|
| Google Maps Extractor with Reservation/Order Online Links | Google Maps business listings plus the online booking platform (OpenTable, Resy, SevenRooms, and others) each venue runs on |
| Facebook Group Posts And Details & Contact Leads Scraper | Facebook group posts, group profile data, and email/phone mentions typed by members themselves |
| Pinterest Profile Scraper With Email & Website Contacts | Public Pinterest profile bios plus emails, phone numbers, and social handles from the linked website |
| TikTok Shop Data Scraper: Reviews & Sentiment Analysis | TikTok Shop products, reviews, and reviewer trust signals by keyword, category, or seller store |
How to extract Otomoto.pl data programmatically
Every run is a standard Apify Actor call: one API call with your Apify token, a JSON input body, and structured JSON back — no separate Otomoto credentials required.
Python example
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("SimpleAPI/otomoto-pl-scraper-with-dealer-contact-leads").call(run_input={"category": "cars","query": "bmw seria 3","location": "Kraków","sellerType": "dealer","withPhoneOnly": True,"maxItems": 100,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():contacts = item.get("sellerContacts") or {}print(item["title"], item["price"], contacts.get("phones"))
Export to spreadsheets or CRM
From the Apify Console, use the dataset's Export button to download CSV or Excel directly, or select the ☎️ Adverts + seller contacts view for a flattened table. Map title, price, and the sellerContacts.dealerName/phones/city keys to your CRM's lead columns — hasPhone gives you a ready-made filter for a "call-ready" segment before import.
⚖️ Is it legal to scrape Otomoto.pl?
Scraping publicly accessible Otomoto.pl advert pages is generally lawful — these listings are published specifically to be found and contacted by buyers, and this Actor reads only what a visitor to the public page (and Otomoto's own public contact endpoint) can already see. No login, cookie, or bypass of access controls is used.
The legal framing depends on which rows you collect. With sellerType: "dealer" (the default), output is business/dealership data — dealership name, storefront, and stock count — governed by Otomoto's Terms of Service and database-rights considerations, not personal-data law. With sellerType: "private" or "any", dealerName and phones can identify an individual rather than a business; that output is personal data and falls under GDPR (and CCPA where applicable), which requires a lawful basis for storage and further use. Consult legal counsel for commercial applications involving bulk storage of personal data.
❓ FAQ
Do sold or removed adverts still show up in the results?
Yes, but as a free, uncharged row rather than being silently dropped: type: "unavailable", with httpStatus and unavailableReason: "advert_removed_or_expired". Every contact field on that row is null because nothing was ever fetched for it.
Can I get seller phone numbers along with the advert data?
Yes — it's the Actor's core feature. With extractSellerContacts: true (the default), each advert's published phone numbers are resolved live from Otomoto's own contact endpoint (up to 5 per advert) and attached in sellerContacts.phones, alongside dealership name, address, storefront URL, live stock count, working hours, and badges. hasPhone and sellerContactsFetched tell you whether a number was actually found versus whether the lookup was even attempted.
How accurate is the phone and price data?
The Actor returns data exactly as Otomoto publishes it at request time — the phone number is read live from Otomoto's own endpoint, not guessed or completed from another source, and price/priceList reflect the advert's current listed price. Accuracy depends on the seller keeping the ad updated; re-run periodically if you need current stock and pricing.
How many adverts can I get per run?
maxItems caps the number of advert detail pages fetched, from 1 up to 100,000 (default 10). In oneRowPerSeller mode, the pushed dataset can hold fewer rows than maxItems because multiple adverts collapse into one seller row — it never holds more.
How do I target only dealerships, or only sellers I can actually call?
Use sellerType: "dealer" (or "private") to apply Otomoto's own business/private split server-side, before any advert page is fetched, and add withPhoneOnly: true to drop rows where no phone number could be resolved. Combine both with oneRowPerSeller: true to get one qualified lead per business instead of one row per listing.
Does Otomoto.pl Scraper With Dealer Contact Leads work with Claude, ChatGPT, and AI agent frameworks?
There is no dedicated MCP server for this Actor. It is callable as a standard HTTP endpoint through the Apify API by any agent framework that can make a tool call and read JSON — LangChain, LlamaIndex, or a custom agent loop can all invoke it as a scraping tool.
How does this compare to other Otomoto scrapers?
The distinguishing capability, verifiable from this Actor's own source and input schema, is the combination of plaintext phone-number resolution, the server-side dealer/private split, and the one-row-per-seller collapse in a single run. Check any other Otomoto listing's own documentation for its specific field coverage before comparing on price or speed.
Can I use this without an Otomoto account or API key?
Yes. You need only an Apify account and API token to run it — no Otomoto login, cookie, or API key of any kind is required, since the Actor reads public pages and Otomoto's own keyless contact endpoint.
What happens if my search matches zero adverts?
The run fails with a clear error naming the problem — Otomoto reporting zero total results, or Otomoto not actually applying a filter you asked for (an unrecognized brand, model, or location) — rather than silently returning an empty or wrongly-scoped dataset labeled as a success.
Conclusion
Otomoto.pl Scraper With Dealer Contact Leads turns an Otomoto category or brand search into a structured, contactable dataset: vehicle listing details plus plaintext seller phone numbers, dealership name, address, and live stock count, filterable by dealer/private split and phone availability. It's built for sales teams, lead-gen agencies, and market analysts who need Otomoto data as clean JSON rather than a spreadsheet built by hand. Start a run from the Apify Console or the API with your search filters, or paste Otomoto URLs directly, and open the ☎️ Adverts + seller contacts view when it finishes.