Otomoto.pl Scraper — Polish Auto Classifieds avatar

Otomoto.pl Scraper — Polish Auto Classifieds

Pricing

from $0.60 / 1,000 car listing extracteds

Go to Apify Store
Otomoto.pl Scraper — Polish Auto Classifieds

Otomoto.pl Scraper — Polish Auto Classifieds

Scrape car listings from Otomoto.pl — Poland's largest vehicle marketplace with 240k+ listings. Get price, make, model, year, mileage, fuel type, engine specs, and location.

Pricing

from $0.60 / 1,000 car listing extracteds

Rating

0.0

(0)

Developer

Automation Lab

Automation Lab

Maintained by Community

Actor stats

1

Bookmarked

42

Total users

5

Monthly active users

a month ago

Last modified

Categories

Share

Extract car listings from Otomoto.pl — Poland's largest automotive marketplace with 240,000+ active listings. Get price, make, model, year, mileage, fuel type, engine specs, location, seller type, and more — all in a clean, structured dataset ready for analysis, valuation models, or lead generation.

🚗 What does Otomoto.pl Scraper do?

This actor crawls Otomoto.pl search results and category pages, extracting structured data from every car listing. It uses the site's own Next.js SSR data (embedded in every page), so it is fast, lightweight, and reliable — no browser automation needed.

For each listing it extracts:

  • Car specs: make, model, version/trim, year, mileage, fuel type, transmission, engine capacity, engine power
  • Price: in PLN with currency code
  • Location: city and voivodeship (region)
  • Listing metadata: unique ID, URL, posting date, badges (e.g. LOW_MILEAGE), seller type (private or dealer), thumbnail image
  • Extraction metadata: scrapedAt on every emitted listing
  • Optional detail-page enrichment: fullDescription, photoUrls, equipment, bodyColor, bodyType, doorCount, seatCount, driveType, condition, and firstRegistrationDate

Detail-page enrichment uses only anonymous public pages. It does not collect seller names, phone numbers, email addresses, VINs, login-gated data, or other private fields. Start URLs must use HTTP(S) on otomoto.pl or www.otomoto.pl; credential-bearing and third-party URLs are rejected before fetching. Results are deduplicated by stable listing ID (URL fallback) across every start URL, so maxResults and result charges count unique listings only.

👥 Who is it for?

  • Polish used-car dealers who need to monitor competitor pricing and stock in their region
  • Residual-value analysts and automotive market researchers building pricing models for PLN-denominated assets
  • OEM data teams tracking brand-level inventory levels or model popularity on the secondary market
  • Classified-data aggregators building pan-CEE automotive datasets alongside similar scrapers for Mobile.de, AutoScout24, OLX, and OtoDom
  • PropTech / FinTech analysts who need correlated auto + real-estate data for Polish consumers
  • Individual buyers automating their car search across thousands of listings

✅ Why use it?

  • ⚡ HTTP + Cheerio — no browser, runs in 256 MB, extremely cost-efficient
  • 🔁 Metadata-driven pagination — follows Otomoto's page metadata while preserving every search filter and preventing page loops
  • 🔗 Validated search URLs — paste an HTTP(S) otomoto.pl URL with your own filters already applied
  • 🌍 Polish market coverage — 240,000+ listings across all voivodeships
  • 💰 Structured pricing — price in PLN as a number (not a string), ready for aggregation
  • ✨ Opt-in detail-page enrichment — add descriptions, media, equipment, body/drive/seat/door facts, condition, and first registration only when needed
  • 🛡️ Resilient — bounded retries, optional proxy routing, configurable detail concurrency, and card preservation when an individual detail page fails

📦 Data extracted

FieldTypeExample
idstring"6147784510"
urlstring"https://www.otomoto.pl/osobowe/oferta/kia-picanto-..."
titlestring"Kia Picanto 1.0 ISG Spirit"
shortDescriptionstring"bezwypadkowa, pewny przebieg, kamera"
makestring"Kia"
modelstring"Picanto"
versionstring"1.0 ISG Spirit"
yearnumber2017
mileageKmnumber91000
fuelTypestring"Benzyna"
gearboxstring"Manualna"
engineCapacityCcnumber998
enginePowerHpnumber67
pricePLNnumber27900
priceCurrencystring"PLN"
citystring"Olsztyn"
regionstring"Warmińsko-mazurskie"
badgesarray["LOW_MILEAGE"]
sellerTypestring"ProfessionalSeller"
thumbnailUrlstring"https://ireland.apollo.olxcdn.com/..."
createdAtstring"2026-05-10T08:06:39Z"
scrapedAtstring"2026-09-19T12:00:00.000Z"
fullDescriptionstring or null"Samochód z polskiego salonu..."
photoUrlsarray or null["https://ireland.apollo.olxcdn.com/..."]
equipmentarray or null["Klimatyzacja automatyczna", "Tempomat adaptacyjny ACC"]
bodyColorstring or null"Biały"
bodyTypestring or null"SUV"
doorCountnumber or null5
seatCountnumber or null5
driveTypestring or null"4x4"
conditionstring or null"Używany"
firstRegistrationDatestring or null"2022-03-01"

