DEV Community

Cover image for How to scrape OLX.pl car listings by make, year and mileage with Python
Norbert Sobala
Norbert Sobala

Posted on

How to scrape OLX.pl car listings by make, year and mileage with Python

OLX.pl is where a large share of Poland's used cars get listed, by dealers and private owners alike. The site has good filters, but there is no export button, and comparing 200 listings by hand gets old fast. This guide uses the OLX Car Scraper Poland on Apify to turn a filtered car search into a table you can open in Excel or load into pandas.

My test search: Toyota Corolla, passenger cars, model year 2018 or newer, whole country, capped at 40 listings. Everything below comes from that dataset.

OLX Toyota Corolla listings in a table

What you get per listing

The field names are in Polish because the actor targets the Polish market. Here is what they mean:

Field Meaning Example from my run
title, url Listing title and link Toyota Corolla 1.5 VVT-i 125KM Comfort
marka, model Make, model Toyota, Corolla
rocznik Model year 2022
przebiegKm Mileage in km 180000
cena, waluta Price, currency 52500, PLN
paliwo Fuel (Benzyna = petrol, CNG i Hybryda = hybrid) Benzyna
skrzynia, naped Gearbox, drive Manualna, Na przednie koła
pojemnoscCm3, mocKm Engine size (cm³), power (hp) 1490, 125
typNadwozia, kolor, stan Body type, colour, damaged or not Sedan, Biały, Nieuszkodzony
krajPochodzenia Country of origin Polska
miasto, wojewodztwo, gpsLat, gpsLon City, region, coordinates Wieliczka, Małopolskie
sprzedawcaTyp Seller type (Prywatny = private, Komis / Firma = dealer) Komis / Firma
dataDodania, dataOdswiezenia Posted and refreshed timestamps 2026-10-07T18:01:47+02:00
glowneZdjecie, zdjecia, opis Main photo, all photos, description (HTML)

There is also sprzedawcaNazwa, the seller's display name. For private sellers that is a person's name, so treat it carefully (more on that at the end).

What 40 Corollas looked like

  • Prices went from 36,900 PLN to 141,900 PLN, median 78,195 PLN. Median mileage was about 90,000 km.
  • 25 cars were hybrids, 11 petrol, 3 LPG and 1 diesel. All 25 hybrids were automatics, and every non-hybrid had a manual gearbox.
  • 34 listings came from dealers and 6 from private sellers.
  • 6 listings were brand new 2026 cars with 1 to 5 km on the clock, all from dealers. They pull the averages up, so filter them out if you want used-car prices.
  • 27 of the 40 cars were in the Mazowieckie region (Warsaw and around). I did not set a city, so that is just where the supply sits for this query.

Comparing like with like is where a table beats scrolling. For model years 2018 to 2023 only, the 14 hybrids had a median price of 79,370 PLN against 58,450 PLN for the 10 petrol cars, at similar median mileage (about 120,000 vs 115,000 km). That is roughly a 21,000 PLN premium for the hybrid in this small sample. Forty rows won't settle a market question. It does show what you can answer in two minutes once the data is in a DataFrame.

Option 1: no code

  1. Open the actor page and click Try for free.
  2. Pick a Kategoria (category): passenger cars, motorcycles, trucks, vans, trailers or parts.
  3. Choose one or more Marki (makes). Multi-select works, so BMW and Audi can go in one run.
  4. Type Modele (models) if you want them, for example Golf, Passat.
  5. Set filters: price, year, mileage, fuel, gearbox, city with a radius.
  6. Set Maks. liczba ogłoszeń (max listings). I used 40. Click Start and export from the Storage tab as CSV, Excel or JSON.

The form groups filters into sections, so you never have to build OLX URLs yourself:

OLX Car Scraper input form

Option 2: Python with apify-client and pandas

pip install apify-client pandas
Enter fullscreen mode Exit fullscreen mode

Grab your API token from Settings → API & Integrations in the Apify console and keep it in an environment variable.

