# Otomoto.pl Car Scraper (`unfenced-group/otomoto-scraper`) Actor

Scrape Otomoto.pl car listings: prices, specs, mileage & equipment. Filter by make, model, year, fuel type, price range and more. 240k+ listings.

- **URL**: https://apify.com/unfenced-group/otomoto-scraper.md
- **Developed by:** [Unfenced Group](https://apify.com/unfenced-group) (community)
- **Categories:** E-commerce
- **Stats:** 7 total users, 3 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.79 / 1,000 car listings

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Otomoto.pl Car Scraper

![Otomoto.pl Car Scraper](https://api.apify.com/v2/key-value-stores/ClElVyZWvQgPQIuDL/records/otomoto-scraper)

Extract car listings from Otomoto.pl, Poland's largest vehicle marketplace, in a clean, consistent structure ready for price monitoring, market research and dealer analytics. Full specifications, structured pricing with drop tracking and price rating, GPS location, equipment lists and seller details. No API key required.

***

### Why this scraper?

#### 🎯 Built for Otomoto.pl

A dedicated Polish scraper tuned for Otomoto.pl — its categories, price format and currency (PLN), not a generic tool pointed at it.

#### 🚗 Complete vehicle data

Make, model, version, generation, year, mileage, fuel, gearbox, drivetrain, engine capacity and power, body type, colour, seats and doors.

#### 💶 Structured pricing

Price and currency, whether the price is net (VAT deductible), whether it recently dropped and by how much, plus Otomoto's own price rating (below / at / above market).

#### 📍 Precise location

City, region and exact latitude/longitude of the listing, ready for mapping and regional analysis.

#### ✅ Trust signals

Otomoto verification and CEPIK (Polish vehicle registry) verification flags, accident-free, first-owner, service-record, registration and import status.

#### 🔒 Privacy by default

Company and dealer data only. We never collect private sellers' personal names, phone numbers or any personal contact details.

***

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array | (empty) | One or more Otomoto.pl listing or search URLs. Overrides the make/model/filter settings below. |
| `make` | string | (empty) | Car brand slug, e.g. `volkswagen`, `bmw`, `toyota`. Leave empty for all makes. |
| `model` | string | (empty) | Car model slug, e.g. `golf`, `3-series`. Requires Make to be set. |
| `yearFrom` | integer | (empty) | Minimum production year, inclusive. |
| `yearTo` | integer | (empty) | Maximum production year, inclusive. |
| `priceFrom` | integer | (empty) | Minimum asking price in PLN. |
| `priceTo` | integer | (empty) | Maximum asking price in PLN. |
| `mileageFrom` | integer | (empty) | Minimum mileage in kilometres. |
| `mileageTo` | integer | (empty) | Maximum mileage in kilometres. |
| `fuelType` | string | Any | Petrol, Diesel, Hybrid, Electric, LPG, CNG or Hydrogen. |
| `bodyType` | string | Any | Sedan, Estate, Hatchback, SUV, Coupé, Cabriolet, Van, Minivan, Bus or Pickup. |
| `gearbox` | string | Any | Manual or Automatic. |
| `sortBy` | string | Default | Newest first, Price low→high, Price high→low, Mileage low→high, or Year newest first. |
| `conditionDamaged` | boolean | `true` | When disabled, only undamaged cars are returned. |
| `maxResults` | integer | `5` | Maximum number of car listings to return. |
| `fetchDetails` | boolean | `false` | Fetch each listing's detail page for the full description, equipment, all photos, GPS and 25+ extra fields. |
| `requestDelayMs` | integer | `1500` | Minimum delay between requests in milliseconds. |

***

### Output schema

Fields the source does not publish for a given car are returned as `null` rather than omitted.

#### Always present (every run)

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique Otomoto listing ID. |
| `title` | string | Listing title. |
| `url` | string | Direct link to the listing. |
| `shortDescription` | string | Short teaser line from the search card. |
| `make` / `makeDisplay` | string | Brand slug and display name. |
| `model` / `modelDisplay` | string | Model slug and display name. |
| `version` | string | Version / trim (null when not published). |
| `year` | number | Production year. |
| `mileageKm` | number | Mileage in kilometres. |
| `fuelType` | string | Fuel type. |
| `engineCapacityCc` | number | Engine capacity in cc. |
| `enginePowerHp` | number | Engine power in hp. |
| `gearbox` | string | Manual or automatic. |
| `priceValue` | number | Asking price. |
| `priceCurrency` | string | Currency code (PLN). |
| `priceIsNet` | boolean | True if the price is net (VAT deductible). |
| `priceDrop` | number | Recent price-drop percentage (null if no drop). |
| `priceDropLowestPrice` | number | Lowest price reached after the drop, in PLN (null if no drop). |
| `priceEvaluationIndicator` | string | Otomoto's price rating: `BELOW`, `IN`, `ABOVE` or `NONE`. |
| `city` / `region` | string | Listing city and region. |
| `sellerName` | string | Dealer / company name (null for private sellers — personal names are never collected). |
| `sellerType` | string | `PROFESSIONAL` or `PRIVATE`. |
| `cepikVerified` | boolean | Verified against the Polish CEPIK vehicle registry. |
| `isHighlighted` / `isPromoted` | boolean | Paid listing placement flags. |
| `bumpDate` | string | Last time the listing was bumped (null if never bumped). |
| `createdAt` | string | When the listing was published. |
| `source` | string | Always `otomoto.pl`. |
| `contentHash` | string | Stable 16-char fingerprint of id + price + mileage for change detection. |
| `scrapedAt` | string | ISO timestamp of scraping. |

#### With `fetchDetails: true`

| Field | Type | Description |
|---|---|---|
| `generation` | string | Model generation, e.g. "F39 (2017-2023)". |
| `condition` | string | New or used. |
| `transmission` | string | Drivetrain, e.g. front-wheel, all-wheel-permanent. |
| `bodyType` | string | Body style. |
| `countryOrigin` | string | Country of origin code. |
| `nrSeats` / `doorCount` | number | Seats and doors. |
| `color` / `colourType` | string | Colour and finish (e.g. metallic, pearl). |
| `damaged` | boolean | Declared as damaged. |
| `noAccident` | boolean | Declared accident-free. |
| `isRegistered` | boolean | Registered in Poland. |
| `isOriginalOwner` | boolean | First owner. |
| `hasVin` / `hasRegistrationDoc` / `hasServiceRecord` | boolean | Documentation flags. |
| `financingAvailable` / `leasingAvailable` | boolean | Finance / leasing offered. |
| `isVintage` | boolean | Historic / classic vehicle. |
| `isImported` | boolean | Imported car. |
| `verifiedCar` | boolean | Otomoto-verified listing. |
| `co2Emissions` | number | CO2 in g/km (null if not published). |
| `urbanConsumption` / `extraUrbanConsumption` / `avgConsumption` | number | Fuel consumption, l/100km (published only for some cars). |
| `autonomyKm` | number | Electric range in km (electric vehicles only). |
| `latitude` / `longitude` | number | GPS coordinates of the listing area. |
| `descriptionHtml` / `descriptionText` / `descriptionMarkdown` | string | Full description in three formats. |
| `imageUrls` | array | All photo URLs. |
| `equipment` | array | Equipment and options list. |
| `sellerUrl` | string | Dealer profile URL. |
| `sellerNumberOfAds` | number | Dealer's active listing count. |
| `updatedAt` / `originalCreatedAt` | string | Listing update and original-publish timestamps. |

#### Example record

```json
{
  "id": "6149219292",
  "title": "Mitsubishi ASX 1.6 ClearTec 2WD Diamant Edition",
  "url": "https://www.otomoto.pl/osobowe/oferta/mitsubishi-asx-ID6I9x2c.html",
  "shortDescription": "1.6 MIVEC DIAMANT LIFT Bezkolizyjny",
  "make": "mitsubishi",
  "makeDisplay": "Mitsubishi",
  "model": "asx",
  "modelDisplay": "ASX",
  "version": "1.6 ClearTec 2WD Diamant Edition",
  "generation": "F39 (2017-2023)",
  "year": 2018,
  "condition": "used",
  "mileageKm": 124000,
  "fuelType": "petrol",
  "engineCapacityCc": 1590,
  "enginePowerHp": 117,
  "gearbox": "manual",
  "transmission": "front-wheel",
  "bodyType": "SUV",
  "countryOrigin": "d",
  "priceValue": 55555,
  "priceCurrency": "PLN",
  "priceIsNegotiable": false,
  "priceIsNet": false,
  "priceDrop": 3.9,
  "priceDropLowestPrice": 55555,
  "priceEvaluationIndicator": "IN",
  "nrSeats": 5,
  "doorCount": 5,
  "color": "Szary",
  "colourType": "Perłowy",
  "damaged": false,
  "noAccident": true,
  "isRegistered": true,
  "isOriginalOwner": true,
  "hasVin": true,
  "hasServiceRecord": true,
  "isImported": true,
  "verifiedCar": false,
  "cepikVerified": false,
  "co2Emissions": 136,
  "urbanConsumption": 7.0,
  "extraUrbanConsumption": 4.4,
  "city": "Końskie",
  "region": "Świętokrzyskie",
  "latitude": 51.19163,
  "longitude": 20.40866,
  "sellerName": "PREMIUM-CARS",
  "sellerType": "PROFESSIONAL",
  "sellerNumberOfAds": 20,
  "isPromoted": false,
  "createdAt": "2026-07-10T06:11:34Z",
  "equipment": ["Apple CarPlay", "Android Auto", "Bluetooth", "Klimatyzacja"],
  "imageUrls": ["https://ireland.apollo.olxcdn.com/v1/files/..."],
  "source": "otomoto.pl",
  "contentHash": "ef4698ebe9f37bfa",
  "scrapedAt": "2026-07-10T06:13:43.352Z"
}
```

***

### Examples

**All BMWs, newest first:**

```json
{
  "make": "bmw",
  "sortBy": "newest",
  "maxResults": 100
}
```

**Cheap diesel estates, full detail:**

```json
{
  "bodyType": "kombi",
  "fuelType": "diesel",
  "priceTo": 40000,
  "sortBy": "price_asc",
  "fetchDetails": true,
  "maxResults": 200
}
```

**Scrape a specific search URL:**

```json
{
  "startUrls": [
    { "url": "https://www.otomoto.pl/osobowe/audi/a4?search%5Bfilter_float_year%3Afrom%5D=2019" }
  ],
  "maxResults": 200
}
```

**Daily price monitoring (run on a schedule):**

```json
{
  "make": "volkswagen",
  "model": "golf",
  "sortBy": "newest",
  "fetchDetails": true,
  "maxResults": 500
}
```

Schedule this input in the Apify Scheduler to track prices, price drops and new listings over time. Use `contentHash` to detect changed records between runs.

***

### 💰 Pricing

**$0.97 per 1,000 results** — you only pay for successfully retrieved listings. Failed retries are never charged.

| Results | Cost |
|---|---|
| 100 | ~$0.10 |
| 1,000 | ~$0.97 |
| 10,000 | ~$9.70 |
| 100,000 | ~$97.00 |

> Flat-rate alternatives typically charge $29–$49/month regardless of usage.

Subscription tiers lower the rate further, down to $0.79 per 1,000 at the highest tier. Use the **Max results** cap in the input to control your spend exactly.

***

### Performance

| Run size | Typical time |
|---|---|
| 100 results | under 1 minute |
| 1,000 results | 2–4 minutes |
| 10,000 results | 20–35 minutes |

Detail mode (`fetchDetails: true`) fetches one extra page per car, so runs take longer but return the full field set.

***

### Known limitations

- Detail-only fields (equipment, GPS, full description, generation, condition, consumption and the boolean flags) require `fetchDetails: true`. Without it, only the search-card fields are returned.
- Fuel consumption, CO2 and electric range are published by Otomoto only for some cars — expect `null` on a share of records.
- VIN and exact registration date are encrypted at source and are not usable, so we expose only the `hasVin` and `hasRegistrationDoc` flags rather than false values.
- Private sellers' personal names and any phone numbers are never collected, by policy.
- Prices and stock change constantly; records reflect the moment of scraping, and cars can sell or be withdrawn at any time.

***

### Technical details

- **Source:** Otomoto.pl — Polish car marketplace
- **Coverage:** the full `/osobowe` (passenger cars) catalogue, filterable via the input parameters above
- **Retry:** automatic retry on network errors with exponential backoff

***

### Need a custom scraper?

**[Unfenced Group](https://www.unfencedgroup.nl)** builds Apify actors for any website — for free.

If the site you need isn't in our portfolio yet, just ask. We scope, build, and publish it at no cost to you. You only pay for results — we absorb the compute and proxy costs ourselves. Same pay-per-result pricing, same quality, same standards as every actor in this portfolio.

**Get in touch:** [www.unfencedgroup.nl](https://www.unfencedgroup.nl)

# Actor input Schema

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

One or more Otomoto.pl listing or search result URLs, e.g. https://www.otomoto.pl/osobowe/bmw. Overrides the make/model/filter settings below.

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

Car brand slug, e.g. volkswagen, bmw, toyota, mercedes-benz. Leave empty to scrape all makes.

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

Car model slug, e.g. golf, 3-series, corolla. Requires Make to be set.

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

Minimum production year, inclusive. Example: 2018.

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

Maximum production year, inclusive. Example: 2023.

## `priceFrom` (type: `integer`):

Minimum asking price in PLN. Example: 20000.

## `priceTo` (type: `integer`):

Maximum asking price in PLN. Example: 80000.

## `mileageFrom` (type: `integer`):

Minimum mileage in kilometres. Example: 0.

## `mileageTo` (type: `integer`):

Maximum mileage in kilometres. Example: 150000.

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

Filter by fuel type. Leave as Any to include all fuel types.

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

Filter by car body style. Leave as Any to include all body types.

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

Filter by transmission type. Leave as Any to include both.

## `sortBy` (type: `string`):

Order the search results. Leave as Default to use Otomoto's own relevance order. Promoted listings may still appear first regardless of this setting.

## `conditionDamaged` (type: `boolean`):

When disabled, only undamaged cars are returned.

## `maxResults` (type: `integer`):

Maximum number of car listings to return.

## `fetchDetails` (type: `boolean`):

Fetch each listing's detail page for the full description, equipment list, all photos, GPS coordinates and 25+ extra fields (generation, condition, seats, doors, colour type, boolean flags, consumption, CO2, etc.). Slower but far richer.

## `requestDelayMs` (type: `integer`):

Minimum delay between requests in milliseconds.

## Actor input object example

```json
{
  "startUrls": [],
  "fuelType": "",
  "bodyType": "",
  "gearbox": "",
  "sortBy": "",
  "conditionDamaged": true,
  "maxResults": 100,
  "fetchDetails": false,
  "requestDelayMs": 1500
}
```

# Actor output Schema

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

No description

# 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": [],
    "make": "",
    "model": "",
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("unfenced-group/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": [],
    "make": "",
    "model": "",
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("unfenced-group/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": [],
  "make": "",
  "model": "",
  "maxResults": 100
}' |
apify call unfenced-group/otomoto-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,unfenced-group/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/IwboWcohUxehfOshh/builds/ZzjW9yswBdJfjprWl/openapi.json
