# OLX Scraper: Poland, Romania, Ukraine, Portugal & Bulgaria (`zibounne/olx-europe-scraper`) Actor

Scrape OLX listings from Poland (olx.pl), Romania (olx.ro), Ukraine (olx.ua), Portugal (olx.pt) and Bulgaria (olx.bg). Paste any search or category URL: cars, real estate, electronics. Get title, price, city, attributes and photos. Export to Excel, CSV or JSON. No personal data.

- **URL**: https://apify.com/zibounne/olx-europe-scraper.md
- **Developed by:** [Zibounne](https://apify.com/zibounne) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.

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

## OLX Scraper: Poland, Romania, Ukraine, Portugal & Bulgaria

Paste one or more OLX search or category URLs and get back structured listing data -- title, price, location, photos, and the listing's full spec table -- for Poland, Romania, Ukraine, Portugal, and Bulgaria.

### What it does

- Fetches one or more OLX search/category URLs through a residential proxy in the matching country.
- Paginates each URL until `maxItems` is reached (per URL) or OLX has no more results.
- Deduplicates listings by id across the entire run -- including the rare case where OLX repeats the same promoted ad twice on one page.
- Pushes a strict, fixed set of fields per listing (see below) -- nothing else.
- Reports a clear run status: how many listings, how many pages, and how many of the requested URLs actually succeeded.

### Supported countries

| Country | Domain |
|---|---|
| Poland | olx.pl |
| Romania | olx.ro |
| Ukraine | olx.ua |
| Portugal | olx.pt |
| Bulgaria | olx.bg |

URLs from other OLX domains, or single-listing URLs, are skipped with a clear message; the run continues with the valid URLs.

### Input

```json
{
  "startUrls": [
    {"url": "https://www.olx.ro/auto-masini-moto-ambarcatiuni/autoturisme/"},
    {"url": "https://www.olx.pl/motoryzacja/samochody/"}
  ],
  "maxItems": 60
}
```

- `startUrls` -- one or more OLX search/category URLs. Plain strings also work: `["https://www.olx.ro/..."]`.
- `maxItems` -- maximum listings **per URL** (not shared across URLs).

### Output fields

Each dataset row is built from an explicit field allow-list -- nothing is copied wholesale from OLX's internal data:

`id`, `url`, `title`, `price` (`value`, `currency`, `negotiable`, `isFree`, `isExchange`), `category` (`id`, `type`), `attributes` (flat `key -> normalizedValue` map -- model, year, mileage, etc., machine-comparable), `attributesDisplay` (flat `key -> value` map -- the same fields as OLX displays them, with units), `location` (`city`, `region` only), `photos` (image URLs), `createdTime`, `lastRefreshTime`, `isPromoted`, `itemCondition`, `country`.

`attributes` are flat key/value columns, so exports stay readable in Excel and CSV.

Example (from a real run, a car listing found via keyword search):

```json
{
  "id": 673043953,
  "url": "https://www.olx.pt/d/anuncio/bmw-116-d-advantage-IDJy1tD.html",
  "title": "BMW 116 d Advantage",
  "price": { "value": 21900, "currency": "EUR", "negotiable": false, "isFree": false, "isExchange": false },
  "category": { "id": 741, "type": "automotive" },
  "attributes": {
    "body_type": "compact", "year": "2023", "modelo": "116",
    "engine_capacity": "1496", "combustivel": "diesel", "engine_power": "116",
    "quilometros": "68000", "gearbox": "manual", "condicao": "usado"
  },
  "attributesDisplay": {
    "body_type": "Utilitário", "year": "2023", "modelo": "116",
    "engine_capacity": "1.496", "combustivel": "Diesel", "engine_power": "116",
    "quilometros": "68.000 km", "gearbox": "Manual", "condicao": "Usado"
  },
  "location": { "city": "Gandra", "region": "Porto" },
  "photos": [
    "https://ireland.apollo.olxcdn.com:443/v1/files/dnqk7owlm73n-PT/image;s=1814x1360"
  ],
  "createdTime": "2026-08-25T19:47:34+01:00",
  "lastRefreshTime": "2026-09-10T11:53:41+01:00",
  "isPromoted": true,
  "itemCondition": "",
  "country": "PT"
}
```

### Beyond vehicles: any OLX category or keyword search

This actor isn't vehicle-specific -- it reads whatever OLX renders for a given URL. Validated against real runs so far:

- **Category pages**: vehicles (all 5 countries), real estate (`olx.ro/imobiliare/`), electronics (`olx.pl/elektronika/`).
- **Keyword search within a category**: append `q-<keyword>/` to a category URL, e.g. `olx.pt/carros-motos-e-barcos/carros/q-bmw/`.

### OLX's 1000-result cap

OLX itself caps any single search at 1000 results (25 pages), regardless of how large `maxItems` is set. This has been observed identically across all five supported countries. If you need more than 1000 listings from one category, split the search into narrower slices and run the actor with one `startUrls` entry per slice -- e.g. one region at a time, or a price range via OLX's own price filter query parameter (`search[filter_float_price:from]` / `search[filter_float_price:to]`, seen in OLX's own generated links).

### Use cases

- **Automated price tracking** -- run on a schedule against the same category/keyword URL and compare `price.value` over time.
- **Real estate market analysis** -- OLX's real estate categories carry the same structured `attributes` (rooms, area, furnishing) as vehicle listings.
- **Deal-hunting** -- combine a keyword search URL with OLX's own price filter to surface only listings under a threshold.

This actor can be run on a schedule (Apify Schedules) and combined with Apify's native integrations (webhooks, email/Slack notifications on run failure, or piping the dataset straight into a downstream Apify actor or external system) without any code changes on your side.

### No personal data

This actor does not collect and will never output seller names, phone numbers, seller/shop profile data, free-text ad descriptions, or vehicle identification numbers (VIN). Location is limited to city and region -- no precise coordinates. This is a deliberate, structural exclusion in the parsing code, not a filter applied after the fact.

**Export tip**: choose the Overview view when exporting to get only the main columns (title, price, location, date, URL).

# Actor input Schema

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

One or more OLX search or category listing URLs. The target country is inferred from each domain (e.g. olx.ro -> RO) and used to select that URL's residential proxy. maxItems applies per URL; listings are deduplicated by id across the whole run.

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

Maximum number of unique listings to return per start URL. Pages are fetched until this is reached or there is no next page. Note: OLX itself caps any single search at 1000 results (25 pages), observed identically on Poland, Romania, Ukraine, Portugal and Bulgaria -- a value above 1000 will simply never be reached.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.olx.ro/auto-masini-moto-ambarcatiuni/autoturisme/"
    }
  ],
  "maxItems": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

Main columns: title, price, location, date, URL.

## `dataset` (type: `string`):

Every field, including attributes and photos.

# 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.olx.ro/auto-masini-moto-ambarcatiuni/autoturisme/"
        }
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("zibounne/olx-europe-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.olx.ro/auto-masini-moto-ambarcatiuni/autoturisme/" }],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("zibounne/olx-europe-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.olx.ro/auto-masini-moto-ambarcatiuni/autoturisme/"
    }
  ],
  "maxItems": 50
}' |
apify call zibounne/olx-europe-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zibounne/olx-europe-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/N3FJAffGDvToXjSzJ/builds/c54GaK5I3FTk3Sdvg/openapi.json
