# Kmart Australia Scraper – Products, Prices & Reviews (`abotapi/kmart-au-scraper`) Actor

Scrape products and customer reviews from Kmart.com.au. Search by keyword or use product/category URLs with sorting and filters. Returns name, brand, price, promo price, ratings, review text and stats, colours, sizes, images, seller, category, stock, and variations.

- **URL**: https://apify.com/abotapi/kmart-au-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Kmart Australia Scraper

Collect product listings and customer reviews from kmart.com.au. Search by keyword, browse a specials collection, or paste links, then get a clean, flat record per product: name, canonical title, brand, current price with the was/original price and discount (amount and percent), star rating, full per-review text with stats, colours, sizes, images, seller, category, stock flags, and every colour/size variation. Reviews and review statistics attach to each product automatically.

### Why this scraper

- Specials and discounts: browse Kmart's Clearance, Catalogue, and Online Exclusives collections, and capture the was/original price, saving amount and percent, and on-special flag on every product that is genuinely reduced.
- Products and reviews together: each product carries its rating summary plus individual review text, author, date, helpful votes, and sub-ratings (Value, Quality).
- Rich, flat records: 30+ fields per product, including canonical title, was/now pricing, variations, images, and category.
- Two ways to start: search by keyword (with an optional specials collection), sorting and filters, or paste product, category, specials, and search URLs.
- Filters that narrow results: brand, colour, category, and a price range. Third-party marketplace sellers are excluded by default (`includeMarketplace` opts in; marketplace records carry `isMarketplace: true`).
- **Resume & recurring updates** — turn on Incremental mode to get only NEW, UPDATED, and REAPPEARED products on every scheduled run, or resume one specific interrupted crawl with `resumeFromRunId`. See "Resume & recurring updates" below.
- Optional export: pipe results straight into Notion, Linear, Airtable, or Apify via MCP connectors.

### Data you get

> Sample shape, values are illustrative placeholders, not from a live listing.

| Field | Example |
|---|---|
| id | `00000001` |
| name | `Sample Bath Towel` |
| title | `Sample Brand Sample Bath Towel` |
| brand | `Sample Brand` |
| price | `8.0` |
| wasPrice | `12.0` |
| savingsAmount | `4.0` |
| savingsPercent | `33` |
| isOnSpecial | `true` |
| promoLabel | `Clearance` |
| listPrice | `8.0` |
| promoPrice | `12.0` |
| currency | `AUD` |
| onSale | `false` |
| clearance | `true` |
| averageRating | `4.6` |
| reviewCount | `316` |
| colour | `Blue` |
| size | `One Size` |
| seller | `kmart` |
| isMarketplace | `false` |
| merchDepartment | `Home` |
| primaryCategoryId | `00000` |
| inStockNationally | `true` |
| url | `https://www.kmart.com.au/product/sample-bath-towel-00000001/` |
| image | `https://assets.kmart.com.au/transform/00000000-0000-0000-0000-000000000000/00000001-1` |
| images | `["https://assets.kmart.com.au/transform/.../00000001-1", "..."]` |
| variations | `[{ "colour": "Blue", "size": "One Size", "price": 12.0, "apn": "0000000000000" }]` |
| reviewStats | `{ "totalReviews": 316, "averageScore": 4.58, "starDistribution": { "5": 222, "4": 64 } }` |
| reviews | `[{ "rating": 5, "title": "Sample title", "content": "Sample review text.", "author": "Sample R.", "createdAt": "2026-01-01T00:00:00.000Z", "verifiedBuyer": true }]` |

### How to use

Search for a keyword:

```json
{
  "mode": "search",
  "searchTerms": ["towel"],
  "maxItems": 20
}
```

Search with sorting and filters:

```json
{
  "mode": "search",
  "searchTerms": ["towel"],
  "sortBy": "price-asc",
  "brand": "Anko",
  "minPrice": 5,
  "maxPrice": 30,
  "maxItems": 25
}
```

Browse a specials collection (Clearance, Catalogue, or Online Exclusives):

```json
{
  "mode": "search",
  "specialsCategory": "clearance",
  "maxItems": 50
}
```