The detail fields are added when includeDetails is true. Their availability depends on each public listing. A failed detail request keeps the card fields and sets all requested detail fields to null.

How much does it cost to scrape Otomoto.pl listings?

This actor uses Pay-Per-Event pricing — you pay per listing extracted, not for actor runtime. There is a small one-time start fee per run plus a per-result charge.

Typical cost examples:

Use caseResultsEstimated cost
Quick price check50 listings< $0.10
Regional market snapshot500 listings~$0.60
Full category crawl5,000 listings~$5.50
Daily monitoring feed200 listings/day~$0.25/day

New Apify users receive a free-tier credit that covers hundreds of results — enough to evaluate the actor at zero cost.

🚀 How to use it

  1. Open the actor on Apify and click Try for free
  2. Paste a Start URL — copy any search URL from Otomoto.pl (with your filters applied) or use a category shortcut like https://www.otomoto.pl/osobowe/bmw
  3. Set Max Results — start with 20 to test, then increase for production runs
  4. Click Start — results appear in the dataset within seconds

Using Otomoto.pl search filters

The easiest way to apply filters is to use Otomoto.pl's own search UI:

  1. Go to otomoto.pl/osobowe
  2. Select brand, model, price range, year, region, etc.
  3. Copy the URL from your browser's address bar
  4. Paste it as a Start URL in this actor

The actor will walk through every result page for that filter combination.

⚙️ Input parameters

ParameterTypeDefaultDescription
startUrlsarray["https://www.otomoto.pl/osobowe"]One or more Otomoto.pl category or search URLs to scrape
maxResultsinteger50Maximum number of listings to extract across all start URLs
includeDetailsbooleanfalseEnable privacy-safe public detail-page enrichment
detailConcurrencyinteger5Parallel detail requests when enrichment is enabled (1–10)
maxRequestRetriesinteger3Bounded retry attempts for transient search or detail failures (1–10)
proxyConfigurationobjectnoneOptional Apify/custom proxy settings; omitted means direct HTTP. Residential routing is limited to card-only collection.

Residential proxy transfer is supported when includeDetails is false. Detail enrichment performs one additional request per listing, so the Actor rejects the uneconomic RESIDENTIAL + includeDetails: true combination before charging or fetching. Use direct or datacenter routing for enriched results.

Example input

{
"startUrls": [
"https://www.otomoto.pl/osobowe/volkswagen/golf?search%5Bfilter_float_price%3Ato%5D=50000&search%5Bfilter_float_year%3Afrom%5D=2015"
],
"maxResults": 200,
"includeDetails": true,
"detailConcurrency": 5
}

📤 Output

Results are saved to the default Apify dataset. Each item corresponds to one car listing.

Example output item

{
"id": "6147784510",
"url": "https://www.otomoto.pl/osobowe/oferta/kia-picanto-ID6I3tAG.html",
"title": "Kia Picanto 1.0 ISG Spirit",
"shortDescription": "bezwypadkowa, pewny przebieg, kamera, grzana kierownica",
"make": "Kia",
"model": "Picanto",
"version": "1.0 ISG Spirit",
"year": 2017,
"mileageKm": 91000,
"fuelType": "Benzyna",
"gearbox": "Manualna",
"engineCapacityCc": 998,
"enginePowerHp": 67,
"pricePLN": 27900,
"priceCurrency": "PLN",
"city": "Olsztyn",
"region": "Warmińsko-mazurskie",
"badges": [],
"sellerType": "ProfessionalSeller",
"thumbnailUrl": "https://ireland.apollo.olxcdn.com/v1/files/wzwce1kactjz2-OTOMOTOPL/image;s=320x240",
"createdAt": "2026-05-10T08:06:39Z",
"scrapedAt": "2026-09-19T12:00:00.000Z",
"fullDescription": "Samochód z polskiego salonu...",
"photoUrls": ["https://ireland.apollo.olxcdn.com/v1/files/.../image"],
"equipment": ["Klimatyzacja automatyczna", "Tempomat adaptacyjny ACC"],
"bodyColor": "Biały",
"bodyType": "SUV",
"doorCount": 5,
"seatCount": 5,
"driveType": "4x4",
"condition": "Używany",
"firstRegistrationDate": "2022-03-01"
}

💡 Tips & tricks

  • Use multiple start URLs to combine brands or regions in one dataset — overlapping listings are emitted and charged only once
  • Low maxResults for testing — set maxResults: 20 for a quick test, then bump to production volume
  • Filter by voivodeship — use Otomoto.pl's location filter in the search UI and copy the URL to target a specific region
  • Monitor new listings — schedule a daily run with maxResults: 200 and the "Najnowsze" (newest first) sort to capture fresh listings
  • Private vs dealer — filter by sellerType: "PrivateSeller" in your downstream code to target only private sellers (often priced lower)
  • Badges — the badges array can include LOW_MILEAGE, PRICE_DROP, and similar signals useful for deal-finding

