# Makro SA Scraper: Prices, Specials, Deals & Sellers (`zaiq/makro-sa-scraper`) Actor

Scrape Makro South Africa (makro.co.za) products by search term, category or URL: prices, specials, was-prices, discounts, More4Less deals, ratings and stock; optionally sellers, delivery estimates, category paths and specifications. Groceries, liquor, appliances and more.

- **URL**: https://apify.com/zaiq/makro-sa-scraper.md
- **Developed by:** [Zaiq](https://apify.com/zaiq) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.20 / 1,000 products

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

## Makro SA Scraper: Prices, Specials, Deals & Sellers

Get products from Makro South Africa (makro.co.za) as structured data: prices, was-prices, discounts, More4Less
(Buy More, Save More) deals, ratings and stock, and on request the seller, delivery estimate, category path and
specifications. Groceries, liquor, household, appliances, electronics and more, including marketplace sellers. Search
by keyword, open any category or filtered listing, or give product links. Requests go through South African home
internet connections.

### What it does

- Searches like the site's search box, reads any category or filtered listing link (filters and sort in the link are
  kept) and single products.
- Returns, for every product: price, was-price and saving, More4Less flag, star rating and rating count, stock status,
  brand, pack size, unit price per kg, litre or item for groceries and household products, category, key
  specifications, image and link.