Discounted products carry `wasPrice`, `savingsAmount`, `savingsPercent` and `isOnSpecial`. Kmart runs an everyday-low-price model, so a was/original price is shown only when an item is genuinely reduced; otherwise those fields are `null` and `isOnSpecial` reflects clearance status. You can also reach a collection in URL mode by pasting its page URL, e.g. `https://www.kmart.com.au/category/online-exclusives/`.

Search multiple keywords with reviews:

```json
{
  "mode": "search",
  "searchTerms": ["air fryer", "mug"],
  "fetchReviews": true,
  "maxReviews": 20,
  "maxItems": 40
}
```

Paste URLs:

```json
{
  "mode": "url",
  "urls": [
    "https://www.kmart.com.au/search/?searchTerm=towel",
    "https://www.kmart.com.au/product/sample-bath-towel-00000001/"
  ],
  "maxItems": 30
}
```

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| mode | string | `search` | `search` for keywords, `url` for pasted links. |
| searchTerms | array | `["towel"]` | Keywords to search (search mode). |
| specialsCategory | string | | Optional specials collection: `clearance`, `catalogue`, or `online-exclusives`. |
| sortBy | string | `relevance` | relevance, popular, newest, price-asc, price-desc. |
| brand | string | | Keep only this brand (exact facet value). |
| colour | string | | Keep only this colour (exact facet value). |
| category | string | | Keep only this category (exact facet value). |
| includeMarketplace | boolean | `false` | Also keep third-party marketplace sellers' products (thousands of extra items). By default only the Kmart, Target and Officeworks ranges are returned. |
| minPrice | integer | | Keep products at or above this price. |
| maxPrice | integer | | Keep products at or below this price. |
| urls | array | | Product, category, or search URLs (url mode). |
| fetchReviews | boolean | `true` | Attach reviews and review stats to each product. |
| maxReviews | integer | `20` | Cap on reviews per product. `0` disables reviews. |
| maxItems | integer | `20` | Total products to return. `0` = unlimited. |
| maxPages | integer | `100` | Safety cap on pages walked per search. |
| resumeFromRunId | string | | Continue one specific interrupted previous run/dataset: products already collected there are skipped. For recurring daily monitoring of the same search, use Incremental mode instead — see "Resume & recurring updates" below. |
| incrementalMode | boolean | `false` | Daily/recurring monitoring of this same search, specials collection, or URL set. First run returns everything as `NEW`; later runs return only `NEW`/`UPDATED`/`REAPPEARED` by default. See "Resume & recurring updates" below. |
| stateKey | string | | Optional name for a monitoring campaign, so its incremental state stays stable or is deliberately shared. Auto-derived from your search/filter settings when left empty. |
| emitUnchanged | boolean | `false` | Incremental mode only. Also return products unchanged since the last run, marked `UNCHANGED`. Adds and bills extra rows you already have. |
| emitExpired | boolean | `false` | Incremental mode only. Also return products from a previous run no longer found, marked `EXPIRED`, once a run has fully scanned the search/URLs (not capped, not a resume). Adds and bills extra synthetic rows. |
| proxy | object | Apify Proxy | Connection configuration. |
| mcpConnectors | array | | Optional MCP connectors to export results into. |
| notionParentPageUrl | string | | Notion parent page for the Notion connector. |
| maxNotifyListings | integer | `50` | Cap on items exported per connector. |

### Send results into your apps (MCP connectors)

Optionally forward results into the apps you already use. Authorize a connector under Apify then Settings then Integrations, select it in the `mcpConnectors` input, and set `notionParentPageUrl` for Notion. Each item is written as a condensed, human-readable summary (a title plus key fields), not the full JSON; nested objects collapse to their main value and arrays trim to a few names. The complete record always stays in the Apify dataset.

### Output example

> Sample shape, values are illustrative placeholders, not from a live listing.

