# OLX Deal Monitor — New Listings & Below-Market Price Alerts (`kala4/olx-deal-monitor`) Actor

Monitor OLX searches in 7 countries. Get only new listings each run, see which ones are priced below market (median), and receive deal alerts in Telegram or via webhook. Fast, no login, no browser.

- **URL**: https://apify.com/kala4/olx-deal-monitor.md
- **Developed by:** [Vladyslav Pershko](https://apify.com/kala4) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

### What does OLX Deal Monitor do?

**OLX Deal Monitor** watches your OLX searches and tells you about **new listings** and **underpriced deals**, without checking the site every hour yourself.

- 🌍 Works on **OLX Poland, Ukraine, Romania, Portugal, Bulgaria, Kazakhstan and Uzbekistan** (olx.pl, olx.ua, olx.ro, olx.pt, olx.bg, olx.kz, olx.uz)
- 🆕 **Only new listings**: each run returns only what you haven't seen yet. Schedule it every 15–60 minutes for a live feed.
- 🔥 **Deal detection**: every listing is compared with the **median price** of similar listings in the same search. Anything X% cheaper is flagged as a deal.
- 🚩 **Suspicious price filter**: listings that are *too* cheap (accessories, placeholder prices, likely scams) are flagged separately and don't trigger deal alerts.
- 📲 **Instant alerts** to **Telegram** or any **webhook** (Make, Zapier, n8n, Discord, Slack)
- 🧹 Filters: price range, condition (new/used), private vs. business sellers, city/region, excluded keywords
- 🎯 **Exact model matching**: searching "iphone 13 pro" skips "13 Pro Max", "iPhone 14 Pro", cases and unrelated items, so the median is the price of *that* model (local spellings like "айфон 13 про" work too)
- 🧠 Smart cleanup: **accessories** ("Case for iPhone…") and **broken / for-parts** items are skipped automatically, and prices listed in **another currency** (e.g. USD on olx.ua) are converted before comparing
- ⚡ Fast and cheap: uses OLX's own JSON API, no browser, no login

### Who is it for?

- **Resellers and flippers** looking for underpriced phones, laptops, bikes, consoles, furniture, cars…
- **Buyers** waiting for a specific item at the right price
- **Market researchers** tracking prices and supply of a product across countries

### How to use it

1. Open OLX, search for what you want (e.g. "iphone 13 pro"), set a price range, and copy the URL. Or fill in **Searches (advanced)** with country + keyword + filters.
2. Paste it into **OLX search URLs**. Add as many searches as you like.
3. Optional: add your **Telegram bot token** and **chat ID** to get deal alerts on your phone.
4. Click **Start**, then **Schedule** the Actor (e.g. every 30 minutes). Each run returns only the new listings.

#### Getting Telegram alerts (2 minutes)

1. In Telegram, open **@BotFather**, send `/newbot`, and copy the **token**.
2. Send any message to your new bot.
3. Open `https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates` in a browser and copy `chat.id`.
4. Paste both into the input. Done.

### Input example

```json
{
    "searchUrls": ["https://www.olx.ua/uk/list/q-iphone-13-pro/?search%5Bfilter_float_price:to%5D=25000"],
    "searches": [
        {
            "country": "pl",
            "query": "rower gravel",
            "maxPrice": 3000,
            "condition": "used",
            "excludeKeywords": ["dziecięcy"],
            "label": "Gravel bikes PL"
        }
    ],
    "onlyNewSinceLastRun": true,
    "dealThresholdPercent": 30,
    "alertOn": "deals"
}
```

### Output example

```json
{
    "searchLabel": "UA: iphone 13 pro [–25000]",
    "country": "ua",
    "id": "876543210",
    "url": "https://www.olx.ua/d/uk/obyavlenie/iphone-13-pro-256gb-IDabc.html",
    "title": "iPhone 13 Pro 256GB, ідеальний стан",
    "price": 16500,
    "currency": "UAH",
    "negotiable": true,
    "condition": "used",
    "sellerType": "private",
    "city": "Київ",
    "region": "Київська область",
    "photoUrl": "https://ireland.apollo.olxcdn.com/v1/files/…;s=800x600",
    "createdAt": "2026-10-14T09:12:00+03:00",
    "medianPrice": 22500,
    "discountVsMedianPercent": 26.7,
    "isDeal": true,
    "suspiciousPrice": false,
    "isNew": true
}
```

The **SUMMARY** record shows, for each search, how many listings were found, how many are new, how many are deals, and the median price.

### How much does it cost?

You pay **per listing returned**. See the **Pricing** tab. With **Only new listings** on, a scheduled monitor only pays for listings you haven't seen, so a quiet search costs almost nothing.

### FAQ

**Why compare private and shop listings separately?**
Shops add a warranty premium and often post the same item several times. Private listings are compared with the median of private listings and shop listings with shops (when there are at least 8 of each). Identical repeated listings count once.

**How is the "median price" calculated?**
From the listings of the same search in the current run plus up to 300 prices remembered from earlier runs. Deals need at least 8 priced listings for a reliable median. Make your search specific (e.g. "iphone 13 pro 256", not "iphone") for the best deal detection.

**Why are some listings skipped as "not the exact model"?**
With **Exact model only** on, a listing must contain every word of your keyword and no other variant (Pro/Max/Plus/Mini/Ultra/Lite/FE). That keeps deal detection honest: a "13 Pro Max" isn't compared with "13 Pro" prices. Turn it off for broad searches like "gravel bike".

**What about prices in dollars or euros?**
OLX converts them to the site's main currency (e.g. UAH on olx.ua), and that converted price is used for price filters and deal detection. The original price and currency are kept in the output too.

**Why was a listing skipped as an accessory?**
Titles that start with an accessory word ("Чохол для…", "Etui do…", "Husa pentru…", "Capa para…", "Case for…") are treated as accessories. Bundles like "iPhone 13 Pro + case" are kept. Turn off **Exclude accessories** if you want everything.

**Can I use category filters from the OLX URL?**
The keyword and price range are taken from the URL. Use **excludeKeywords**, **condition**, **sellerType** and **locationContains** for more precise results.

**How many listings can a search return?**
OLX returns up to 1,000 listings per keyword. For monitoring that's plenty, because new listings are returned first.

**Do you collect seller data?**
No. Seller names, phone numbers, profile IDs and exact map coordinates are never stored. You get only the listing and its city/region.

**Responsible use**
Use reasonable schedules (every 15 minutes or slower) and don't use the data for spam or to contact sellers in bulk. Respect OLX's terms of service.

### Support

Need another OLX country, a different alert format, or price-drop tracking? Open an issue in the **Issues** tab.

# Actor input Schema

## `searchUrls` (type: `array`):

Paste OLX search URLs that contain a keyword (…/q-your-keyword/). Supported: olx.pl, olx.ua, olx.ro, olx.pt, olx.bg, olx.kz, olx.uz. The keyword and price range from the URL are used; category filters are not.

## `searches` (type: `array`):

Optional, instead of or in addition to URLs. Each search: {"country": "pl|ua|ro|pt|bg|kz|uz", "query": "...", "minPrice": 0, "maxPrice": 0, "condition": "any|new|used", "sellerType": "any|private|business", "locationContains": "city or region", "excludeKeywords": \["…"], "label": "name in alerts"}.

## `maxListingsPerSearch` (type: `integer`):

Maximum number of listings returned per search per run (newest first). You pay per listing returned.

## `onlyNewSinceLastRun` (type: `boolean`):

Return only listings that weren't returned before for this monitor. Turn on and schedule the Actor (e.g. every hour) to get a stream of new listings without duplicates.

## `excludeAccessories` (type: `boolean`):

Skip cases, screen protectors, chargers, cables, holders etc. (e.g. "Чохол для iPhone", "Etui do iPhone"). Bundles like "iPhone + case" are kept.

## `excludeBrokenOrParts` (type: `boolean`):

Skip listings like "на запчастини", "uszkodzony", "pentru piese", "for parts", "icloud locked".

## `strictModelMatch` (type: `boolean`):

Keep only listings whose title contains every keyword and no other model variant. Searching "iphone 13 pro" skips "13 Pro Max", "iPhone 14 Pro" and unrelated items. Local spellings like "айфон 13 про" are understood. Turn off for broad searches (e.g. "bike").

## `monitorName` (type: `string`):

Separate name for remembering seen listings. Use different names for independent monitors with the same searches.

## `dealThresholdPercent` (type: `integer`):

A listing is a deal when its price is at least this many percent below the median price of comparable listings for the same search.

## `maxDealDiscountPercent` (type: `integer`):

Listings cheaper than this are flagged as suspicious (accessories, placeholder prices, scams) instead of deals.

## `alertOn` (type: `string`):

Which listings to send to Telegram / webhook.

## `telegramBotToken` (type: `string`):

Optional. Create a bot with @BotFather and paste its token. Stored encrypted.

## `telegramChatId` (type: `string`):

Optional. Your chat ID (send a message to your bot, then open https://api.telegram.org/bot<token>/getUpdates to see it) or a channel like @mychannel.

## `webhookUrl` (type: `string`):

Optional. We POST a JSON payload with the alert listings (works with Make, Zapier, n8n, Slack workflows, Discord bridges).

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

Usually not needed. Enable Apify Proxy only if OLX starts blocking requests.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.olx.ua/uk/list/q-iphone-13-pro/?search%5Bfilter_float_price:to%5D=25000"
  ],
  "searches": [
    {
      "country": "pl",
      "query": "rower gravel",
      "maxPrice": 3000,
      "condition": "used",
      "excludeKeywords": [
        "dziecięcy"
      ],
      "label": "Gravel bikes PL"
    }
  ],
  "maxListingsPerSearch": 100,
  "onlyNewSinceLastRun": true,
  "excludeAccessories": true,
  "excludeBrokenOrParts": true,
  "strictModelMatch": true,
  "monitorName": "default",
  "dealThresholdPercent": 30,
  "maxDealDiscountPercent": 70,
  "alertOn": "deals",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `deals` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "searchUrls": [
        "https://www.olx.ua/uk/list/q-iphone-13-pro/?search%5Bfilter_float_price:to%5D=25000"
    ],
    "searches": [
        {
            "country": "pl",
            "query": "rower gravel",
            "maxPrice": 3000,
            "condition": "used",
            "excludeKeywords": [
                "dziecięcy"
            ],
            "label": "Gravel bikes PL"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kala4/olx-deal-monitor").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 = {
    "searchUrls": ["https://www.olx.ua/uk/list/q-iphone-13-pro/?search%5Bfilter_float_price:to%5D=25000"],
    "searches": [{
            "country": "pl",
            "query": "rower gravel",
            "maxPrice": 3000,
            "condition": "used",
            "excludeKeywords": ["dziecięcy"],
            "label": "Gravel bikes PL",
        }],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("kala4/olx-deal-monitor").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 '{
  "searchUrls": [
    "https://www.olx.ua/uk/list/q-iphone-13-pro/?search%5Bfilter_float_price:to%5D=25000"
  ],
  "searches": [
    {
      "country": "pl",
      "query": "rower gravel",
      "maxPrice": 3000,
      "condition": "used",
      "excludeKeywords": [
        "dziecięcy"
      ],
      "label": "Gravel bikes PL"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call kala4/olx-deal-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kala4/olx-deal-monitor"
        }
    }
}
```

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/VvrQFM3YsulHKnu1M/builds/WuICM0YLvNRTexWoc/openapi.json