import os
import pandas as pd
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run_input = {
    "kategoria": "samochody-osobowe",
    "marki": ["toyota"],
    "modele": ["Corolla"],
    "rocznikOd": 2018,
    "maxLiczbaOgloszen": 40,
}

run = client.actor("liveclaude/olx-motoryzacja-pl").call(run_input=run_input)
items = client.dataset(run["defaultDatasetId"]).list_items().items
df = pd.DataFrame(items)

# Leave out new cars and the seller name column
used = df[df["przebiegKm"] > 100].drop(columns=["sprzedawcaNazwa"], errors="ignore")

summary = (
    used[used["rocznik"] <= 2023]
    .groupby("paliwo")
    .agg(listings=("cena", "size"),
         median_price=("cena", "median"),
         median_km=("przebiegKm", "median"))
)
print(summary)

cols = ["title", "rocznik", "przebiegKm", "cena", "paliwo",
        "skrzynia", "mocKm", "miasto", "sprzedawcaTyp", "url"]
used[cols].sort_values("cena").to_csv("olx_corolla.csv", index=False)
Enter fullscreen mode Exit fullscreen mode

call() waits for the run to end. For runs with thousands of listings, start() plus a webhook is cleaner.

Input options worth knowing

Category and makes. kategoria takes samochody-osobowe, motocykle, ciezarowe, dostawcze, przyczepy-naczepy or czesci. marki is a list of lowercase slugs like bmw or volkswagen, and modele is free text.

Ranges. cenaOd/cenaDo (price in PLN), rocznikOd/rocznikDo (year), przebiegOd/przebiegDo (km), pojemnoscOd/pojemnoscDo (cm³), mocOd/mocDo (hp).

Specs. paliwa (fuel list), skrzynia (manual or automatic), naped (front, rear or one of the AWD variants), typNadwozia, kolor, and stan to keep or drop damaged cars.

Location. miasto plus promienKm (0 to 100 km) for a radius search around a city.

Seller and freshness. typSprzedawcy filters to private or business. opublikowaneW limits to listings from the last 24 hours, 7 days or 30 days. tylkoZeZdjeciem keeps only listings with photos.

Volume. maxLiczbaOgloszen defaults to 500 per run. uzyjProxy turns on Apify proxy rotation if you run large jobs. advancedUrls accepts raw OLX search URLs when a filter is missing from the form.

Scheduling: alerts for new listings

The most practical feature is monitorNowe. With it on, each run returns only listings that were not there last time. wykrywajZmianyCen (on by default) also flags price drops on cars you already saw. Here is an input a dealer could schedule every 30 minutes:

{
  "kategoria": "samochody-osobowe",
  "marki": ["bmw", "audi"],
  "cenaDo": 80000,
  "rocznikOd": 2015,
  "przebiegDo": 150000,
  "miasto": "Warszawa",
  "promienKm": "50",
  "monitorNowe": true
}
Enter fullscreen mode Exit fullscreen mode

Create the schedule in the Apify console, then send results to Google Sheets, Slack, Make, Zapier or n8n, or to your own endpoint with a webhook. You can also call the actor from Claude, ChatGPT or Cursor through the Apify MCP server.

Pricing

Pay per event. Per 1,000 events at the current price list:

Event Free Bronze Silver Gold
Listing scraped $6 $5 $4 $3
New listing found (monitoring) $12 $10 $8 $6
Price change detected $6 $5 $4 $3

Each run also has a $0.05 start fee. New users get their first 100 listings free, which covers a test like mine twice over.

Responsible use

The actor reads public OLX listings. Private sellers are people, and their names and anything in a free-text description can be personal data under GDPR. Drop sprzedawcaNazwa unless you have a lawful reason to keep it, do not build contact lists from private listings, and check that your use fits OLX.pl's terms. Keep run frequency sensible: every 30 minutes for a narrow search is plenty.

This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.

Top comments (0)