OLX Scraper - Listings Across 9 Countries avatar

OLX Scraper - Listings Across 9 Countries

Pricing

from $1.00 / 1,000 results

Go to Apify Store
OLX Scraper - Listings Across 9 Countries

OLX Scraper - Listings Across 9 Countries

Fast OLX scraper across 9 countries, including Poland, Romania, Portugal, Ukraine, Bulgaria, Kazakhstan, Uzbekistan, India and Brazil. Search or paste OLX URLs to extract structured listing data with pagination and multi-market support.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

4

Bookmarked

94

Total users

13

Monthly active users

5 days ago

Last modified

Share

OLX Scraper: Classifieds Listings, Prices, Sellers & Photos

OLX Scraper turns OLX classifieds into structured data. It covers OLX country sites (Poland, Romania, Portugal, Ukraine, Bulgaria, Kazakhstan, Uzbekistan, plus India and Brazil, which are currently limited, see Plan Requirement), and extracts title, price, category, full location with coordinates, seller profile, contact options, images, attributes and posting dates for every listing. Search by keyword and filters, or paste OLX search-result links and let the actor auto-paginate them. Export to JSON, CSV or Excel, or pull results straight into your app through the API.

Why This Scraper?

  • Two ways to collect listings. Build a search from country, category, city, query and price filters, or paste OLX search-result URLs and the actor auto-paginates each one forward.
  • Many country sites from one actor. Poland, Romania, Portugal, Ukraine, Bulgaria, Kazakhstan and Uzbekistan each run on their local OLX domain with the same output shape.
  • 55+ named fields per listing. Price, category path, full location with latitude and longitude, seller profile, contact toggles, images, key attributes and posting dates, not just the search-result summary.
  • Optional detail enrichment. Turn on "Fetch full details per listing" to fill in the complete description, full attribute list and any fields the search results leave empty, with one extra request per listing.
  • Built for large catalogues. Resume a paused run without re-scraping listings you already have, or narrow with an advanced filter passthrough for site-specific query parameters.
  • Built for schedules. Incremental mode returns only new, updated and reappeared listings on recurring runs, so a daily monitor does not re-bill what has not changed.
  • Honest failures. If a site refuses every connection, the run fails with a message saying so instead of returning a silent empty dataset. Brazil (olx.com.br) is currently blocked by the site; see Plan Requirement.

Use Cases

  • Price and market monitoring: track asking prices for a model, category or city over time across one or more OLX countries.
  • Vehicle listings aggregation: pull car, motorcycle or parts listings by make, model and filters into your own marketplace or comparison site.
  • Real estate lead sourcing: collect apartment and rental listings by city and price range for agents or lead-generation tools.
  • Resale and dropshipping research: watch a category or search for newly posted items to act on quickly.
  • Business intelligence: compare seller types, tags and pricing across categories and countries for competitive analysis.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
listingId"789456123"
country"pl"
title"iPhone 13 Pro 128GB, jak nowy"
price / priceCurrency3200 / "PLN"
priceDisplay"3 200 zł do negocjacji"
priceNegotiabletrue
categoryName / categoryPath"Telefony i Akcesoria" / "Elektronika / Telefony i Akcesoria"
city / region"Warszawa" / "Mazowieckie"
fullLocation"Mokotów, Warszawa, Mazowieckie"
latitude / longitude52.1978 / 21.0224
sellerName / sellerType"Kamil" / "private"
sellerTag"Approved dealer" (when present)
businessFlagfalse
hasPhone / hasChat / hasCouriertrue / true / true
images / imageCountlist of photo URLs / 6
keyParams["Używany"]
status"active"
isPromotedtrue
createdAt / validToTimeposting date / expiry date, both ISO
urllink to the listing on its OLX country site
condition / previousPrice"used" / earlier price after a price drop (classic OLX sites)
isHighlighted / isUrgent / isTopAd / promotionOptionspaid-promotion flags and the options bought
sellerCompany / sellerAbout / sellerIsOnline / shopSubdomainbusiness seller profile details
phonesseller phone numbers, only with Fetch seller phone number (otherwise null)

Some fields are country-specific: score, kycVerified and sellerTag come from India, safedeal and delivery from countries that support those programs. With Incremental mode on, each row also gets changeType, changedFields, firstSeenAt and lastSeenAt.