```json
{
  "kind": "product",
  "id": "00000001",
  "name": "Sample Bath Towel",
  "title": "Sample Brand Sample Bath Towel",
  "url": "https://www.kmart.com.au/product/sample-bath-towel-00000001/",
  "brand": "Sample Brand",
  "apn": "0000000000000",
  "price": 8.0,
  "listPrice": 8.0,
  "promoPrice": 12.0,
  "wasPrice": 12.0,
  "savingsAmount": 4.0,
  "savingsPercent": 33,
  "isOnSpecial": true,
  "promoLabel": "Clearance",
  "variantBadges": ["Clearance"],
  "currency": "AUD",
  "onSale": false,
  "clearance": true,
  "freeShipping": false,
  "averageRating": 4.6,
  "reviewCount": 316,
  "colour": "Blue",
  "size": "One Size",
  "seller": "kmart",
  "merchDepartment": "Home",
  "inStockNationally": true,
  "images": ["https://assets.kmart.com.au/transform/00000000-0000-0000-0000-000000000000/00000001-1"],
  "variations": [
    { "colour": "Blue", "size": "One Size", "price": 12.0, "apn": "0000000000000" }
  ],
  "reviewStats": {
    "totalReviews": 316,
    "averageScore": 4.58,
    "starDistribution": { "5": 222, "4": 64, "3": 24, "2": 4, "1": 2 },
    "subRatings": { "Value": 5.0, "Quality": 4.0 }
  },
  "reviews": [
    {
      "rating": 5,
      "title": "Sample title",
      "content": "Sample review text.",
      "author": "Sample R.",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "verifiedBuyer": true,
      "votesUp": 6,
      "votesDown": 0,
      "subRatings": { "Value": 5, "Quality": 5 }
    }
  ]
}
```

**Incremental mode only.** When `incrementalMode` is on, every returned record also carries:

| Field | Description |
|---|---|
| `changeType` | `NEW` | `UPDATED` | `UNCHANGED` | `REAPPEARED` | `EXPIRED` |
| `changedFields` | Top-level fields that changed since last seen; non-empty only for `UPDATED` |
| `firstSeenAt` | When this product was first observed by this monitoring campaign |
| `lastSeenAt` | When this product was last observed |

Change detection is based on the product itself — price, was/now pricing and specials, stock, brand, colour, size, seller, images, badges, and so on. `reviews`, `reviewStats`, `averageRating`, and `reviewCount` are deliberately excluded from that comparison: they come from a separate review widget (foreign to the product) and normally shift between two runs of the same product (a new review, or just a fresh vote count) with nothing about the product having changed, so including them would mark almost every product `UPDATED` on every run.

### Resume & recurring updates

There are two different things here — pick the one that matches what you're doing:

| Need | Use |
| --- | --- |
| A crawl stopped and should continue | `resumeFromRunId` / automatic checkpoint recovery |
| Run the same search/specials/URLs every day and receive only changes | `incrementalMode` |
| Keep separate daily campaigns for similar searches | distinct `stateKey` values |
| Run a normal full snapshot | leave both off |

**Resume** (`resumeFromRunId`) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips products already collected there, returning only the remaining new products. An automatic same-run checkpoint also protects against platform migrations/Resurrects without any input needed.

**Incremental mode** (`incrementalMode`) is for a schedule (for example, daily): the actor remembers the previous run of the *same* search/specials/URL/filter setup by itself, so you never paste a run ID. The first run returns everything as `NEW`. Later runs return only `NEW`, `UPDATED`, and `REAPPEARED` products by default — duplicates and unchanged products are suppressed (and not charged). Turn on `emitUnchanged` or `emitExpired` only when you also want those rows returned (and billed for). State is isolated per search/specials/URL/filter setup automatically; set `stateKey` to name or deliberately share a monitoring campaign.

Scheduled-run example — same search, run daily:

Day 1 (first run ever for this search):

```json
{ "mode": "search", "searchTerms": ["towel"], "incrementalMode": true }
```

→ every product comes back with `"changeType": "NEW"`.

Day 2 (the schedule fires again, identical input):

```json
{ "mode": "search", "searchTerms": ["towel"], "incrementalMode": true }
```

→ products whose price/specials/stock/etc. changed come back as `"changeType": "UPDATED"` with `changedFields` listing what changed, brand-new products come back as `"changeType": "NEW"`, products that vanished and came back come back as `"changeType": "REAPPEARED"` — and products that are still there, unchanged, are **not** returned at all (suppressed, not charged) unless `emitUnchanged` is on.

