# Takealot Price Drop Monitor & Scraper - South Africa (`neverempty/takealot-price-drop-monitor`) Actor

Schedule it hourly/daily and get only new products, price drops and price rises from Takealot, with the old price. Search by keyword, department or brand: price, list price, saving, rating, reviews and stock in ZAR. Export JSON, CSV or Excel.

- **URL**: https://apify.com/neverempty/takealot-price-drop-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** E-commerce, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.39 / 1,000 product returneds

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

## Takealot Price Drop Monitor & Scraper - South Africa

**Schedule it hourly/daily → get only new listings & price drops from Takealot.** For resellers, online shops, deal sites and bargain hunters in South Africa: type a product name (or paste a Takealot search, department or product URL) and every run returns each product's price, rating, reviews, stock and delivery estimate in ZAR, plus the list price and saving whenever Takealot shows them. Turn on watch mode and later runs return only what changed since the last run, with the previous price and the change in %.

- Search by keyword, department (home-kitchen, computers, cellphones, gaming, toys, beauty...) or brand
- Filter by in-stock only, featured deals only, minimum star rating and price range in rand
- Watch exact products by pasting their Takealot product URLs
- Price, list price and saving as shown on Takealot, plus the price range for products sold in several options
- Each product once per run, even when two searches overlap
- Export to JSON, CSV or Excel, or send rows to Google Sheets, Slack or a webhook with Apify integrations

### What you get

| Field | Example |
|---|---|
| `productId`, `url` | `98945485`, link to the Takealot product page |
| `title`, `subtitle`, `brand` | `Russell Hobbs Digital 9L Air Fryer - RHAF09S`, `Smart pause function`, `Russell Hobbs` |
| `price`, `listPrice`, `savingText` | `899`, `1499`, `40%` (price in rand; list price and saving when Takealot shows them) |
| `priceMax`, `hasOptions` | Highest price when the product comes in several options (colour, size...); `price` is then the cheapest option |
| `rating`, `reviewCount` | `4.8`, `2166` |
| `inStock`, `stockStatus`, `warehouses` | `true`, `In stock`, `["CPT", "DBN", "JHB"]` |
| `deliveryEstimate`, `isPreorder` | `Get it Tomorrow, 7am - 7pm`, `false` |
| `sku`, `tsin` | Takealot's own product numbers |
| `currency` | Always `ZAR` |
| `imageUrl` | Product image |
| `changeType`, `previousPrice`, `priceChange`, `priceChangePercent`, `comparedOn`, `previousInStock`, `previousSeenAt`, `removedReason` | Watch mode: what changed since the last run, and the price it is compared with |

### How to use it

1. Type one or more product names in **Products to search**, for example `air fryer`, `iphone 15` or `lego`. You can also paste the URL of a Takealot search or department page with your filters set, or the URL of a product page (`.../PLID...`).
2. If you like, pick a **Department**, **Brands**, **In stock only**, **Deals only**, a minimum rating or a price range.
3. Set **Max products per search** and run. Leave everything empty to run the example: 36 products for air fryer.