How to Use

  1. Pick a mode: search (filters) or url (paste OLX search-result links).
  2. For search mode, pick a country and fill in the filters you need; for URL mode, paste one or more links. Fields that belong to the other mode are ignored.
  3. Set Maximum listings and, optionally, Maximum pages to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search by keyword and price in Poland:

{
"mode": "search",
"country": "pl",
"query": "iPhone 13",
"priceMax": 2500,
"maxListings": 50
}

Search a vehicle category in Romania with advanced filters:

{
"mode": "search",
"country": "ro",
"categoryId": 9,
"extraFilters": { "filter_enum_make": ["bmw"], "filter_float_year:from": 2018 },
"sortBy": "price_asc",
"maxListings": 100
}

Paste search-result URLs and auto-paginate:

{
"mode": "url",
"urls": ["https://www.olx.pl/motoryzacja/samochody/bmw/"],
"fetchDetails": true,
"maxListings": 200
}

Paste any of these and the actor resolves what the page shows (category, city, search, filters, sort order) through the site itself, rather than guessing from the link text:

ShapeExample
Category / subcategoryhttps://www.olx.pl/motoryzacja/samochody/bmw/
Top-level listinghttps://www.olx.pl/motoryzacja/samochody/
Category + cityhttps://www.olx.pl/nieruchomosci/mieszkania/warszawa/
Free-text searchhttps://www.olx.pl/oferty/q-iphone/
Paginated (starts on that page)https://www.olx.pl/motoryzacja/samochody/bmw/?page=2
Filtered and sortedhttps://www.olx.pl/motoryzacja/samochody/bmw/?search%5Bfilter_float_price%3Afrom%5D=10000&search%5Border%5D=filter_float_price%3Aasc
Single listinghttps://www.olx.pl/d/oferta/ksiazka-encyklopedia-popularna-olesiejuk-CID751-IDRFFqw.html
Seller pagehttps://www.olx.pl/oferty/uzytkownik/1VRzN/
Mobile hosthttps://m.olx.pl/motoryzacja/samochody/bmw/
Romania, Portugal, Ukraine (/uk/), Kazakhstan, Bulgariahttps://www.olx.ro/auto-masini-moto-ambarcatiuni/autoturisme/

olx.uz category links also work. olx.in links are attempted but the site was not reachable on our last check, and olx.com.br links are blocked by the site. A link the actor cannot resolve (a page that does not exist, or one that is not a listing page) is skipped with a warning naming the link, never silently.