Reviews are still fetched for every scanned product (needed to classify it), but the `review-enrichment` surcharge is only charged for products that actually reach the dataset — a product suppressed as `UNCHANGED` is never charged for its reviews.

### Plan requirement

Apify Proxy is used by default and works on every plan. Leave proxy enabled for the most reliable results.

# Actor input Schema

## `mode` (type: `string`):

search = provide search terms and filters. url = paste product, category, or search URLs and walk them.

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

One or more keywords to search, e.g. towel, air fryer, kids toys.

## `specialsCategory` (type: `string`):

Optionally scrape one of Kmart's promotional collections instead of (or alongside) your search terms: Clearance, the current Catalogue, or Online Exclusives. Leave as None to search normally. Was/original price and discount fields are captured on every product when the item is genuinely reduced.

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

Order of results within each search or specials collection.

## `brand` (type: `string`):

Filter to one brand (exact facet value, e.g. Anko).

## `colour` (type: `string`):

Filter to one colour (exact facet value, e.g. Blue).

## `category` (type: `string`):

Filter to one category (exact facet value, e.g. Bath Towel).

## `includeMarketplace` (type: `boolean`):

Also keep products sold by third-party marketplace sellers. Listings carry thousands of these extra items, so they are excluded by default — only products from the Kmart, Target and Officeworks ranges are returned. Tick to include marketplace sellers too.

## `minPrice` (type: `integer`):

Only keep products at or above this price.

## `maxPrice` (type: `integer`):

Only keep products at or below this price.

## `urls` (type: `array`):

Paste product, category, or search URLs from kmart.com.au. Multi-URL supported. Filter fields still apply.

## `fetchReviews` (type: `boolean`):

Attach product reviews and review stats to each product.

## `maxReviews` (type: `integer`):

Cap on reviews captured per product. 0 disables reviews.

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

Total products to return across all searches or URLs. 0 = unlimited.

## `maxPages` (type: `integer`):

Safety cap on pages walked per search term. 0 = walk every page (the run still stops naturally once the storefront's own result total is reached or a page repeats).

## `resumeFromRunId` (type: `string`):

Optional. ID of a previous run of this actor (or a dataset ID). Products already in that dataset are skipped, so this run returns only NEW products (a delta). Combine both runs' datasets for the full set. Max products then counts only the new products. For recurring daily monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching products as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED products. Turn on "Emit unchanged" or "Emit expired" only when you also want those products returned (and billed). State is kept separately for each search/URL/filter setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and filter settings — different setups then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED. This returns — and bills — extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return products that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search/URLs — not when Max products or Max pages capped it, or when Resume was used. This returns — and bills — extra synthetic rows, so leave it off unless you need expiry tracking.

## `proxy` (type: `object`):

Apify Proxy is used by default and works on every plan. Leave it enabled for reliable results.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify then Settings then API & Integrations, then select it here. Notion gets a page-per-item export; other connectors get a best-effort write. Leave empty to skip. Supported: Notion, Linear, Airtable, Apify.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required only for the Notion export.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerms": [
    "towel"
  ],
  "specialsCategory": "",
  "sortBy": "relevance",
  "includeMarketplace": false,
  "urls": [
    "https://www.kmart.com.au/search/?searchTerm=towel"
  ],
  "fetchReviews": true,
  "maxReviews": 20,
  "maxItems": 20,
  "maxPages": 0,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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 = {
    "mode": "search",
    "searchTerms": [
        "towel"
    ],
    "urls": [
        "https://www.kmart.com.au/search/?searchTerm=towel"
    ],
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/kmart-au-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 = {
    "mode": "search",
    "searchTerms": ["towel"],
    "urls": ["https://www.kmart.com.au/search/?searchTerm=towel"],
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/kmart-au-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "searchTerms": [
    "towel"
  ],
  "urls": [
    "https://www.kmart.com.au/search/?searchTerm=towel"
  ],
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/kmart-au-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=abotapi/kmart-au-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/gR5qGX597MJSBhNpY/builds/ilkdo7lHUsgUWgZuF/openapi.json
