# Otomoto.pl Scraper (`redomic/otomoto-scraper`) Actor

Scrape Otomoto.pl Polish car listings: one run returns used-car rows with price, make, model, year, mileage, fuel, gearbox, seller and URL. Detail mode adds description, photos, equipment, VIN and CEPiK history; monitor mode tracks new, price-changed and removed cars.

- **URL**: https://apify.com/redomic/otomoto-scraper.md
- **Developed by:** [Redomic](https://apify.com/redomic) (community)
- **Categories:** E-commerce, Lead generation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Otomoto.pl Scraper: Polish Car Listings, Prices and Price Drops

Export car listings from Otomoto.pl, Poland's largest car marketplace, to a spreadsheet or an API. Each row is one car: price in PLN, make, model, year, mileage, engine, fuel, gearbox, location and seller. Paste a search URL from otomoto.pl or set a few filters, and the first results arrive in about 30 seconds.

Schedule it in monitor mode and each run returns only the cars that are new, cheaper or gone since the last run.

### Who uses it

- **Dealers and importers** who want to know what a model sells for in Poland before they buy or price stock.
- **Analysts** building price and depreciation data by model, year and mileage.
- **Dealers watching a competitor.** Point it at a rival's Otomoto inventory page and get their new stock and price cuts every morning.

### What you get

A run with the default input (BMW, detail mode) on 15 November 2026 returned these cars, among others:

| Car | Price (PLN) | Year | Mileage (km) | Fuel | Power (hp) | City | Seller |
|---|---|---|---|---|---|---|---|
| BMW Seria 3 330i M Sport Shadow | 46,999 | 2018 | 74,000 | petrol | 252 | Warszawa | dealer |
| BMW Seria 5 530e PHEV | 73,677 | 2023 | 54,622 | plug-in hybrid | 299 | Warszawa | private |
| BMW X3 xDrive30i Luxury Line | 97,000 | 2020 | 49,597 | petrol | 252 | Bielsk Podlaski | private |
| BMW Seria 7 740i sport | 54,900 | 2019 | 115,000 | petrol | 340 | Warszawa | dealer |
| BMW iX3 40 | 308,650 | 2026 | 10,000 | electric | 320 | Bydgoszcz | dealer |

Every row also carries the listing URL, Otomoto's own price rating (below, in or above market), the photos, the full description and the equipment list. When the seller publishes them, you also get the VIN and the CEPiK history: first registration, number of owners, and the accident-free and service-record flags.

You can download the results as CSV, Excel or JSON, or read them through the Apify API.

### Three modes

| Mode | What you get | Good for |
|---|---|---|
| `detail` (default) | Card data plus the offer page: description, photos, equipment, VIN, CEPiK history, the seller's map pin | Valuations, due diligence, full exports |
| `search` | Card data only, faster | Large price surveys |
| `monitor` | Only cars that are new, changed price or disappeared since the last run, with price history and days on market | Daily alerts, competitor tracking |

### Price

$0.75 per 1,000 cars, in every mode. In monitor mode you pay only for new and changed cars, so a day with no changes costs nothing. A run that returns 100 BMWs with full details costs $0.075.

### How to run it

The quickest way: search on otomoto.pl, copy the address from your browser, and paste it into **Start URLs**. Search pages, single offers and dealer inventory pages all work.

To narrow results by keywords, add `query`. A run with `make: "BMW"` and `query: "M pakiet"` on 15 November 2026 returned only the 3 matching BMW 4 cars from the same search, for example:

| Car | Price (PLN) | Year | Mileage (km) | Fuel | Gearbox | City | Seller |
|---|---|---|---|---|---|---|---|
| BMW Seria 4 430i GPF xDrive M Sport | 41,400 | 2018 | 84,935 | petrol | automatic | Warszawa | dealer |
| BMW Seria 4 420d Coupe Sport Edition | 48,500 | 2020 | 115,000 | diesel | automatic | Warszawa | private |
| BMW Seria 4 430i xDrive Sport | 41,400 | 2018 | 164,000 | petrol | automatic | Chotomów | dealer |

Or describe the cars with filters:

```json
{
  "make": "BMW",
  "model": "Seria 3",
  "location": "warszawa",
  "yearFrom": 2020,
  "priceMax": 150000,
  "maxItems": 100
}
```

To track one dealer's stock and price cuts, save this as a task and give it a daily schedule:

```json
{
  "startUrls": [{ "url": "https://AUTO21KRKOCMYRZOWSKA.otomoto.pl/inventory" }],
  "mode": "monitor",
  "maxItems": 200
}
```

The first run records what the dealer has today and returns it all as `new`. From the second run on, you get only the changes: `new` cars, `changed` prices and `removed` listings.

### Input

| Field | Default | What it does |
|---|---|---|
| `startUrls` | none | Otomoto search, offer or dealer inventory URLs. When set, the filters below are ignored. |
| `mode` | `detail` | `detail`, `search` or `monitor` (see above). |
| `category` | `osobowe` | `osobowe` (cars), `dostawcze` (vans), `ciezarowe` (trucks), `przyczepy` (trailers), `maszyny-budowlane` (construction) or `czesci` (parts). English names like `cars` and `vans` work too. |
| `make`, `model` | none | For example `BMW` and `Seria 3`, or `Skoda` and `Octavia`. |
| `location` | whole Poland | A city or region as it appears in Otomoto URLs: `warszawa`, `krakow`, `mazowieckie`. |
| `radiusKm` | none | With `location`, keeps cars within this distance. |
| `yearFrom`, `yearTo` | none | Production year range. |
| `priceMin`, `priceMax` | none | Price range in PLN. |
| `mileageMin`, `mileageMax` | none | Mileage range in km. |
| `fuelType` | any | `petrol`, `diesel`, `electric`, `hybrid`, `plugin-hybrid`, `lpg`, `cng` or `hydrogen`. |
| `gearbox` | any | `manual` or `automatic`. |
| `bodyType` | any | `sedan`, `kombi`, `suv`, `compact`, `coupe`, `cabrio`, `minivan` or `city-car`. |
| `sellerType` | any | `private` or `business`. |
| `sort` | Otomoto's order | `newest`, `cheapest`, `price-asc` or `price-desc`. |
| `onlyPriceDrops` | `false` | Return only cars Otomoto marks as reduced. |
| `query` | none | Keyword filter. Only rows whose title, version, short description or description contain all words from this text are returned. For example `M pakiet` or `faktura VAT`. |
| `lat`, `lng` | none | Your location. In detail mode each car gets `distanceKm` from the seller. |
| `maxItems` | `100` | The most cars to return, up to 5,000. |
| `includeNoPrice` | `false` | Also return listings without a price. |

### Output fields

**Every row:** `id`, `url`, `title`, `priceAmount`, `priceCurrency`, `priceIsGross`, `make`, `model`, `version`, `year`, `mileageKm`, `fuelType`, `gearbox`, `engineCapacityCm3`, `enginePowerHp`, `bodyType`, `city`, `region`, `thumbnailUrl`, `sellerType`, `sellerId`, `sellerName` (dealers only, never a private seller's name), `priceEvaluation`, `createdAt`, `daysListed`, `scrapedAt`.

`priceEvaluation` is Otomoto's own price badge for the listing: `below_market`, `within_market` or `above_market`. It is empty when Otomoto shows no badge.

**Detail mode adds:** `description`, `photos`, `equipment`, `vin`, `firstRegistrationDate`, `numberOfOwners`, `noAccident`, `serviceRecord`, `damaged`, `insuranceValidity`, `inspectionValidity`, `condition`, `conditionLabel`, `newUsed`, `driveType`, `driveTypeLabel`, `color`, `colorLabel`, `colourType`, `doorCount`, `nrSeats`, `lat`, `lng`, `distanceKm`, `sellerInventoryUrl`, `imageCount`, and `badges` when the listing has them. Run status and the run summary are stored in the key-value store as `STATUS` and `SUMMARY`.

**Monitor mode adds:** `changeType` (`new`, `changed` or `removed`), `previousPriceAmount`, `priceHistory`, `firstPrice`, `lowestPrice`, `priceDropPct`, `firstSeenAt`, `lastSeenAt`, `daysOnMarket`.

Prices are numbers, dates are ISO 8601 in UTC, and the currency is an ISO code, so the data goes into Excel or a database without cleanup.

### FAQ

**Does Otomoto have an API?**
Not a public one for searching listings. This Actor reads the same public pages you see in your browser and turns them into rows.

**Do I get the seller's phone number?**
No. You get the seller's name, whether they are a dealer or a private person, and the dealer's Otomoto page. The Actor removes phone numbers and email addresses from descriptions too.

**Why is the VIN or the CEPiK history empty on some cars?**
Many sellers hide the VIN, and Otomoto shows the CEPiK history only for some listings. When Otomoto doesn't show a field, it comes back empty.

**Why did I get fewer cars than `maxItems`?**
`maxItems` is an upper limit. You get fewer when the search has fewer matches, and listings without a price are skipped unless you turn on `includeNoPrice`.

**Is scraping Otomoto legal?**
The Actor reads public pages without logging in and doesn't collect contact details. Check Otomoto's terms and your local law for what you do with the data.

**Something looks wrong in my results.**
Open an issue on the Issues tab with your input. We read every one and usually fix it within a day.

### Po polsku

Eksportuj ogłoszenia samochodowe z Otomoto.pl do arkusza: cena, marka, model, rok, przebieg, silnik, lokalizacja i sprzedawca. Wklej adres wyszukiwania albo ustaw filtry. W trybie `monitor` dostajesz tylko nowe auta, obniżki cen i usunięte ogłoszenia od ostatniego uruchomienia.

### Auf Deutsch

Exportiert Autoanzeigen von Otomoto.pl als Tabelle: Preis, Marke, Modell, Baujahr, Kilometerstand, Motor, Standort und Verkäufer. Such-URL einfügen oder Filter setzen. Im Modus `monitor` bekommen Sie nur neue Autos, Preissenkungen und verschwundene Anzeigen seit dem letzten Lauf.

### Use it from AI agents (MCP) and Python

**AI agents.** Add this Actor as a tool in Claude, Cursor, VS Code or any MCP client through the Apify MCP server. The agent reads the input schema, so a plain request is enough.

```json
{
  "mcpServers": {
    "otomoto-scraper": {
      "url": "https://mcp.apify.com?tools=redomic/otomoto-scraper",
      "headers": {
        "Authorization": "Bearer <YOUR_APIFY_TOKEN>"
      }
    }
  }
}
```

**Python.** `pip install apify-client`, then:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("redomic/otomoto-scraper").call(run_input={"make": "BMW", "maxItems": 24})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### More from us

- [Allabolag Scraper - Swedish Company Data](https://apify.com/redomic/allabolag-company-scraper): Scrape allabolag.se for Swedish company financials, industry, status and board role titles by search, org number or URL
- [Ashby Jobs Scraper with Salaries](https://apify.com/redomic/ashby-jobs-monitor): Ashby jobs scraper for any startup careers board (OpenAI, Ramp, Notion and thousands more), with salary ranges as numbers: min, max, currency, period, plus equity and bonus flags
- [ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API](https://apify.com/redomic/ats-jobs-search): Search 300,000+ open jobs from 11,000+ companies on Greenhouse, Lever and Ashby in one run
- [Blocket Scraper: Car Monitor](https://apify.com/redomic/blocket-se-scraper): Blocket scraper: each run returns up to 2,500 Blocket Bil and Torget listings as flat rows with price, make, model, year, mileage, VIN, inspections and seller
- [Closed Jobs Tracker: Filled Roles & Time-to-Fill](https://apify.com/redomic/closed-jobs-tracker): Search closed jobs from 11,000+ companies with closedOn, daysOpen and time-to-fill signals
- [Google Jobs Scraper - Job Postings API](https://apify.com/redomic/google-jobs): Google Jobs and job postings scraper: get job title, company, location, posted date, salary, full description and every apply link for any search
- [Google Trends API: Trending Now & Interest Over Time](https://apify.com/redomic/google-trends): Trending-now searches and new-trends alerts/monitoring per country with the news behind them, plus interest over time, interest by region, and related and rising queries for any keyword
- [GovDeals Scraper](https://apify.com/redomic/govdeals-scraper): Search and monitor GovDeals government surplus auctions
- [Greenhouse Jobs Monitor & Scraper](https://apify.com/redomic/greenhouse-jobs-monitor): Monitor Greenhouse jobs from any company careers board (Airbnb, Stripe, Discord and thousands more)
- [Job Postings Dataset: 320k+ Open Jobs, Updated Daily](https://apify.com/redomic/job-postings-dataset): 320,000+ open jobs from 10,000+ company career sites (Greenhouse, Lever, Ashby), updated daily with first-seen and closed dates
- [Lever Jobs Scraper with Salaries](https://apify.com/redomic/lever-jobs-monitor): Lever jobs scraper for any company's careers page (Palantir, Spotify, Zoox, Shield AI and thousands more): flat rows with title, team, location, workplace, commitment, apply link, salary as numbers and the full description merged
- [Marktplaats.nl Scraper](https://apify.com/redomic/marktplaats-nl): Scrape Marktplaats.nl listings into clean rows: title, price in EUR, condition, seller, location, images
- [Otodom Scraper: Poland Property Listings & Price Monitor](https://apify.com/redomic/otodom-scraper): Scrape Otodom.pl property listings in Poland
- [Personio Jobs Scraper](https://apify.com/redomic/personio-jobs): Scrape open jobs from Personio company career pages (jobs.personio.de/.com XML feeds)
- [Salary Data API: Pay Ranges by Job Title & Level](https://apify.com/redomic/salary-data): Get salary benchmarks (p10-p90, annualised, with n) and pay ranges from 150,000+ employer-posted jobs across 11,000+ companies, updated daily
- [SIRET Company Scraper](https://apify.com/redomic/siret-company-scraper): Search French companies by name, SIREN or SIRET
- [SUUMO Scraper - Japan Property Listings](https://apify.com/redomic/suumo-scraper): Scrape SUUMO Japan property listings from search URLs for rentals and sales
- [Talabat Scraper — Menus, Prices & Delivery Fees](https://apify.com/redomic/talabat-scraper): Talabat menus, prices and delivery fees as flat rows in 8 MENA markets
- [Workday Jobs Scraper](https://apify.com/redomic/workday-jobs): Search and monitor public Workday (myworkdayjobs.com) job postings

# Changelog

This Actor's version history is a separate document: https://apify.com/redomic/otomoto-scraper/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Otomoto.pl search, offer or dealer inventory URLs to scrape (e.g. https://www.otomoto.pl/osobowe/bmw or https://dealers.otomoto.pl/inventory). When set, the structured filters below are ignored.

## `mode` (type: `string`):

detail (default) opens offer pages for richer rows (description, equipment, photos, VIN, CEPiK); search returns listing cards only; monitor reports only new, changed and removed listings since the last run.

## `category` (type: `string`):

Vehicle section to search.

## `make` (type: `string`):

Vehicle make, e.g. BMW, Audi, Skoda. Use the Otomoto.pl slug or the name.

## `model` (type: `string`):

Vehicle model, e.g. Seria 3, A4, Octavia.

## `location` (type: `string`):

City or voivodeship path segment, e.g. warszawa, krakow, mazowieckie. Leave empty for whole Poland.

## `yearFrom` (type: `integer`):

Earliest production year (1900-2030).

## `yearTo` (type: `integer`):

Latest production year (1900-2030).

## `priceMin` (type: `integer`):

Minimum price in Polish zloty.

## `priceMax` (type: `integer`):

Maximum price in Polish zloty.

## `mileageMin` (type: `integer`):

Minimum mileage in kilometres.

## `mileageMax` (type: `integer`):

Maximum mileage in kilometres.

## `fuelType` (type: `string`):

Fuel type filter. Leave empty for all.

## `gearbox` (type: `string`):

Gearbox filter. Leave empty for all.

## `bodyType` (type: `string`):

Body type filter using Otomoto slugs (e.g. sedan, kombi, suv, compact, coupe, cabrio, minivan, city-car). Leave empty for all.

## `sellerType` (type: `string`):

Private seller or business/dealer. Leave empty for all.

## `sort` (type: `string`):

Listing order for structured search (ignored when startUrls are set).

## `onlyPriceDrops` (type: `boolean`):

Return only listings that Otomoto marks as price drops (structured search).

## `lat` (type: `number`):

Centre latitude for radius search. In detail mode, rows get distanceKm from the seller's map pin; with radiusKm only rows within the radius are returned.

## `lng` (type: `number`):

Centre longitude for radius search. In detail mode, rows get distanceKm from the seller's map pin; with radiusKm only rows within the radius are returned.

## `radiusKm` (type: `number`):

With a location, keeps only listings within this many kilometres of that location. With lat/lng in detail mode, filters by the seller's map pin and adds distanceKm.

## `query` (type: `string`):

Keyword filter. Only rows whose title, version, short description or description contain all words from this text are returned.

## `maxItems` (type: `integer`):

Maximum listing rows to return across all sources.

## `includeNoPrice` (type: `boolean`):

By default listings with no published price are dropped. Set true to also return them with priceAmount null.

## `proxy` (type: `object`):

Proxy settings (used if the Actor is configured for proxied requests).

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.otomoto.pl/osobowe/bmw"
    }
  ],
  "mode": "detail",
  "category": "osobowe",
  "make": "",
  "model": "",
  "location": "",
  "fuelType": "",
  "gearbox": "",
  "bodyType": "",
  "sellerType": "",
  "sort": "",
  "onlyPriceDrops": false,
  "query": "",
  "maxItems": 24,
  "includeNoPrice": false,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All result rows from the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.otomoto.pl/osobowe/bmw"
        }
    ],
    "make": "",
    "model": "",
    "location": "",
    "query": "",
    "maxItems": 24
};

// Run the Actor and wait for it to finish
const run = await client.actor("redomic/otomoto-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [{ "url": "https://www.otomoto.pl/osobowe/bmw" }],
    "make": "",
    "model": "",
    "location": "",
    "query": "",
    "maxItems": 24,
}

# Run the Actor and wait for it to finish
run = client.actor("redomic/otomoto-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.otomoto.pl/osobowe/bmw"
    }
  ],
  "make": "",
  "model": "",
  "location": "",
  "query": "",
  "maxItems": 24
}' |
apify call redomic/otomoto-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,redomic/otomoto-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/MqU2UdY9sp57gL0Zl/builds/pJai2GZaSAFiCajY8/openapi.json
