# OLX.pl Scraper - Polish Classified Listings (`ziomixshot/olx-pl-scraper`) Actor

Collect verified OLX.pl listings from every category with search, price, location and category filters.

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

## Pricing

from $1.50 / 1,000 listings

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?

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

## OLX.pl Scraper

Collect listings from [OLX.pl](https://www.olx.pl), Poland's largest classifieds site, in every category. Give a phrase, a category and a place by name, add price, seller and category-specific filters, or paste a search URL copied from OLX. Every listing is checked against your filters, de-duplicated and returned as clean JSON, ready for CSV, Excel, the API or AI agents.

[Run OLX.pl Scraper](https://console.apify.com/actors/MAtrZSndbJYjPQDUK?addFromActorId=MAtrZSndbJYjPQDUK) · [Input schema](https://apify.com/ziomixshot/olx-pl-scraper/input-schema) · [Output schema](https://apify.com/ziomixshot/olx-pl-scraper/output-schema)

### What you get

- All OLX.pl categories: electronics, cars, real estate, jobs, fashion, home and more, with the filters OLX offers for the chosen category.
- Names instead of IDs: `location` takes a city or voivodeship (`Kraków`, `Mazowieckie`), `category` takes a category name or path (`Elektronika`, `motoryzacja/samochody`). No numeric IDs to look up.
- Filters you can discover: a free run with `listFilters` lists every filter of a category with its allowed values and a ready-to-paste example.
- Price range, private or business sellers, listings with photos only, listings with OLX delivery only, four sort orders, search URLs copied from OLX (`startUrls`), several searches in one run with shared de-duplication.
- Verified results: filters are checked with OLX before the run and against every record. A filter that OLX would silently ignore stops the run with an explanation instead of returning wrong data.
- No duplicates: the same listing is returned once per run, and you are charged once.
- Optional details (`enrichDetails`): seller profile, extra price information and push-up times, with optional view counts (`includeViews`).
- Monitoring (`mode: monitor`): each run returns only listings not reported by earlier runs, so you can schedule it and get new listings.
- Free estimate (`countOnly`): how many listings match your search, without scraping or charges.
- More than 1000 results per search: one OLX query exposes about 1050 listings, so the Actor splits large searches by region and price automatically.
- One date format (UTC, `YYYY-MM-DDTHH:mm:ssZ`) in every field.
- Phone numbers are never returned.

### Quick start

1. Type a **Search phrase**, or choose a **Category** and a **Location**.
2. Add a price range, seller type or category filters if you need them.
3. Set **Max items** (the limit of listings returned and charged).
4. Click **Start**. The default input (`query: rower`, `maxItems: 100`) is a working example.
5. Open the **Overview** table, export JSON, CSV or Excel, or read the data through the API.

Not sure how many listings match, or what a run would cost? Start with **Count only**: it is free and returns the number OLX reports.

### Pricing

Pay per event, no start fee:

| Event | Price | When |
|---|---|---|
| `listing` | $1.50 / 1000 | One per listing returned |
| `listing-details` | $2.25 / 1000 | One per listing when `enrichDetails` is on and the details were fetched |
| `listing-change` | not charged yet | One per `change` record (`trackViews`); a price will be published here before it is charged |

Duplicates, rejected cards, empty runs, `countOnly` and `listFilters` runs and runs that end with an input or filter error are not charged. `maxItems` and your maximum cost per run are hard limits: the run stops when either is reached. In tests the platform usage cost (proxy and compute) was about $0.01 to $0.07 per 1000 listings, depending on `enrichDetails`.

Cost of a run = listings returned × $0.0015 (plus $0.00225 per enriched listing). Run `countOnly` first to see how many listings match.

### Ready-to-use recipes

#### 1. Search by phrase and place

```json
{
  "query": "rower",
  "location": "Kraków",
  "priceTo": 1500,
  "sortBy": "newest",
  "maxItems": 100
}
```

`location` is a city or a voivodeship. The run log shows how many listings OLX reports for the search.

#### 2. Browse a category

```json
{
  "category": "elektronika/telefony",
  "location": "Warszawa",
  "distance": 30,
  "ownerType": "private",
  "onlyWithPhotos": true,
  "maxItems": 200
}
```

`category` takes the URL path of the category or its name. A name used by several categories (for example `Telefony`) is refused with the list of paths to choose from, so you never get the wrong category by accident. `distance` (km around the city) needs a city in `location`.

#### 3. Filter by category filters (cars, flats, jobs)

Each category has its own filters. List them for free:

```json
{
  "category": "motoryzacja/samochody",
  "listFilters": true
}
```

The run returns one `filter` record per filter: `name`, `label`, `type`, `unit`, allowed `values` and `categoryFiltersExample`. Paste the examples into `categoryFilters` (a bare number for a range filter means that exact value, `"filter_float_year": 2018`):

```json
{
  "category": "motoryzacja/samochody",
  "categoryFilters": {
    "filter_float_year": { "from": 2018 },
    "filter_enum_petrol": ["diesel"]
  },
  "sortBy": "newest",
  "maxItems": 200
}
```

A filter name or value the category does not have fails the run before anything is charged, and the status record lists what is wrong.

#### 4. Real estate in a district

```json
{
  "category": "nieruchomosci/mieszkania/sprzedaz",
  "location": "Warszawa",
  "districtId": 359,
  "priceTo": 900000,
  "maxItems": 100
}
```

`359` is Wola. Districts are not recognised by name: run any search in the city once and read the `districtId` and `district` fields of the results (Warsaw: `351` Śródmieście, `353` Mokotów, `359` Wola, `373` Ursynów).

#### 5. Use one search copied from OLX

```json
{
  "startUrls": ["https://www.olx.pl/warszawa/q-rower/"],
  "enrichDetails": true,
  "includeViews": true,
  "maxItems": 100
}
```

Plain strings and `{ "url": "..." }` objects both work. Search URLs replace every search field. Several URLs in one run share de-duplication and `maxItems`.

#### 6. Estimate before you collect

```json
{
  "query": "iphone 13",
  "countOnly": true
}
```

Returns one `estimate` record with `estimatedTotal`. It is free.

#### 7. New listings since the last run (schedule it)

```json
{
  "category": "elektronika",
  "mode": "monitor",
  "seenStoreName": "my-olx-monitor",
  "maxItems": 500
}
```

Save this input as an Actor Task and attach an [Apify Schedule](https://docs.apify.com/platform/schedules). Details are in the monitoring section below.

#### 8. Call the synchronous API

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/ziomixshot~olx-pl-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "rower",
    "location": "Kraków",
    "maxItems": 100
  }'
```

The response is the list of dataset items. When the input is wrong, the list holds one `status` record with the reason instead of listings, so a script can tell an error from an empty result.

The Actor also works through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so agents can read the input and output schemas and call it.

### Input

At least one of `query`, `category`, `categoryId`, `location`, `regionId`, `cityId` or `startUrls` is required. The full description of every field is in the [input form](https://apify.com/ziomixshot/olx-pl-scraper/input-schema). A field the Actor does not know (for example a typo) is rejected when the run starts.

| Field | Description |
|---|---|
| `query` | Search phrase, for example `iphone 13`. |
| `category` | Category name or URL path: `Elektronika`, `elektronika/telefony`, `motoryzacja/samochody`. A pasted OLX category URL also works. |
| `location` | City or voivodeship: `Kraków`, `Warszawa`, `Mazowieckie`. |
| `distance` | Radius around the city in km (0, 2, 5, 10, 15, 30, 50, 75, 100); needs a city in `location` or `cityId`. |
| `categoryFilters` | Filters of the chosen category as a JSON object, for example `{"filter_enum_petrol":["diesel"]}`. List them with `listFilters`. |
| `priceFrom`, `priceTo` | Price range in PLN, inclusive. Listings without a price are excluded when a limit is set. |
| `ownerType` | `any`, `private` or `business`. |
| `onlyWithPhotos` | Only listings with at least one photo ('Tylko ze zdjęciem' on olx.pl). |
| `onlyWithDelivery` | Only listings with OLX delivery ('Tylko z przesyłką' on olx.pl); verified per card against `olxDelivery`. Cannot be combined with `location`, `regionId`, `cityId`, `districtId` or `distance`: OLX then lists offers from all of Poland (local ones first), so the run stops with `INVALID_INPUT`. |
| `sortBy` | `relevance`, `newest`, `priceAsc` or `priceDesc`. |
| `maxItems` | Hard limit of returned listings and charges, shared by all `startUrls` (default 100). |
| `includePromoted` | OLX appends promoted cards above the page limit; `false` skips them (default `true`). |
| `enrichDetails` | Fetch the listing details; each listing also triggers the `listing-details` event. |
| `includeViews` | Add the view count (needs `enrichDetails`). `null` when OLX does not return it. |
| `includeRawData` | Add `raw`, the unchanged OLX payload of the listing. |
| `mode`, `seenStoreName`, `seenIdsKey`, `stopMonitorOnAllSeenPages`, `trackViews` | Monitoring, see below. |
| `countOnly` | Return only the number of matching listings (free). |
| `listFilters` | Return the filters of the category instead of listings (free). Needs `category` or `categoryId`. |
| `startUrls` | Search URLs copied from OLX, as strings or `{url}` objects. They replace all search fields above, including `?courier=1` ('Tylko z przesyłką') and `search[photos]=1`. A URL OLX cannot fully resolve (for example an unknown district) is rejected. |
| `categoryId`, `regionId`, `cityId`, `districtId` | OLX numeric IDs, for when you already know them. `category` and `location` are easier. `districtId` needs a city. |

`category` and `categoryId` cannot be combined, and neither can `location` with `regionId` or `cityId`; the run stops with an explanation instead of guessing.

### Output

Every listing is one dataset item. The dataset has an `Overview` view, an `Enriched details` view (with `enrichDetails`) and a `Category filters` view (with `listFilters`). The **Overview** table also shows `status` and `estimate` records.

```json
{
  "recordType": "listing",
  "id": 1096944000,
  "url": "https://www.olx.pl/d/oferta/iphone-14-pro-max-128gb-bateria-100-gwarancja-12-miesiecy-CID99-ID1ceFfa.html",
  "title": "iPhone 14 PRO MAX 128GB BATERIA 100% GWARANCJA 12 miesiecy !!!",
  "description": "iPhone 14 PRO MAX 128GB ...",
  "categoryId": 2298,
  "categoryType": "electronics",
  "price": 2099,
  "currency": "PLN",
  "priceLabel": "2 099 zł",
  "createdAt": "2026-09-08T11:50:18Z",
  "lastRefreshedAt": "2026-09-30T22:39:05Z",
  "validTo": "2026-10-08T11:50:18Z",
  "promoted": false,
  "city": "Warszawa",
  "region": "Mazowieckie",
  "district": "Wola",
  "latitude": 52.23725,
  "longitude": 20.96608,
  "coordinatesExact": false,
  "seller": { "type": "business", "registeredAt": "2025-12-07T16:43:05Z" },
  "photos": ["https://ireland.apollo.olxcdn.com:443/v1/files/nowebhf71bsy-PL/image;s=800x600"],
  "params": [{ "key": "state", "name": "Stan", "value": "used", "label": "Używane" }],
  "olxDelivery": true,
  "scrapedAt": "2026-10-01T03:13:10Z"
}
```

The example is a real record, abbreviated (some fields, photos and parameters are left out).

Fields of every `listing` item: `recordType`, `id`, `url`, `title`, `description` (plain text), `categoryId` (the listing's own, most specific category), `categoryType`, `price`, `currency`, `priceLabel`, `salary` (jobs only: `from`, `to`, `currency`, `period`, `gross`, `arranged`), `createdAt`, `lastRefreshedAt`, `validTo`, `promoted`, `highlighted`, `urgent`, `topAd`, `city`, `cityId`, `region`, `regionId`, `district`, `districtId`, `latitude`, `longitude`, `coordinatesRadius`, `coordinatesExact`, `seller` (`id`, `name`, `type`, `registeredAt`, `shopSubdomain`), `photos` (800x600), `params` (`key`, `name`, `value`, `label`), `olxDelivery`, `scrapedAt`. A value OLX does not provide is `null`.

Added by `enrichDetails`: `detailsFetched`, `pushedUpAt`, `omnibusPushedUpAt`, `keyParams`, `externalUrl`, `gpsrAvailable`, `priceNegotiable`, `priceArranged`, `previousPrice`, in `seller`: `companyName`, `about`, `logoUrl`, `lastSeenAt`, `isOnline`, and with `includeViews` the field `views`. A listing OLX no longer serves (404 or not active) is skipped and not charged; the count is `detailsUnavailable` in the run status.

Other record types, always free:

- `status`: the run ended because of your input and returned no listings. Fields: `status` (`INVALID_INPUT`, `URL_NOT_FULLY_RESOLVED`, `FILTER_VERIFICATION_FAILED`, `SEEN_STATE_INVALID`), `message` (what is wrong and how to fix it), `details`, `scrapedAt`.
- `estimate`: result of `countOnly`: `estimatedTotal`, `sources`, `note`.
- `filter`: result of `listFilters`: `categoryId`, `name`, `label`, `type`, `unit`, `values`, `categoryFiltersExample`, `note`.

#### Run status

The `OUTPUT` record of the key-value store describes the run: `status` (`OK`, `PARTIAL`, `INVALID_INPUT`, `URL_NOT_FULLY_RESOLVED`, `FILTER_VERIFICATION_FAILED`, `SEEN_STATE_INVALID`, `UPSTREAM_ERROR`), counters (`cardsRead`, `emitted`, `duplicates`, `alreadySeen`, `promotedSkipped`, `rejected`, `predicateViolations`, `detailsUnavailable`, `detailsFailed`, `viewsMissing`, `chargeLimitReached`) and `jobs[]` per search (`criteria` as sent to OLX, `expectedTotal` reported by OLX, `coverage`, `partitions`, `truncatedPartitions`, `failedPages`). Input and filter errors end the run without listings and without charges (`message` explains why). `PARTIAL` means some pages or details failed after all retries; the returned records are still valid. While a run is going, the status line in Console shows `Collected N of M listings`; at the end it shows the result, for example `OLX reports 0 listings for this search`.

### Monitoring new listings

`mode: monitor` returns only listings whose ID was not reported by earlier runs with the same `seenStoreName` and `seenIdsKey` (a named key-value store in your account). The first run returns everything up to `maxItems`; later runs return only new IDs.

- It always reads newest first and ignores `sortBy`, does not split the search and skips promoted cards.
- It reads pages until `stopMonitorOnAllSeenPages` consecutive pages hold nothing new.
- State is saved only for listings that were actually returned, also after a failed run. A corrupted state record ends the run with `SEEN_STATE_INVALID` instead of starting over. Up to 500000 newest IDs are kept.
- It detects new IDs only, not price changes or expired listings. OLX sorts by refresh time, so an old listing that a seller has just refreshed is reported as new if its ID was never reported before; compare `createdAt` with `scrapedAt` to tell fresh listings apart.
- One query exposes about 1050 listings. In busy categories more new listings can appear between two runs than that window holds (category 99 gets about 400 per hour), so schedule the run often enough.

#### Tracking page views (`trackViews`)

`mode: monitor` with `trackViews: true` also returns a `change` record for every offer whose page views changed since the previous run: `recordType: "change"`, `metric: "views"`, `id`, `url`, `title`, `previous`, `current`, `delta` and `changedAt` (when the run detected it). New listings are still returned as `listing` items.

- It checks the offers on the pages the monitor reads (the newest ones, up to the first page without new IDs), not every offer ever seen. An offer that falls off those pages is not checked.
- The first run (or the first run an offer is seen) only stores a baseline counter; a change needs a stored value to compare with.
- Counters are stored next to the seen IDs, in the record named like `seenIdsKey` plus `_VIEWS` (up to 200000 newest offers). A corrupted record ends the run with `SEEN_STATE_INVALID`.
- `maxItems` limits listings and change records together. A change beyond the limit is kept for the next run.
- If the OLX views service fails, the run ends `PARTIAL` (`viewsFailed` in `OUTPUT`) and the counters stay as they were. `OUTPUT` also has `viewsTracked` and `viewChanges`.
- The views endpoint is unofficial and anonymous; OLX can change it without notice.

### Estimate (`countOnly`)

Returns one item with `recordType: "estimate"` and `estimatedTotal`, the count OLX reports (`visible_total_count`). Filters are still verified. With several `startUrls` the result is the sum of the searches (overlapping listings are counted once per search). It is not charged.

### Limits and notes

- One OLX query exposes about 1050 listings. For `maxItems` above 1000 the Actor splits by region and then by price (median). Sorting then applies only inside each part, listings without a price can be missed after a price split, and `coverage` (records against OLX's own count) can exceed 1. `truncatedPartitions` above 0 means more than 1000 listings with the same price that cannot be separated.
- `price` is the amount OLX stores and `priceLabel` is how OLX shows it. `price: 0` with the label `Za darmo` means free, with `Zamienię` a swap. Jobs have no `price`; the pay is in `salary`. Sorting by price puts symbolic prices (1 zł) first, so set `priceFrom` to skip them.
- OLX matches search phrases loosely: a phrase with a typo or a made-up word still returns near matches. Check the count with `countOnly` before a large run. A phrase can have at most 150 characters.
- Sorting applies to organic listings. OLX appends promoted cards (`promoted: true`) out of order; in tests all price-sorting violations involved a promoted card. Use `includePromoted: false` for a strictly sorted stream. `newest` is based on the refresh time, so a few older listings pushed up by their sellers can appear slightly out of `lastRefreshedAt` order.
- `location` resolves a city or voivodeship name through OLX (`Kraków` and `Kraków, Małopolskie` both work). The run stops with `INVALID_INPUT` when OLX only knows a different place under that name, instead of searching there. Several places share some names (for example more than one town called Wola); the run log prints the region and city IDs that were used, and `jobs[].criteria` in `OUTPUT` has them too. Use `startUrls` or `cityId` when you need an exact place.
- The category list is a snapshot of the OLX category tree; `categoryId` always works for a category added later.
- A card that does not expose an attribute is skipped when that attribute is checked against your filters.
- The Actor uses OLX's own web interface endpoints, which are unofficial and can change without notice. View counts come from such an endpoint and are optional.
- Runs use Apify residential proxies in Poland (included in the platform usage cost).

### Legal notice

This Actor collects data that OLX.pl shows publicly. OLX's [Terms of Service](https://www.olx.pl/regulamin/) restrict using the content of the service and aggregating its data for passing it on to third parties. You are responsible for using the data lawfully and in line with OLX's terms. Listings contain personal data of sellers (name, ID, approximate location), so GDPR rules apply to how you store and use them. Phone numbers are never returned. The Actor is not affiliated with OLX.

### Support

Report problems or request fields through the Issues tab of the Actor.

# Actor input Schema

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

For example iphone 13. Leave empty to browse a whole category or place.

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

Category name or URL path, for example Elektronika, elektronika/telefony or motoryzacja/samochody. A name used by several categories (for example Telefony) is refused with the list of paths to choose from. Run with Show category filters to list the filters of a category.

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

City or voivodeship, for example Kraków, Warszawa or Mazowieckie. Districts are not recognised by name: use District ID (Advanced) together with a city.

## `distance` (type: `integer`):

Radius around the city in km: 0, 2, 5, 10, 15, 30, 50, 75 or 100 (0 means the city only). Needs Location (a city) or City ID.

## `categoryFilters` (type: `object`):

OLX filters of the chosen category, for example {"filter\_enum\_petrol":\["diesel"],"filter\_float\_year":{"from":2015}}. A name or value the category does not have fails the run before any listing is charged.

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

Minimum price in PLN, inclusive. Listings without a price are excluded when a price limit is set.

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

Maximum price in PLN, inclusive.

## `ownerType` (type: `string`):

Show only private sellers or only businesses.

## `onlyWithPhotos` (type: `boolean`):

Return only listings that have at least one photo.

## `onlyWithDelivery` (type: `boolean`):

Return only listings with OLX delivery (the 'Tylko z przesyłką' checkbox on olx.pl). Cannot be combined with a location: OLX then searches all of Poland.

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

Newest uses the refresh time, as on OLX.

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

Hard limit of unique listings returned and charged.

## `includePromoted` (type: `boolean`):

Promoted listings match your filters too. Turn off to return organic results only.

## `enrichDetails` (type: `boolean`):

Fetch every offer page and add push-up time, price flags, seller company data, key parameters and external link. Each enriched record is also charged the listing-details event; offers OLX no longer serves are skipped and not charged. Phone numbers are never returned.

## `includeViews` (type: `boolean`):

Add the number of page views to each enriched record. Requires Fetch offer details. When OLX returns no count the field is null.

## `includeRawData` (type: `boolean`):

Add the unmodified OLX offer as raw (the detail when enriched, otherwise the list card).

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

Scrape returns every matching listing. Monitor returns only listing IDs not reported by earlier runs that use the same store and key; it reads the newest first, skips promoted cards and ignores the sort option.

## `seenStoreName` (type: `string`):

Named key-value store shared by monitor runs. Use one name per monitored search. Empty uses the run's default store, which does not keep history across independent runs.

## `seenIdsKey` (type: `string`):

Record in the store that holds the reported IDs (up to 500000 newest IDs are kept).

## `stopMonitorOnAllSeenPages` (type: `integer`):

Monitor stops when this many consecutive pages contain no new organic listing. Raise it when new listings may appear further down the list.

## `trackViews` (type: `boolean`):

Monitor only. Also returns a change record for every offer whose page views changed since the previous run. It checks the offers on the pages the monitor reads; the first run only stores the counters. Counters are kept next to the seen IDs, in the record named like the seen-IDs key plus \_VIEWS (up to 200000 newest offers). Charged as the listing-change event.

## `countOnly` (type: `boolean`):

Return only the number of listings OLX reports for the search, without collecting or charging for listings. Use it to estimate the cost of a run before you start it. Filters are still verified.

## `listFilters` (type: `boolean`):

List the filters of the chosen category (names, labels, allowed values, ready-to-paste examples for Category filters) instead of collecting listings. Needs Category or Category ID. Free.

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

Copied OLX.pl search or category URLs, one per line. When set, they replace Query, Category, Location and the other search fields, so fill either the URLs or the fields. A URL with a part OLX cannot resolve (for example an unknown district) is rejected.

## `categoryId` (type: `integer`):

OLX category ID, for example 99 for Elektronika or 84 for Samochody osobowe. Use it instead of Category when you already know the ID.

## `regionId` (type: `integer`):

OLX region (voivodeship) ID, for example 2 for Mazowieckie. Use Location to give a place by name.

## `cityId` (type: `integer`):

OLX city ID, for example 17871 for Warszawa. Use Location to give a place by name.

## `districtId` (type: `integer`):

OLX district ID. Needs Location or City ID. The IDs are in the districtId field of the results.

## Actor input object example

```json
{
  "query": "rower",
  "category": "elektronika/telefony",
  "location": "Kraków",
  "distance": 0,
  "ownerType": "any",
  "onlyWithPhotos": false,
  "onlyWithDelivery": false,
  "sortBy": "relevance",
  "maxItems": 100,
  "includePromoted": true,
  "enrichDetails": false,
  "includeViews": false,
  "includeRawData": false,
  "mode": "scrape",
  "seenIdsKey": "OLX_SEEN_IDS",
  "stopMonitorOnAllSeenPages": 1,
  "trackViews": false,
  "countOnly": false,
  "listFilters": false,
  "startUrls": [
    "https://www.olx.pl/warszawa/q-rower/"
  ]
}
```

# Actor output Schema

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

Listings found by the run, one dataset item per listing. A run that ended on your input holds one status record with the reason; countOnly holds one estimate record.

## `filters` (type: `string`):

Filters of the category, from a run with Show category filters.

## `status` (type: `string`):

Status record with counters (cards read, duplicates, rejected cards, failed pages) and the error code when the input or filters were invalid.

# 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 = {
    "query": "rower",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("ziomixshot/olx-pl-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 = {
    "query": "rower",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("ziomixshot/olx-pl-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 '{
  "query": "rower",
  "maxItems": 100
}' |
apify call ziomixshot/olx-pl-scraper --silent --output-dataset

```

## MCP server setup

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