Behaviour change: URL mode with the urls field left untouched now scrapes one example of each shape above instead of failing with "no URLs". Also, category, listing, filtered and seller links used to be turned into a free-text keyword search (for example /bmw/ became the keyword "bmw"); they now return the real category, search or seller listings, so output for saved URL-mode tasks can differ. Resolving a link reads the page once before paging through its results.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/olx-scraper").call(run_input={"mode": "search", "country": "pl", "query": "iPhone 13"})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
print(listing["title"], listing["price"], listing["priceCurrency"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/olx-scraper').call({ mode: 'search', country: 'pl', query: 'iPhone 13' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Resume and recurring updates

  • Resume from a previous run (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and already-saved listings are skipped, so you do not pay to re-scrape them.
  • Incremental mode (incrementalMode) is for repeating the same search on a schedule. Each listing is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED, or EXPIRED (only after a run that scanned the whole search, and only with emitExpired on). stateKey names or shares the tracked state; leave it empty and the actor derives one from the search itself. Change detection ignores volatile fields (scrapedAt, displayDate, score, searchUrl, isPromoted, isHighlighted, isUrgent, isTopAd, promotionOptions, pushupTime, sellerIsOnline, sellerLastLogin, vasTags, images), which stay in the output but never cause UPDATED; add more with ignoreFieldsForChanges (plain name such as sellerName, or a dotted path to a nested value such as params.value). A pasted URL starting at ?page=N with N above 1 is a partial scan and never produces EXPIRED rows. Only URL mode looks at pasted URLs for this; Search mode is never blocked by the example URL list. Category and brand URLs are now read as that category (not a text search across all categories), so the first Incremental run after this change on a state saved by an older version skips EXPIRED detection once, drops listings the new reading no longer returns from tracking without an EXPIRED row (nothing billed for them), and resumes normal EXPIRED tracking from the next run.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (filters) or url (paste links). Only fields belonging to the chosen mode are used.
urlsarrayone example of each supported shape (14 links)OLX links to scrape (URL mode). Country is auto-detected per URL; each URL auto-paginates and a ?page=N link starts on that page. Ignored in search mode. See "URL mode: supported link shapes" below.
conditionstringanynew, used or damaged (all countries except India and Brazil).
sellerFilterstringanyprivate or business sellers only (all countries except India and Brazil).
fetchPhonebooleanfalseAlso read the phone number the seller shows publicly on the listing. 1 extra request per listing; not for India and Brazil; hidden numbers stay empty. Billing is unchanged: one result per listing.
countrystringplCountry to search: pl, ro, pt, ua, bg, kz, uz, in or br. Search mode only.
querystring(none)Free-text search keyword. Combined with category and city filters when present.
categoryIdinteger(none)OLX numeric category ID. Find it by browsing OLX and reading the category page's URL or metadata. Not used for Brazil searches.
categoryNamestring(none)Plain category name or path (for example Samochody osobowe or motoryzacja/samochody), looked up in the site's own category list. The run stops with a clear error if nothing matches. Ignored when categoryId is set. Not available for India and Brazil.
cityIdinteger(none)Numeric city ID for classic countries (PL, RO, PT, UA, BG, KZ, UZ).
cityNamestring(none)Plain city name (for example Kraków), looked up on the site's own city pages. The run stops with a clear error if the city is not found. Ignored when cityId is set. Not available for India and Brazil.
locationIdinteger(none)Numeric location ID for India (state/city). Ignored for non-India searches.
priceMininteger(none)Lower bound for price, in the country's local currency.
priceMaxinteger(none)Upper bound for price, in the country's local currency.
sortBystringdefaultResult order: default (relevance), created_desc, created_asc, price_asc or price_desc.
extraFiltersobject(none)Escape hatch for site-specific filters not exposed above. Keys are passed verbatim into the request URL; not validated.
fetchDetailsbooleanfalseFetch each listing's detail endpoint to fill in the complete description, full attribute list and any fields the search results leave empty. One extra request per listing.
maxListingsinteger20Stop after this many listings across the whole run. 0 means unlimited, capped only by maxPages.
maxPagesinteger(none, unlimited)Per-search page cap. Leave empty to walk every result page until end of results or the site's own last-page signal.
resumeFromRunIdstring(none)Continue one interrupted run without re-scraping listings already saved there.
incrementalModebooleanfalseTurn on for recurring monitoring of the same search: later runs return only new, updated and reappeared listings.
stateKeystring(none)Names or shares an incremental-mode state. Left empty, the actor derives one from the search itself.
emitUnchangedbooleanfalseAlso return (and bill) listings that have not changed since the last run, marked UNCHANGED.
emitExpiredbooleanfalseAlso return (and bill) listings no longer found after a complete scan, marked EXPIRED.
ignoreFieldsForChangesstring[][]Extra fields (name or dotted path) that never make a listing UPDATED.
proxyConfigurationobjectApify ProxyConnection settings. Apify Proxy is the default; if it is refused the actor escalates through backup connections (see Plan Requirement).
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"listingId": "789456123",
"country": "pl",
"url": "https://www.olx.pl/d/oferta/iphone-13-pro-128gb-jak-nowy-CID123.html",
"title": "iPhone 13 Pro 128GB, jak nowy",
"description": "Sprzedam iPhone 13 Pro 128GB w kolorze grafitowym. Stan idealny, komplet akcesoriów w oryginalnym pudełku.",
"createdAt": "2026-09-20T08:15:00+02:00",
"lastRefreshTime": "2026-09-25T10:00:00+02:00",
"validToTime": "2026-10-25T08:15:00+02:00",
"price": 3200,
"priceCurrency": "PLN",
"priceDisplay": "3 200 zł do negocjacji",
"priceNegotiable": true,
"offerType": "offer",
"categoryId": "1518",
"categoryName": "Telefony i Akcesoria",
"categoryPath": "Elektronika / Telefony i Akcesoria",
"city": "Warszawa",
"region": "Mazowieckie",
"district": "Mokotów",
"fullLocation": "Mokotów, Warszawa, Mazowieckie",
"latitude": 52.1978,
"longitude": 21.0224,
"sellerId": "44556677",
"sellerName": "Kamil",
"sellerType": "private",
"businessFlag": false,
"hasPhone": true,
"hasChat": true,
"hasNegotiation": true,
"hasCourier": true,
"images": ["https://ireland.apollo.olxcdn.com/v1/files/sample/image;s=1000x700"],
"imageCount": 6,
"params": [{ "key": "state", "name": "Stan", "value": "Używany", "type": "select" }],
"keyParams": ["Używany"],
"status": "active",
"isPromoted": true,
"searchUrl": "https://www.olx.pl/api/v1/offers/?category_id=1518&offset=0&limit=40",
"scrapedAt": "2026-09-27T20:00:00.000Z"
}

Output views

The dataset has five views: Overview (price, title, location), Seller info, Media (images), Changes (incremental) (changeType, changedFields, first and last seen) and Listing detail (description and full attributes).

Plan Requirement

The default Apify Proxy setting is what the actor starts on. Poland (olx.pl) accepts it only intermittently: some connections get a bare 403 refusal and the next one is served, so the actor retries on a fresh connection. Romania (olx.ro) was served on it in our checks, and the other classic countries are read the same way.

Brazil (olx.com.br) is currently blocked by the site on every connection type we tested, including residential with country BR. A Brazil run therefore fails with: "No results: olx.com.br refused every connection tried this run, including residential, so no Brazilian listings could be read. This is a block by the site, not an empty search. Other OLX countries are unaffected; try again later or use a different country." India (olx.in) was not reachable on our last check.

If the default connection is refused, the actor escalates through backup connections before giving up, and the run log says so when it happens, so a successful run never silently hides which connection carried it. On a free Apify plan (no residential access) the log warns: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." If a free-plan run then loads nothing, it fails with: "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested OLX pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."

If your plan has no proxy access at all and every connection is refused, the run stops with: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid." Any other run where no results page loads fails with: "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."

FAQ

How much does it cost?

You pay per listing returned: $0.002 per listing on the Free plan, falling to $0.001 per listing on Gold and above, plus a $0.08 actor start fee on the Free plan. Detail enrichment, phone numbers and connector exports do not add to the price. The Pricing tab always shows the current rates. Use Maximum listings and Maximum pages to cap the cost of any run.

This actor collects only publicly available classifieds data. You are responsible for how you use it: follow OLX's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Do not use scraped contact details to spam sellers.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Later runs then return only new, updated and reappeared listings by default, and unchanged ones are not billed unless you opt in.

Why are some of my filter fields being ignored?

Search fields (country, query, category, city, price, sort, extra filters) only apply in search mode, and the URLs field only applies in URL mode. Filling in fields from the other mode has no effect; check Mode first if a run isn't behaving as expected.

Why did my run fail instead of returning an empty dataset?

The actor fails when scraping cannot start or nothing could be read: your custom proxy URLs could not be set up, URL mode was chosen with no URLs, an unsupported country was set, the resumeFromRunId you pasted could not be loaded, Incremental mode was combined with resumeFromRunId on a search that already has saved state, or not a single results page could be read (a connection problem, which the message says is not an empty search). If a results page loads and simply has no listings, that is a genuine "nothing matched" and the run succeeds with an empty dataset. If some pages load and a later one keeps failing after retries, the run keeps what it collected and warns that the results may be incomplete.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more classifieds data?

Pair this actor with these related scrapers from the same team:

🏷️ Marktplaats.nl Scraper
From $1/1K. Scrape Marktplaats.nl listings by keyword or URL. Extract title, price...
🏷️ 2dehands & 2ememain
Scrape classifieds from 2dehands.be and 2ememain.be by keyword, filters, or URLs. Returns...
🏷️ Avito.ru Scraper
From $1/1K. Scrape structured listings from Avito.ru by region, category, filters, or...
🏷️ Gumtree AU Scraper
Scrape gumtree.com.au classifieds across every vertical: for-sale goods, motors, real...
🏷️ FINN.no Jobs Scraper
Scrape active FINN.no job listings by search filters or URL. Extract 30+ fields including...
🏷️ Kleinanzeigen.de Scraper
From $1/1K. Scrape Kleinanzeigen.de ads by keyword, category, location, price, seller...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.