- Read each product's page (optional): adds the seller (Makro or the marketplace seller), the delivery estimate, the
  full category path, all specifications and the full deal text with its end date ("Buy any 2 at R 358.00, ends 26th
  October 2026"), at the same price per product.
- Specials only: returns just the discounted products.
- Out-of-stock products can be included (Makro hides them by default).

### Who uses it

- **Retailers, wholesalers and spaza or tuck-shop suppliers** comparing Makro's bulk and promotional prices.
- **Marketplace sellers** watching competitors' prices, discounts and ratings on makro.co.za.
- **Price comparison and deal sites** in South Africa.
- **Brands** checking how their products are priced and promoted, and which sellers carry them.

### Example

The search "kettle" and one product link, with product pages read, on 4 October 2026 (7 products in 13 seconds):

| Product | Price | Was | Seller | Delivery | Deal |
|---|---|---|---|---|---|
| Jacobs Kronung Instant Coffee 200 g | R198.95 | | Makro | by 06 Oct | Buy any 2 at R 358.00 (R179 each), ends 26 Oct 2026 |
| DEFY WK5100JS Electric Kettle | R299 | R399 | DefyAppliancesPTYLTD | by 06 Oct | |
| Russell Hobbs Illumina Glass Beverage Maker | R599 | R699 | NicheLiving | by 06 Oct | |
| Black & Decker MBF90-B5 Electric Kettle | R999 | R1,399 | DVM International SA | by 06 Oct | |
| Condere 48L Urn Beverage Maker | R990 | R1,499 | One collections | by 10 Oct | |

All six kettles in the search were sold by marketplace sellers rather than by Makro itself.

Other test runs the same day:

- 20 everyday search terms, up to 60 products each, listings only: 1,127 products in 38 seconds, no failed or blocked
  requests.
- 350 products of one search ("coffee", 7,467 on the site) in 25 seconds.
- Specials only for coffee and chocolate: 61 products; out-of-stock products included for "coffee": 8 of 200 marked
  not deliverable.

### Input

```json
{
  "searchTerms": ["coffee", "kettle"],
  "startUrls": [{ "url": "https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui" }],
  "maxItemsPerSource": 100,
  "includeDetails": false,
  "specialsOnly": false,
  "includeOutOfStock": false
}
```

| Field | What it does |
|---|---|
| `searchTerms` | Words to search for. |
| `startUrls` | Search (`/search?q=coffee`), category or filtered listing (`/food-products/coffee-powder/pr?sid=eat,dui`) or product (any `.../p/itm...?pid=...` link), or a bare product id (`COFHFSYFAYQUHSGX`). |
| `maxItemsPerSource` | Products per search term or URL (default 100). A product link gives one. |
| `maxItems` | Products in total for the run; 0 means no total limit. |
| `includeDetails` | Also read each product's page (seller, delivery estimate, category path, specifications, full deal). |
| `specialsOnly` | Only discounted products. |
| `includeOutOfStock` | Also list products Makro shows as out of stock or not deliverable. |
| `sort` | `relevance` (default), `popularity`, `price_low` or `price_high`. |
| `proxyConfiguration`, `maxConcurrency` | Advanced: South African residential connections by default; requests at once (default 5). |

### Output

One row per product. This row is from the example above (product page read, specifications shortened):

```json
{
  "retailer": "Makro",
  "productId": "COFHFSYFAYQUHSGX",
  "sku": "ITMB371E9FA288F5",
  "barcode": null,
  "name": "Jacobs Kronung Instant Coffee",
  "brand": "Jacobs",
  "size": "200 g",
  "sizeValue": 200.0,
  "sizeUnit": "g",
  "packCount": 1,
  "soldByWeight": null,
  "price": 198.95,
  "currency": "ZAR",
  "wasPrice": null,
  "promoPrice": null,
  "onSpecial": true,
  "savings": null,
  "unitPrice": 994.75,
  "unitPriceUnit": "kg",
  "loyaltyPrice": null,
  "loyaltyProgram": null,
  "loyaltyValidFrom": null,
  "loyaltyValidUntil": null,
  "promotions": [
    {
      "text": "Buy any 2 at R 358.00",
      "type": "Buy More, Save More",
      "memberOnly": false,
      "promoUnitPrice": 179.0,
      "minQuantity": 2,
      "description": "JACOBS 200G (All Variants) Excl Decaf",
      "endsOn": "26th October 2026",
      "promotionId": "nb:mp:06dbb1d125"
    }
  ],
  "inStock": true,
  "stockStatus": "In stock",
  "stockQuantity": null,
  "category": "Food Products > Coffee Powder > Jacobs Coffee Powder",
  "categories": ["Food Products", "Coffee Powder", "Jacobs Coffee Powder"],
  "imageUrl": "https://www.makro.co.za/asset/rukmini/fccp/832/832/ng-fkpublic-ui-user-fbbe/coffee/c/c/x/-original-imah9zhxy7zptdru.jpeg?q=70",
  "url": "https://www.makro.co.za/jacobs-kronung-instant-coffee/p/itmb371e9fa288f5",
  "rating": 4.9,
  "reviewCount": 239,
  "seller": "Makro",
  "deliveryEstimate": "Delivery by 06 Oct",
  "store": null,
  "position": 1,
  "sourceType": "product",
  "sourceValue": "https://www.makro.co.za/jacobs-kronung-instant-coffee/p/itmb371e9fa288f5?pid=COFHFSYFAYQUHSGX&lid=LSTCOFHFSYFAYQUHSGXI96XNE",
  "scrapedAt": "2026-10-04T16:12:47Z",
  "listingId": "LSTCOFHFSYFAYQUHSGXI96XNE",
  "subtitle": "200 g",
  "sellerId": "155410923f68483e",
  "attributes": { "Brand": "Jacobs", "Quantity": "200 g", "Container Type": "Glass Bottle", "Shelf Life": "36 Month" },
  "detailsIncluded": true
}
```

- `wasPrice` is Makro's crossed-out price; `promotions` holds the More4Less (Buy More, Save More) deal with the price
  per item it works out to and its end date when product pages are read. In listings a More4Less product is flagged
  without the deal's text.
- `reviewCount` is the number of ratings.
- `seller`, `deliveryEstimate` (for Makro's default delivery area, Sandton 2157) and the full category path come from
  product pages.
- `unitPrice` is given for groceries, household and personal-care products; for appliances and other goods a size is
  a capacity, so no unit price is given.
- All prices are in rand, VAT included. (Makro's platform labels amounts INR internally; the site shows rand.)

### Use it from code, automations and AI agents

- **API**: run it and get the results in one call: `POST https://api.apify.com/v2/acts/zaiq~makro-sa-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN` with the input as JSON. The API tab on this page has ready-made Python, JavaScript and cURL examples.
- **Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("zaiq/makro-sa-scraper").call(run_input={'searchTerms': ['coffee', 'kettle'], 'startUrls': [{'url': 'https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui'}], 'maxItemsPerSource': 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

- **No code**: connect it to Google Sheets, Zapier, Make or n8n from the Integrations tab, schedule runs in Apify Console, and get a webhook when a run finishes.
- **AI agents (MCP)**: add it as a tool to Claude, Cursor or any MCP client through Apify's MCP server: `https://mcp.apify.com?tools=zaiq/makro-sa-scraper`.

### Pricing

$4.00 per 1,000 products ($0.004 per product row), with or without product pages. Apify's platform usage
is included.

Each product row is one charged event. Failed, blocked and empty pages, retries and duplicates are free. Your spending
limit is respected: the run stops cleanly before going over it.

### Limits

- Makro does not publish barcodes, so `barcode` is empty.
- Delivery estimates are for Makro's default delivery area; store-by-store stock is not shown online.
- Some searches are narrowed by Makro to one product type (for example "toilet paper" lists 26 products); a category
  link reaches the rest.
- No member (mRewards) prices appear in Makro's online product data, so `loyaltyPrice` is empty.
- Use the data in line with Makro's terms and South African law. This Actor is not affiliated with or endorsed by
  Makro or Massmart.

### FAQ

**Does it include marketplace sellers?** Yes. Listings include every seller's products; read product pages to get the
seller's name in `seller` (the listing gives only `sellerId`).

**Why is reading product pages optional?** It is one more, larger request per product, so runs take longer: 30
products took 26 seconds in testing against a few seconds for 30 listings. The price per product is the same.

**Can I keep the site's filters?** Yes. Filter and sort on makro.co.za, copy the link and put it in the URLs.

# Actor input Schema

## `searchTerms` (type: `array`):

Words to search for, as you would type them on the site (for example milk, coffee, nappies). A barcode (EAN-13) also works.

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

Makro pages: a search (https://www.makro.co.za/search?q=coffee), a category (https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui) or a product (any .../p/itm...?pid=... link). A bare product id (the pid, for example COFHFSYFAYQUHSGX) works too. Filters in the URL are kept.

## `maxItemsPerSource` (type: `integer`):

Stop each search term or category after this many products. A product URL always gives one.

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

Stop the whole run after this many products. 0 means no total limit (each search term or URL still stops at its own maximum, and your spending limit always applies).

## `specialsOnly` (type: `boolean`):

Return only products the site marks as on promotion (a lower price, a member price or a multi-buy deal).

## `sort` (type: `string`):

The order the site lists products in. With a product limit, this decides which products you get.

## `includeDetails` (type: `boolean`):

Adds the seller (Makro or a marketplace seller), delivery estimate, category path, specifications and the full More4Less deal with its end date. One extra request per product, so slower; the price per product is the same.

## `includeOutOfStock` (type: `boolean`):

Makro hides out-of-stock products by default; switch this on to list them too.

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

By default every request goes through South African home (residential) internet connections, as a shopper in South Africa would browse.

## `maxConcurrency` (type: `integer`):

How many requests run at the same time. Kept low to stay polite to the site.

## Actor input object example

```json
{
  "searchTerms": [
    "coffee",
    "kettle"
  ],
  "startUrls": [
    {
      "url": "https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui"
    }
  ],
  "maxItemsPerSource": 20,
  "maxItems": 0,
  "specialsOnly": false,
  "sort": "relevance",
  "includeDetails": false,
  "includeOutOfStock": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "ZA"
  },
  "maxConcurrency": 5
}
```

# Actor output Schema

## `products` (type: `string`):

Dataset with one row per product.

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

Products per search term or URL, results the site reported, errors, requests and approximate traffic.

# 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 = {
    "searchTerms": [
        "coffee",
        "kettle"
    ],
    "startUrls": [
        {
            "url": "https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui"
        }
    ],
    "maxItemsPerSource": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "ZA"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zaiq/makro-sa-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 = {
    "searchTerms": [
        "coffee",
        "kettle",
    ],
    "startUrls": [{ "url": "https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui" }],
    "maxItemsPerSource": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "ZA",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("zaiq/makro-sa-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 '{
  "searchTerms": [
    "coffee",
    "kettle"
  ],
  "startUrls": [
    {
      "url": "https://www.makro.co.za/food-products/coffee-powder/pr?sid=eat,dui"
    }
  ],
  "maxItemsPerSource": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "ZA"
  }
}' |
apify call zaiq/makro-sa-scraper --silent --output-dataset

```

## MCP server setup

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