To keep track of prices, turn on **Watch mode** and add a schedule (hourly or daily). See [Monitoring on a schedule](#monitoring-on-a-schedule).

### Input

| Field | What it does |
|---|---|
| `searchQueries` | Product names, Takealot search or department URLs, or product URLs. Up to 50 searches and 1,000 product URLs per run. |
| `department` | Takealot department as in its URL, for example `home-kitchen`, `computers`, `gaming`. With no search words, the whole department is searched. |
| `brand` | Brands as shown on Takealot, for example `Russell Hobbs`, `Defy`, `Samsung`. |
| `inStockOnly`, `dealsOnly` | Only products in stock now, or only featured deals. |
| `minRating` | Only products rated at least this many stars. |
| `minPrice`, `maxPrice` | Price range in ZAR. |
| `sortBy` | Relevance, price low/high, top rated or newest. |
| `maxResultsPerSearch` | Products per search (default 100, at most 10,000). |
| `monitoringMode` | Watch mode for schedules. |
| `minChangePercent` | Report a price move only when it reaches this % (default 1). |
| `includeUnchanged` | Also return products that did not move. |
| `watchName`, `resetMonitoringState` | Keep separate memories for two watches of the same search, or start over. |

#### Example input

```json
{
    "searchQueries": ["air fryer"],
    "brand": ["Russell Hobbs", "Defy"],
    "inStockOnly": true,
    "maxResultsPerSearch": 200,
    "monitoringMode": true,
    "minChangePercent": 5
}
```

### Output

A real row from a run on 2026-10-28 (search `air fryer`):

```json
{
    "status": "ok",
    "productId": 98945485,
    "url": "https://www.takealot.com/russell-hobbs-digital-9l-air-fryer-rhaf09s/PLID98945485",
    "title": "Russell Hobbs Digital 9L Air Fryer - RHAF09S",
    "subtitle": "Smart pause function",
    "brand": "Russell Hobbs",
    "price": 899,
    "priceMax": null,
    "listPrice": 1499,
    "savingText": "40%",
    "hasOptions": false,
    "rating": 4.8,
    "reviewCount": 2166,
    "inStock": true,
    "stockStatus": "In stock",
    "warehouses": ["CPT", "DBN", "JHB"],
    "deliveryEstimate": "Get it Tomorrow, 7am - 7pm",
    "isPreorder": false,
    "sku": 224000182,
    "tsin": 100366962,
    "imageUrl": "https://media.takealot.com/covers_images/5c8058bc304740c2a9cb18919b56228a/s-zoom.file",
    "currency": "ZAR",
    "searchQuery": "air fryer",
    "scrapedAt": "2026-10-28T21:52:51.877Z"
}
```

Every row has a `status`. Product rows are `ok`. When a search finds nothing, a product is gone, or a search stops early, you get one free row that says so (`no-results`, `not-found`, `incomplete`, `blocked`, `unreadable`, `bad-input`), so you always know how the run went.

### Monitoring on a schedule

Turn on **Watch mode**, then click **Schedule** on the Actor page and pick hourly or daily.

- **First run:** returns the products it finds, each with `changeType: "new"`, and remembers their prices.
- **Every later run:** returns only
  - `new` - products that just appeared in your search, or came back after leaving it
  - `price_drop` - cheaper than last time, with `previousPrice`, `priceChange` and `priceChangePercent`
  - `price_up` - pricier than last time
  - `removed` - the product left your search for two runs in a row (`removedReason: "left-search"`). Reported for searches the run read in full (the search fits in Max products and has no price range).
- **Quiet run:** one free `no-change` row confirms the run worked.

Small moves add up: with `minChangePercent: 5`, a product that drops 2% a day is reported on the third day, compared with the price it was last reported at. Only a complete read can mark a product as removed.

In watch mode, a search sorted by relevance or top rated is read newest first, so every run compares the same products. To watch the cheapest or priciest products of a big search, sort by price.

Each search is tracked separately. To watch the same search twice with different settings, give each task its own `watchName`. To start over, run once with `resetMonitoringState`.

### Pricing

You pay per product row, plus a small start fee per run:

| Event | Price |
|---|---|
| Product row (`ok`) | $2.99 per 1,000 rows (less on higher Apify plans) |
| Run start | $0.003 |

Status rows (`no-change`, `no-results`, `not-found`, `incomplete` and the others) are free. In watch mode you pay only for the rows that changed, so a daily watch of 200 products where 10 moved costs about $0.03 per run. The first watch run returns every product as `new`, so it bills all of them (200 products = about $0.60 + $0.003).

### FAQ

**How do I get an alert when a product drops in price on Takealot?**
Turn on Watch mode, type the product name or paste its product URL, set `minChangePercent` (for example 5) and schedule the Actor daily. Each run returns only the products that got cheaper or pricier, with the old price. Connect the run to Slack, email or a webhook with Apify integrations to get the alert.

**Can I track a whole department or brand?**
Yes. Leave the search empty, set `department` (for example `home-kitchen`) and, if you like, `brand`. Set `maxResultsPerSearch` high enough to cover the products you want.

**Can I watch exact products?**
Yes. Paste the Takealot product URLs, one per line. Each run returns those exact products.

**Can I catch new products when Takealot lists them?**
Yes. On an hourly or daily schedule in watch mode, every product that appears in your search for the first time comes back with `changeType: "new"`. Sort by newest to watch the latest listings of a big search.

**What currency are the prices in?**
South African rand. Every row carries `currency: "ZAR"`.

**Can I export to Excel or Google Sheets?**
Yes. Download the dataset as CSV or Excel, or use the Google Sheets integration.

### Good to know

- Unofficial and not affiliated with Takealot.
- Takealot shows up to 10,000 products for one search here. For larger searches, split by department, brand or price range; the run adds an `incomplete` row when a search hits that limit.
- Prices are those shown on Takealot.com in ZAR at the time of the run. `listPrice` and `savingText` are `null` when Takealot shows no list price for the product.
- Watch mode compares the price. A change in stock alone is not reported, but every watch row carries `inStock` and `previousInStock`.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

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

One per line: a product name as you would type it on Takealot (air fryer, iphone 15, lego), the URL of a Takealot search or department page with your filters already set, or the URL of a product page (…/PLID…) to watch that exact product. Up to 50 searches and 1,000 product URLs per run. Leave it empty to run the example: 36 products for air fryer.

## `monitoringMode` (type: `boolean`):

Schedule it hourly/daily → get only new listings & price drops. The first run returns the current products marked new and remembers their prices. Each later run returns only products that are new to the search (changeType new), cheaper than last time (price_drop) or pricier (price_up) with the previous price and the change in %, or have left the search (removed). A run with no changes returns one free row that says so.

## `department` (type: `string`):

Only products from this Takealot department, as in the department page URL: home-kitchen, computers, cellphones, gaming, toys, beauty, baby-toddler, sport, tv-audio-video and so on. With no search words, the whole department is searched. Empty = all departments.

## `brand` (type: `array`):

Only products from these brands, as shown on Takealot, for example Russell Hobbs, Defy, Samsung. Empty = all brands.

## `inStockOnly` (type: `boolean`):

Only products Takealot has in stock now.

## `dealsOnly` (type: `boolean`):

Only products Takealot shows as a featured deal.

## `minRating` (type: `number`):

Only products rated at least this many stars, for example 4. Empty = any rating.

## `minPrice` (type: `number`):

Only products priced at least this much in rand. Empty = no minimum.

## `maxPrice` (type: `number`):

Only products priced at most this much in rand. Empty = no maximum. In watch mode, a product that moves out of the price range is not reported as removed.

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

The order Takealot lists the results in. With a maximum per search set, it decides which products you get and which ones a watch covers. When every product of a search is wanted, or in watch mode, relevance and top rated are read newest first, so none are skipped and every watch run covers the same products.

## `maxResultsPerSearch` (type: `integer`):

How many products to return for each search (in watch mode: how many products to watch). Empty = 100. At most 10,000 per search; split larger searches by department, brand or price range. Each product is returned once per run, even if two searches overlap.

## `minChangePercent` (type: `number`):

Report a price drop or rise only when the price moved at least this much since it was last reported, for example 5 for 5%. Small moves add up: a product that drops 1% a day is reported once the total reaches this.

## `includeUnchanged` (type: `boolean`):

Return every watched product on every run, with changeType unchanged for those that did not move. Off = only changes (cheaper runs).

## `watchName` (type: `string`):

Optional. Give each scheduled task its own name so two watches of the same search keep separate memories.

## `resetMonitoringState` (type: `boolean`):

Forget what this watch has already returned. The next run behaves like a first run.

## Actor input object example

```json
{
  "searchQueries": [
    "air fryer"
  ],
  "monitoringMode": false,
  "inStockOnly": false,
  "dealsOnly": false,
  "sortBy": "relevance",
  "maxResultsPerSearch": 36,
  "minChangePercent": 1,
  "includeUnchanged": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

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

One row per Takealot product: product ID, link, title, brand, price, list price and saving in ZAR, rating, review count, stock status, warehouses, delivery estimate and the image. Watch mode marks rows new, price_drop, price_up or removed with the previous price and the change in %. A search with no results, nothing changed, a refused request or a run that hit its maximum charge comes back as a free row that says why.

# 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 = {
    "searchQueries": [
        "air fryer"
    ],
    "maxResultsPerSearch": 36
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/takealot-price-drop-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 = {
    "searchQueries": ["air fryer"],
    "maxResultsPerSearch": 36,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/takealot-price-drop-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 '{
  "searchQueries": [
    "air fryer"
  ],
  "maxResultsPerSearch": 36
}' |
apify call neverempty/takealot-price-drop-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/takealot-price-drop-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/PpXt3dfLmVpmHjivk/builds/OdyeWcg0ch5fpAiAd/openapi.json
