OLX.pl Scraper - Polish Classified Listings
Pricing
from $1.50 / 1,000 listings
OLX.pl Scraper - Polish Classified Listings
Collect verified OLX.pl listings from every category with search, price, location and category filters.
Pricing
from $1.50 / 1,000 listings
Rating
0.0
(0)
Developer
Amadeusz
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
OLX.pl Scraper
Collect listings from 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 · Input schema · 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:
locationtakes a city or voivodeship (Kraków,Mazowieckie),categorytakes a category name or path (Elektronika,motoryzacja/samochody). No numeric IDs to look up. - Filters you can discover: a free run with
listFilterslists 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
- Type a Search phrase, or choose a Category and a Location.
- Add a price range, seller type or category filters if you need them.
- Set Max items (the limit of listings returned and charged).
- Click Start. The default input (
query: rower,maxItems: 100) is a working example. - 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
{"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
{"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:
{"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):
{"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
{"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
{"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
{"query": "iphone 13","countOnly": true}
Returns one estimate record with estimatedTotal. It is free.
7. New listings since the last run (schedule it)
{"category": "elektronika","mode": "monitor","seenStoreName": "my-olx-monitor","maxItems": 500}
Save this input as an Actor Task and attach an Apify Schedule. Details are in the monitoring section below.
8. Call the synchronous API
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, 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. 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.
{"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 ofcountOnly:estimatedTotal,sources,note.filter: result oflistFilters: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
stopMonitorOnAllSeenPagesconsecutive 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_INVALIDinstead 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
createdAtwithscrapedAtto 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
seenIdsKeyplus_VIEWS(up to 200000 newest offers). A corrupted record ends the run withSEEN_STATE_INVALID. maxItemslimits 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(viewsFailedinOUTPUT) and the counters stay as they were.OUTPUTalso hasviewsTrackedandviewChanges. - 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
maxItemsabove 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, andcoverage(records against OLX's own count) can exceed 1.truncatedPartitionsabove 0 means more than 1000 listings with the same price that cannot be separated. priceis the amount OLX stores andpriceLabelis how OLX shows it.price: 0with the labelZa darmomeans free, withZamienięa swap. Jobs have noprice; the pay is insalary. Sorting by price puts symbolic prices (1 zł) first, so setpriceFromto 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
countOnlybefore 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. UseincludePromoted: falsefor a strictly sorted stream.newestis based on the refresh time, so a few older listings pushed up by their sellers can appear slightly out oflastRefreshedAtorder. locationresolves a city or voivodeship name through OLX (KrakówandKraków, Małopolskieboth work). The run stops withINVALID_INPUTwhen 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, andjobs[].criteriainOUTPUThas them too. UsestartUrlsorcityIdwhen you need an exact place.- The category list is a snapshot of the OLX category tree;
categoryIdalways 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 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.