🔗 Integrations

Pricing dashboard (Google Sheets)

Schedule a daily run → connect dataset to Google Sheets via the Apify integration → build a pivot table showing average price by make/model/year. Auto-refreshes every morning.

Lead generation CRM (Zapier/Make)

Trigger on new dataset items → filter by sellerType: "PrivateSeller" → push listing URLs and vehicle metadata to HubSpot or another CRM for dealer review. The Actor does not collect seller contact details.

Valuation model (Python + pandas)

import pandas as pd
import requests
dataset_id = "YOUR_DATASET_ID"
token = "YOUR_APIFY_TOKEN"
url = f"https://api.apify.com/v2/datasets/{dataset_id}/items?token={token}&format=json"
df = pd.read_json(url)
# Average price by make and year
pivot = df.groupby(['make', 'year'])['pricePLN'].mean().reset_index()
print(pivot)

Daily price alert (n8n)

Schedule run → compare pricePLN against your threshold → send Slack alert when a listing drops below target price.

🖥️ API usage

Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('automation-lab/otomoto-scraper').call({
startUrls: ['https://www.otomoto.pl/osobowe/bmw'],
maxResults: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("automation-lab/otomoto-scraper").call(run_input={
"startUrls": ["https://www.otomoto.pl/osobowe/bmw"],
"maxResults": 100,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["make"], item["model"], item["pricePLN"])

cURL

curl -X POST "https://api.apify.com/v2/acts/automation-lab~otomoto-scraper/runs?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": ["https://www.otomoto.pl/osobowe/bmw"],
"maxResults": 100
}'

🤖 MCP (Claude / AI assistant integration)

Use this actor directly from Claude Code, Claude Desktop, Cursor, or VS Code with the Apify MCP server.

Claude Code

$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/otomoto-scraper"

Claude Desktop / Cursor / VS Code

Add to your MCP config:

{
"mcpServers": {
"apify": {
"type": "http",
"url": "https://mcp.apify.com?tools=automation-lab/otomoto-scraper",
"headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
}
}
}

Example prompts

  • "Scrape the top 50 BMW listings from Otomoto.pl under 80,000 PLN"
  • "Get all VW Golf listings from 2018–2022 with under 100,000 km and export to CSV"
  • "Monitor new listings on Otomoto.pl in the Mazowieckie region every morning"

⚖️ Legality

Web scraping public data is broadly legal in the EU under CJEU C-30/23. Otomoto.pl's public listing pages are accessible without login and constitute publicly available information. This actor does not extract private user data, bypass authentication, or submit forms.

Users are responsible for complying with Otomoto.pl's Terms of Service and applicable Polish/EU law in their jurisdiction. Do not use this actor to re-publish Otomoto.pl data in a way that competes with their core business.

This independent Actor is not affiliated with, endorsed by, or sponsored by Otomoto. It uses deterministic HTTP parsing and does not call AI models. Results, diagnostics, and logs stay in the user's Apify run storage and follow that account's retention/deletion settings; the Actor keeps no external copy.

❓ FAQ

Q: How many listings can I scrape per run? A: maxResults controls the unique-listing cap. Runtime is also bounded by the Actor's configured timeout, and detail enrichment adds one request per listing. For large collections, split non-overlapping filtered URLs across scheduled runs and choose a limit that fits your timeout.

Q: Does it scrape detail pages (full description, all photos, equipment list)? A: Yes, optionally. Set includeDetails: true to add descriptions, photos, equipment, color, body type, doors, seats, drive, condition, and first-registration date. It is slower because it makes one extra public request per listing. Fields are nullable because not every listing publishes every value, and a failed detail request still returns the valid card record. VIN and seller contacts are not collected.

Q: Are prices in EUR or PLN? A: All prices are extracted in PLN (priceCurrency: "PLN"). Otomoto.pl is a Polish platform and lists in Polish Złoty. Convert to EUR using the current exchange rate in your downstream code.

Q: The actor returned 0 results. What went wrong? A: The Actor rejects malformed, credential-bearing, and non-Otomoto URLs before fetching. A valid category with no matching listings can return an empty dataset; request/parser failures are counted separately, and a run where every search route fails ends non-zero instead of reporting a false-success empty match. Try https://www.otomoto.pl/osobowe first, then add your filters.

Q: Why are fuel types in Polish (e.g. "Benzyna")? A: Otomoto.pl returns fuel types in Polish. "Benzyna" = Petrol/Gasoline, "Diesel" = Diesel, "Hybryda" = Hybrid, "Hybryda Plug-in" = Plug-in Hybrid, "Elektryczny" = Electric, "Benzyna+LPG" = LPG.