# OLX.pl Scraper (`lowlanddata/olx-pl-scraper`) Actor

OLX.pl is Poland's biggest marketplace, and popular searches return more listings than the site will page through past its 1,000-result cap. It splits queries by price band to pull the full set: prices in grosz plus category attributes like year and mileage. No seller identity collected.

- **URL**: https://apify.com/lowlanddata/olx-pl-scraper.md
- **Developed by:** [Lowland Data](https://apify.com/lowlanddata) (community)
- **Categories:** E-commerce, Automation, Business
- **Features:** Limited permissions
- **Stats:** 5 total users, 2 monthly users, 99.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 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

## OLX.pl Scraper

A popular search on OLX.pl, Poland's biggest marketplace, returns more listings than the site will page through. OLX stops at 1,000 results, so anyone who wants a whole category ends up hand-splitting queries by price.

This actor does the splitting for you: it probes the result count, cuts the query into price bands until each fits under the cap, and returns the union as one dataset. Prices arrive as integers in grosz with the currency taken from each listing, descriptions and category attributes intact, and no seller identity anywhere in the output.

**Live health record:** [lowlanddata.com/status/olx-pl-scraper](https://lowlanddata.com/status/olx-pl-scraper/) - 30-day success rate and daily canary results, failures included. Full input/output reference: [tool page](https://lowlanddata.com/tools/olx-pl-scraper/).

No login, no CAPTCHA solving, no private endpoints: the actor reads what OLX shows a logged-out visitor. The only seller field is whether the listing is from a business or a private seller; names, profile photos, contact routes and exact map coordinates are not collected.

### Quick start (30 seconds)

1. Put what you'd type in the OLX search box into **searchQuery** (e.g. `rower górski`).
2. Click **Start**. That's the whole minimum setup.
3. When the run finishes, open the dataset's **Overview** tab for a clean table, or **Export** it as CSV/Excel/JSON.

Optional knobs: paste olx.pl search links instead of typing a query, several queries in one run, a city or region, private or business sellers, item condition, a price band in złoty and newest-first sorting for monitoring. Any input works on a daily Schedule.

### What you can build with it

- **Watch a niche for underpriced listings.** Run `searchQuery: "rower górski"` with `priceMaxPln: 800` and `sortBy: "date"` hourly: every new listing arrives with `priceGrosz` parsed and `negotiable` flagged, ready for your deal filter.
- **Scrape the searches you already use.** Set the filters on olx.pl, copy the address from the browser and paste it into `startUrls`: the run returns exactly what that page lists, as many links as you like in one run.
- **Compare several products in one go.** `searchQueries` takes a list (`iphone 14`, `iphone 15`, `iphone 15 pro`) with the same city, seller type, condition and price filters for all of them; an offer two searches both find comes back once.
- **Price a used car with real specs.** Category attributes come through per listing: `rok_produkcji`, `przebieg`, `paliwo`, `skrzynia`, a dataset of comparables with mileage and year, not just titles.
- **Map business vs. private supply.** The `sellerType` flag on every listing tells you how much of any category is professional traders, market structure no OLX page shows you.
- **Feed an AI agent or a pipeline.** Every field is structured and predictable, so an assistant can consume it directly with no parsing step.

### What you get

Each listing is one dataset item:

```json
{
  "listingId": "1090000001",
  "url": "https://www.olx.pl/d/oferta/rower-gorski-kross-level-3-CID767-ID14zZz1.html",
  "title": "Rower górski Kross Level 3 jak nowy",
  "description": "Sprzedam rower górski, mało używany, stan bardzo dobry.",
  "priceGrosz": 150000,
  "currency": "PLN",
  "negotiable": true,
  "postedAt": "2026-08-18T17:40:00+02:00",
  "refreshedAt": "2026-08-20T09:12:00+02:00",
  "city": "Kraków",
  "region": "Małopolskie",
  "categoryId": 767,
  "attributes": { "state": "Używane", "typ": "Górskie" },
  "sellerType": "private",
  "deliveryAvailable": true,
  "imageUrls": ["https://ireland.apollo.olxcdn.com/v1/files/example/image;s=1000x750"]
}
```

Category-specific specs come through in `attributes`: condition (`state`) on any item; year, mileage, fuel and transmission on vehicles; floor area and room count on property. Only a whitelist of non-personal attribute keys passes; anything else in the listing is dropped.

Field notes, so you know exactly what you are buying:

- `priceGrosz` is the asking price in grosz (1/100 PLN), so `150000` = 1 500 zł. Listings priced "za darmo" or "zamienię" carry no price.
- `postedAt` vs `refreshedAt`: sellers bump listings; `refreshedAt` is why an old listing can appear in a newest-first run.
- `city`/`region` are municipality-level. Exact coordinates exist in OLX's data and are deliberately never collected.
- `description` is the seller's full text with the site's HTML markup stripped to plain lines.
- `attributes` values are the site's Polish display labels ("Używane", "Benzyna"), exactly what a Polish buyer sees.

### How much does it cost to scrape OLX?

$3.00 per 1,000 listings delivered, pay-as-you-go, no subscription, and you pay per result rather than per hour. A run that finds nothing still costs the $0.005 actor start. In plain dollars:

- **100 listings ≈ $0.30**, a daily niche watch.
- **500 listings ≈ $1.50**, a solid market snapshot.
- **A 5,000-listing crawl ≈ $15.00**, a full category across price bands, deduplicated.

The price is all-inclusive: your runs' platform usage is covered by it, no separate compute or proxy charges, even on large split crawls. Datacenter proxies are sufficient, no residential proxy surcharge needed.

Free-plan runs are limited to a sample of 5 items, enough to evaluate the output format against your real query.

### Not technical? Let your AI assistant set it up

Copy this into ChatGPT, Claude or any AI assistant, fill in the one line, and follow the conversation:

```text
Help me set up the "OLX.pl Scraper" actor on Apify
(https://apify.com/lowlanddata/olx-pl-scraper). Guide me one step at a time.

What I want to watch: [E.G. "mountain bikes under 1500 zł in good condition"]

Guide me to:
1. Propose my input values: searchQuery (what I'd type in the OLX search box),
   an optional priceMinPln/priceMaxPln band, sortBy "date" for newest-first
   monitoring, and maxItems.
2. Create a free Apify account (apify.com), open the actor page, paste the values
   into the Input form, and start a run.
3. Set up a daily Schedule in the Apify Console with the same input, plus an email
   or Slack integration so new results reach me automatically.
4. Show me how to export results as CSV/Excel, or read them from the API if I code.
5. If the results are what I wanted, remind me at the end to leave a quick rating on the actor page, and to report anything broken or missing on its Issues tab.
```

### Input

| Field                | Description                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `searchQuery`        | What you'd type in the OLX search box. Leave it out when you paste links or re-check offers through `listingIds`; with those it is ignored.                                                                                                                                                                                                                                                     |
| `listingIds`         | Re-check offers you already know instead of searching: offer IDs (the `listingId` of every row), the offers' full addresses or their `ID…` codes, one per line. Each comes back exactly as a search result would, plus the site's own `status`. An offer that is gone from the site is skipped, named in the log and not billed. When given, the search fields and links are ignored. Up to 50. |
| `categoryId`         | Numeric OLX category id to scope the search. A pasted category link does the same without looking the number up.                                                                                                                                                                                                                                                                                |
| `searchQueries`      | More search queries for the same run, one per line, all with the same category, place, seller type, condition and price filters. Up to 50; an offer found twice comes back once.                                                                                                                                                                                                                |
| `startUrls`          | olx.pl search pages to scrape, as you copy them from the browser: a category, a city, or a search with its filters. Each link is scraped as the site shows it, so the form fields below stand down; the run status says so. Search pages only. Up to 50.                                                                                                                                        |
| `location`           | One city or region, written as OLX writes it in its addresses: `krakow`, `warszawa`, `malopolskie`. Capitals, spaces and Polish letters are fine ("Nowy Sącz"). An unknown word stops the run with a message; a pasted link always works.                                                                                                                                                       |
| `sellerType`         | `any` (default), `private` or `business`.                                                                                                                                                                                                                                                                                                                                                       |
| `condition`          | Any of `new`, `almost-new`, `refurbished`, `used`, `damaged`. Several mean "any of these". Offers listed without a condition are left out when you pick one.                                                                                                                                                                                                                                    |
| `priceMinPln`        | Only listings costing at least this many złoty.                                                                                                                                                                                                                                                                                                                                                 |
| `priceMaxPln`        | Only listings costing at most this many złoty.                                                                                                                                                                                                                                                                                                                                                  |
| `sortBy`             | `date` (newest first, default), `price_asc`, `price_desc`, or `relevance`.                                                                                                                                                                                                                                                                                                                      |
| `postedAfter`        | Only listings posted on or after this date (YYYY-MM-DD). Stops early with newest-first sorting.                                                                                                                                                                                                                                                                                                 |
| `postedBefore`       | Only listings posted on or before this date (YYYY-MM-DD).                                                                                                                                                                                                                                                                                                                                       |
| `maxItems`           | Stop after this many listings (default 1000).                                                                                                                                                                                                                                                                                                                                                   |
| `proxyConfiguration` | Proxy settings; keep Apify proxy enabled.                                                                                                                                                                                                                                                                                                                                                       |

A run minimally needs a `searchQuery` (or `searchQueries`), a `categoryId`, search links in `startUrls` or a list of `listingIds`; invalid combinations (like an inverted price band) fail immediately with the reason in the run's status message.

#### Re-checking offers you already have

Put their IDs (or their addresses) into `listingIds` and nothing else: the run asks the site for each offer by its number and returns it in exactly the shape a search result has - same fields, same values - plus `status`, the site's own word for its state. A price change shows up in the price field; an offer that has been sold, has expired or was taken down is not on the site any more - the run skips it, says so in the log and the status, and does not bill it. Schedule such a run and you have a watch on the exact offers you are following. The `ID…` code at the end of an OLX address is the offer number in base 62, so pasting addresses works as well as pasting numbers.

#### Using search links

Open olx.pl, search, pick a category or a city, set the filters you want (price, condition, private or business, region, distance, the category's own filters) and copy the address from the browser into `startUrls`. Several links run one after the other, an offer two of them list comes back once, and `maxItems` counts the whole run. Because a link already says everything, `searchQuery`, `categoryId`, `location` and the other form fields are ignored when links are given; the run status lists which ones.

A few things to know:

- A link with a place in its path (`olx.pl/krakow/q-rower/`) is looked up on OLX and fails with a clear message if OLX does not know the word. A link with the place chosen through the site's filters carries the numbers itself.
- Filters the open data has no equivalent for are left out, and the log names them.
- The category list is a snapshot of olx.pl's own: a category OLX added last week may not be recognised yet. The `categoryId` in any dataset row works as input too.
- A link to a single offer is refused with a pointer to `listingIds`.

#### Choosing places, sellers and conditions without a link

`location` takes the word OLX uses in its addresses (`olx.pl/krakow/` gives `krakow`), for a city or a region. `sellerType` and `condition` apply to every query of the run. A newest-first run with `postedAfter` follows OLX's refresh order, so bumped old offers do not end it early; only offers created inside the window are kept.

### Use it from your code

Run the actor and get items straight back with one HTTP call (fine for scoped runs up to ~5 minutes):

```bash
curl "https://api.apify.com/v2/acts/lowlanddata~olx-pl-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -X POST -H "Content-Type: application/json" \
  -d '{"searchQuery": "rower górski", "maxItems": 100}'
```

Node.js:

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('lowlanddata/olx-pl-scraper').call({
  searchQuery: 'rower górski',
  maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lowlanddata/olx-pl-scraper").call(
    run_input={"searchQuery": "rower górski", "maxItems": 100})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

For large split crawls, start the run asynchronously and fetch the dataset when the finished-run webhook fires. Schedules (e.g. a daily price snapshot), webhooks and the Make/Zapier/n8n integrations all work out of the box: this is a standard Apify actor.

### Use it with AI agents (MCP)

Claude, Cursor and other MCP-capable agents can run this scraper as a tool through Apify's hosted MCP server: the agent fills in the search itself, starts the run and reads the results, no glue code.

Claude Code:

```bash
claude mcp add apify --transport http "https://mcp.apify.com?actors=lowlanddata/olx-pl-scraper"
```

Cursor or Claude Desktop (add a custom connector / MCP server with this URL):

```text
https://mcp.apify.com?actors=lowlanddata/olx-pl-scraper
```

**Want the whole family at once?** Point one connector at every tool in the EU Marketplaces bundle:

```text
https://mcp.apify.com?actors=lowlanddata/kleinanzeigen-scraper,lowlanddata/marktplaats-scraper,lowlanddata/tweedehands-scraper,lowlanddata/olx-pl-scraper,lowlanddata/olx-ro-scraper,lowlanddata/olx-pt-scraper,lowlanddata/willhaben-scraper,lowlanddata/finn-no-scraper,lowlanddata/tori-fi-scraper,lowlanddata/blocket-se-scraper,lowlanddata/dba-dk-scraper,lowlanddata/gumtree-uk-scraper,lowlanddata/vinted-scraper,lowlanddata/bol-com-scraper,lowlanddata/subito-scraper,lowlanddata/bazos-cz-scraper,lowlanddata/bazos-sk-scraper,lowlanddata/olx-bg-scraper,lowlanddata/olx-ua-scraper,lowlanddata/willhaben-car-scraper,lowlanddata/kleinanzeigen-free-finds,lowlanddata/olx-listing-watch,lowlanddata/marktplaats-new-listing-alerts,lowlanddata/tweedehands-new-listing-alerts,lowlanddata/kleinanzeigen-deal-radar
```

Sign in with your Apify account when prompted. Runs are billed to it. Setup details per client: [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp), or start from this actor's own MCP page: [apify.com/lowlanddata/olx-pl-scraper/api/mcp](https://apify.com/lowlanddata/olx-pl-scraper/api/mcp).

Prompts that work once connected:

- "Search OLX Poland for 'rower górski' under 1500 zł and summarize the price distribution by condition."
- "Get 200 newest iPhone 15 listings from OLX.pl and flag private sellers asking below the median."
- "Watch OLX for 'przyczepa kempingowa' and tell me when something under 20 000 zł appears."

### Beyond the 1,000-result window

OLX serves at most 1,000 results per query, however you page. This actor splits bigger queries into price bands automatically, crawls each band and deduplicates by listing id, so a 5,000-listing category comes back complete without you thinking about the window. Shards that cannot be narrowed further are fetched to the window's edge and reported honestly.

### Is it legal to scrape OLX?

Public listing data (prices, descriptions, categories, locations) is public commercial information, and this scraper is built so that the hard part of the question never arises: **no personal data enters your dataset in the first place.** Poland's data-protection authority (UODO) follows the same GDPR baseline as the rest of the EU; an output that carries none of the seller's personal data is the point of this actor, not an afterthought.

Structurally, the extractor maps a fixed whitelist of fields out of the listing payload. The seller block, the contact block and the map coordinates are never read into the output: the only seller-derived value is the business-vs-private flag. Requests are paced, load on the site is kept negligible, and no anti-bot protection is bypassed.

One honest limit: titles and descriptions are the seller's own words, delivered as-is (markup stripped). If a seller chooses to type contact details into their listing text, that text is not rewritten: the guarantee covers the data fields, not the content sellers publish about themselves.

This actor is an independent tool. It is not affiliated with, endorsed by or sponsored by OLX or its owners, and trademarks belong to their respective holders.

### Is there an OLX API alternative?

OLX publishes no public API for reading listings (the partner API serves advertisers posting them). This actor is the practical alternative: the same listings as structured JSON through one HTTP call (`run-sync-get-dataset-items`), on a schedule, or as an MCP tool for AI agents, with the GDPR question already answered in the data itself.

### Does OLX block scrapers?

OLX serves its listings openly to ordinary requests, and this actor stays inside that welcome: paced requests, standard datacenter proxies, load kept negligible. No CAPTCHA fights, no bot-wall cat-and-mouse, which is also why runs are fast and reliable enough for daily schedules.

### How do I monitor OLX prices?

Set `sortBy: "date"` with your query, cap `maxItems` to a page or two, and add a daily (or hourly) Schedule in the Apify Console with an email/Slack integration on the runs: every new listing lands in your inbox with the price already parsed to grosz. The AI-assistant prompt above walks a non-technical user through exactly this setup. Even tighter: set `postedAfter` to yesterday's date: the dataset then contains only the new listings, nothing to dedupe on your side.

### FAQ

**Can I get seller names or phone numbers?** No, by design. That is the product: data you can store, share and process without a GDPR review. The output tells you only whether the seller is a business or a private person.

**Why does an old listing show up in a newest-first run?** Sellers bump listings; OLX orders by refresh time. Compare `postedAt` with `refreshedAt` to tell fresh listings from bumped ones.

**Can I get only the newest listings?** Yes. Set `postedAfter` to a date (yesterday, say) and the dataset contains only listings posted since then. With newest-first sorting the run stops paging as soon as it provably reaches older listings, so a daily watch stays fast and cheap.

**How fresh is the data?** Live at run time: every run queries OLX directly. For continuous freshness, schedule the actor.

**Can I export to Excel or CSV?** Yes. Every dataset exports as CSV, Excel, JSON or XML from the Apify Console or API.

**What happens above 1,000 results?** The actor splits the query into price bands, crawls each and dedupes: see "Beyond the 1,000-result window" above.

**Does it cover other OLX countries?** This actor is OLX.pl only, on purpose, one site done completely. Other OLX markets may follow as separate actors.

**Does it work with Make, Zapier or n8n?** Yes. It is a standard Apify actor; all platform integrations, webhooks and schedules apply.

**Is there an official OLX.pl API for reading listings?** No. OLX's partner API is for advertisers posting ads, not for reading them. This actor returns the same listings as structured JSON instead: one HTTP call, a schedule, or an MCP tool.

**What does it cost to scrape 1,000 listings from OLX.pl?** $3.00, pay-as-you-go. There is no subscription, and empty or failed runs cost nothing.

**How are prices returned: złoty or grosz?** Both signals are there: `priceGrosz` holds the amount in grosz (1/100 PLN) and `currency` is `"PLN"`, so `150000` means 1 500 zł. Listings marked "za darmo" or "zamienię" carry no price.

**Do I need residential proxies for OLX.pl?** No. Standard datacenter proxies through the default Apify proxy setting are enough, which keeps runs cheap.

**Can I limit results to one city, like Warsaw or Kraków?** Yes. Put `krakow` (or `warszawa`, `malopolskie` for a region) in `location`, or paste a search link with the place chosen on olx.pl. Every listing also carries `city` and `region`.

**Can I paste an olx.pl search link?** Yes, into `startUrls`: category pages, city pages and searches with filters all work, up to 50 links in one run. Single-offer links go into `listingIds`.

**Can I run several searches at once?** Yes. List them in `searchQueries` (one per line) or paste several links; results are merged and deduplicated by listing id, and `maxItems` counts the whole run.

**Are the attribute values in Polish or English?** Polish, the site's own display labels, e.g. "Używane" or "Benzyna". They are exactly what a buyer sees on olx.pl, so they match any Polish-language downstream logic.

**How many listings can a single run return?** OLX caps any one query at 1,000 results. The actor splits larger queries into price bands and dedupes by listing id, so category-scale crawls of several thousand items come back complete.

**What happens if OLX blocks the run halfway?** You keep everything collected before the block, and the run's status message says coverage was partial. Re-run later or narrow the query; a blocked start usually clears on retry with a fresh proxy session.

**Can I filter OLX.pl listings by posting date?** Yes. `postedAfter` and `postedBefore` take YYYY-MM-DD dates. With newest-first sorting, `postedAfter` also stops the run early, which keeps daily watches fast.

**Are listing photos included?** Each item carries `imageUrls` with the OLX CDN links. The actor links images rather than downloading them, so datasets stay small.

**Can I tell business sellers from private ones on OLX.pl?** Yes. `sellerType` on every listing marks it business or private, and the `sellerType` input limits a run to one of the two. It is the only seller-derived field in the output; names, avatars and contact routes never appear.

**Can Claude or another AI agent run this scraper?** Yes, through Apify's MCP server: the agent fills in the search, starts the run and reads the results itself. See the MCP section above for the one-line setup.

### Related scrapers

Working the European second-hand market? Same output discipline, same public health record:

- [Kleinanzeigen.de Scraper](https://apify.com/lowlanddata/kleinanzeigen-scraper), Germany's biggest classifieds site.
- [Marktplaats.nl Scraper](https://apify.com/lowlanddata/marktplaats-scraper), the Netherlands' biggest marketplace.
- [2dehands & 2ememain Scraper](https://apify.com/lowlanddata/tweedehands-scraper), Belgium's classifieds duo, one actor for both language sites.

### Troubleshooting

The actor fails fast with the reason in the run's status message:

- **"Provide a search query, a category id, search links in startUrls, or the listingIds to re-check."**: the run needs a scope; add a searchQuery, a categoryId or a search link.
- **"... was not found as a place on olx.pl."**: OLX does not know that word for `location`; use the word in OLX's own address for the city (`olx.pl/krakow/`) or paste a search link.
- **"... is a single offer, not a search page."**: put offer addresses in `listingIds` instead of `startUrls`.
- **"priceMinPln must not be higher than priceMaxPln."**: swap the two values.
- **"OLX blocked the run before any results could be fetched. This is usually temporary - retry in a few minutes."**: a temporary block on the first request; a retry usually lands on a clean proxy session.
- **"... then the site blocked further requests. Partial coverage ..."**: the run kept everything collected before the block; re-run later or narrow the query.
- **Fewer items than requested on a free plan**: the 5-item free sample cap; run on a paid Apify plan for full results.

### Support

Found an issue or missing a field you need? The fastest route is the actor's **Issues tab** - it is monitored and reports get fixed. For anything private, email **contact@lowlanddata.com**. This actor is actively maintained.

Working well for you? A **rating on this page** takes ten seconds and helps other buyers find it: it is also the clearest signal of what we should build next.

# Actor input Schema

## `searchQuery` (type: `string`):

What to search for on OLX.pl, exactly as you would type it in the site's search box, e.g. "rower górski" or "iphone 15". <b>Ignored when you paste search links or offer IDs below</b>; the run status says so.

## `searchQueries` (type: `array`):

More searches in the same run, one per line, with the same category, place, seller type, condition and price filters. An offer found by two searches comes back once. <b>Max listings counts the whole run</b>, and the searches run in the order given. Up to 50.

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

Paste search pages copied from olx.pl: a category, a city, a search with the filters you set on the site (price, condition, seller type, region, distance, category filters). Each link is scraped exactly as the site shows it, so the form fields below stand down for it. <b>Search pages only</b> - for single offers use Specific offer IDs. Up to 50.

## `listingIds` (type: `array`):

Re-check offers you already know instead of searching: one offer ID per line (the <code>listingId</code> of every dataset item), the offer's full address (its <code>ID…</code> code is that number in base 62), or the code alone. Each one comes back in exactly the shape a search result has, plus the site's own <code>status</code>. An offer that is gone from the site (sold, expired, removed) is skipped, named in the log and not billed. <b>When given, the search fields and links of this form are ignored</b> and the run status says which. Up to 50.

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

Numeric OLX category id to limit the search to. Easiest is to paste a category link into <b>OLX.pl search links</b> instead; the id also appears as <code>categoryId</code> in every dataset item. Empty = all categories.

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

Limit the search to one city or region, written the way OLX writes it in its addresses: <code>krakow</code>, <code>warszawa</code>, <code>malopolskie</code> (capitals, spaces and Polish letters are fine: "Nowy Sącz" works). When OLX does not know the word the run stops and says so; a pasted link with the place chosen on the site always works.

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

Private sellers only, businesses only, or both.

## `condition` (type: `array`):

Only offers in these conditions; pick several to include any of them. Empty = any condition. Offers listed without a condition are left out when you pick one.

## `priceMinPln` (type: `integer`):

Only include listings costing at least this many złoty.

## `priceMaxPln` (type: `integer`):

Only include listings costing at most this many złoty.

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

Order of results: date (newest first, best for monitoring), price_asc, price_desc, or relevance. A pasted link keeps its own order.

## `postedAfter` (type: `string`):

Only include listings posted on or after this date. With newest-first sorting the run stops early once older listings are reached. <b>Format: <code>YYYY-MM-DD</code></b> (for example <code>2026-09-08</code>) or a full ISO timestamp such as <code>2026-09-08T14:30:00Z</code>. Slash dates like <code>08/09/2026</code> are refused on purpose: they are read as September in Europe and August in the United States, and this actor will not guess which you meant.

## `postedBefore` (type: `string`):

Only include listings posted on or before this date. <b>Format: <code>YYYY-MM-DD</code></b> (for example <code>2026-09-08</code>) or a full ISO timestamp such as <code>2026-09-08T14:30:00Z</code>. Slash dates like <code>08/09/2026</code> are refused on purpose: they are read as September in Europe and August in the United States, and this actor will not guess which you meant.

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

Stop after this many listings. Free-plan runs are capped at 5 items. The form starts at 25 for a cheap first run - that is the form's prefill, not a cap on your plan; clear it to use the default of 1000.

## `proxyConfiguration` (type: `object`):

Proxy settings. Keep Apify proxy enabled.

## `reportFailures` (type: `boolean`):

When a run fails, send the developer the actor name and build, an error category, the error message (truncated) and a one-way hash of your input - so a bug can be fixed without anyone asking you to reproduce it. <b>Your input itself, your results and your identity are never sent, and successful runs send nothing at all.</b> Switch this off and the actor behaves exactly the same.

## Actor input object example

```json
{
  "searchQuery": "rower górski",
  "listingIds": [],
  "sellerType": "any",
  "sortBy": "date",
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "reportFailures": true
}
```

# Actor output Schema

## `listings` (type: `string`):

Scraped OLX.pl listings, one JSON object per listing.

# 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 = {
    "searchQuery": "rower górski",
    "listingIds": [],
    "sortBy": "date",
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lowlanddata/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 = {
    "searchQuery": "rower górski",
    "listingIds": [],
    "sortBy": "date",
    "maxItems": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("lowlanddata/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 '{
  "searchQuery": "rower górski",
  "listingIds": [],
  "sortBy": "date",
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call lowlanddata/olx-pl-scraper --silent --output-dataset

```

## MCP server setup

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