# Myer Scraper: Products, Prices, Variants & Reviews (`abotapi/myer-au-scraper`) Actor

Scrape Myer (myer.com.au) department-store products: name, brand, price, was-price, saving, availability, category, images, attributes, colour & size variants, plus ratings and customer reviews. Search by keyword with brand, price and rating filters, or paste product, search or category URLs.

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

## Pricing

from $1.00 / 1,000 product results

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

## Myer Australia Scraper - Products & Reviews

Scrape **Myer** department-store products from
[myer.com.au](https://www.myer.com.au) into a clean, structured dataset. Search
by keyword with brand, price and rating filters, or paste product, search and
category URLs directly. Optionally collect the full product detail plus customer
ratings and reviews with an aggregate rating summary for every product.

Myer is Australia's largest department store, spanning beauty, fashion, home,
electrical, toys and more. This actor turns any Myer search, category or product
page into structured rows you can analyse, monitor or feed into your own tools.

### What you get

One flat record per product, including:

- **Identity** - `name`, `title`, `brand`, `id`, `internalId`, `seoToken`,
  `mfPartNumber`
- **Price & discount** - `price`, `priceTo`, `listPrice`, `wasPrice` (original
  strike-through price), `savedAmount`, `savingsPercent`, `promoLabel` /
  `promoLabels` (the site's own sale badges, e.g. "Reduced to clear"),
  `isOnSale`, `isClearance`, `currency`, `afterPayEligible`, `hummEligible`
- **Availability** - `isAvailable`, `isBuyable`
- **Category** - `category`, `categories`, `merchCategory`, `categoryUri`
- **Descriptions** - `shortDescription`, `longDescription`, `metaDescription`
- **Attributes** - `specifications` (name/value pairs)
- **Variants** - `colourVariants`, `variants` (size / colour with identifiers
  and per-variant price, `wasPrice`, `savedAmount`, `savingsPercent`),
  `supplierColour`, `hasMoreColours`
- **Media** - `imageUrl`, `images` (full gallery)
- **Ratings & reviews** (with detail enrichment) - `rating`, `reviewCount`,
  `ratingDistribution`, `recommendedCount`, and `reviews[]` with per-review
  rating, title, body, author, ISO-8601 date, verified-purchase flag, helpful
  count and pros/cons, plus `reviewsCollected`
- **Resume & recurring updates** (optional) - turn on Incremental mode to get
  only NEW, UPDATED, and REAPPEARED products on every scheduled run, or resume
  one specific interrupted crawl with `resumeFromRunId`

### Modes

#### Search by keyword + filters

Set **Mode = search** and add one or more **Search keywords**. Each keyword is
searched separately. Refine with:

- **Specials / sale category** - browse one of Myer's promotional views instead
  of (or alongside) a keyword search: All sale, Clearance, or a department sale
  (Women's, Men's, Beauty, Home, Kids & baby, Toys, Travel & tech). Every
  product returned carries its `wasPrice`, `savedAmount` and `savingsPercent`,
  and clearance items include the site's own `promoLabel`. Combine with the
  **Brand** field to filter a sale to one brand.
- **Brand** - keep only a given brand
- **Minimum / maximum price** (AUD)
- **Minimum rating** (1-5) - requires detail enrichment
- **Include unavailable products** - on by default
- **Sort by** - relevance, price low-to-high, price high-to-low, highest rated,
  or name A-Z

#### Scrape pasted URLs

Set **Mode = url** and paste **Myer URLs**:

- A **product URL** (`/p/<slug>`, e.g.
  `https://www.myer.com.au/p/some-product`) returns that single product.
- A **search URL** (e.g. `https://www.myer.com.au/search?query=perfume`) or a
  **category URL** (e.g. `https://www.myer.com.au/c/beauty/skincare`) returns
  multiple pages of results, continuing forward from the page in the URL.
- A **sale / clearance URL** (e.g. `https://www.myer.com.au/c/sale-all` or
  `https://www.myer.com.au/c/clearance-offers`) is just a category URL - it
  returns the sale products with their was-price and saving fields.

### Ratings & reviews

Keep **Fetch full product detail + reviews** on (the default) to attach each
product's full detail, an aggregate rating summary and its customer reviews. Use
**Max reviews per product** to cap how many are collected per product (0 = all
available).

Reviews are common on Myer beauty, fashion and home products - for example, a
popular skincare product might carry `reviewCount: 1811` with a `rating` of 4.7
and a `ratingDistribution` of `{ "5": 1511, "4": 193, "3": 49, "2": 15, "1": 43 }`,
each review including rating, title, body, author, date and a verified-purchase
flag. Products with **no reviews** simply leave `rating`, `reviewCount`,
`ratingDistribution` and `reviews` absent (these fields are never faked);
`reviewsCollected` reads `0`.

Turn detail enrichment **off** for a faster, lower-cost run that returns the
listing card fields only (name, brand, price, images, category) with no reviews.

Note on ordering: Myer serves results in relevance order. Price, name and rating
ordering is applied to the set of products the run collects.

**Incremental mode note:** `rating`, `reviewCount`, `ratingDistribution`,
`recommendedCount`, `reviews` and `reviewsCollected` are always returned, but
they do **not** drive `changeType`. Other shoppers post reviews independently
of and far more often than a product's own price/stock/specials change, so
counting them would mark almost every product `UPDATED` on every scheduled run
and defeat suppression. A genuine price, was-price, saving, stock, or specials
change still triggers `UPDATED` as usual.

### Output limits

- **Max products** - overall cap across the run (0 = unlimited)
- **Max pages per search** - `0 = walk the whole catalogue` (the run still stops at the storefront's own result total or a page repeat — no artificial page cap)
- **Resume from run ID** - prior run ID (or dataset ID) to resume from — seeds the de-dup set so a re-run only appends new items

### 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 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 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 mode/search/URL/specials/brand/sort/price/rating/stock/detail setup automatically; set `stateKey` to name or deliberately share a monitoring campaign. `EXPIRED` is only synthesized once a run fully scans every keyword/URL/specials target (not capped by Max products/Max pages, not a Resume run).

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 |

Scheduled-run example - same search, run daily:

Day 1 (first run ever for this search):

```json
{ "mode": "search", "queries": ["moisturiser"], "incrementalMode": true }
```

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

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

```json
{ "mode": "search", "queries": ["moisturiser"], "incrementalMode": true }
```

→ products whose price/was-price/stock/specials/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.

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

Optionally pipe results into the apps you already use via Model Context Protocol
(MCP) connectors - Notion, Linear, Airtable or Apify. Authorize a connector under
**Apify → Settings → API & Integrations**, then select it in the input. Notion
gets a rich page-per-item export; other connectors get a best-effort write or
digest. This never changes the dataset output.

### Plan Requirement

Runs on any Apify plan. Using Apify Proxy is recommended for reliable results; on
the free plan, coverage may be limited and some runs may return fewer results.

### Example input

```json
{
  "mode": "search",
  "queries": ["moisturiser"],
  "brand": "Chanel",
  "minRating": 4,
  "sortBy": "priceAsc",
  "detailEnrichment": true,
  "maxReviewsPerProduct": 10,
  "maxItems": 50,
  "proxy": { "useApifyProxy": true }
}
```

Browse the Clearance sale with full detail and reviews:

```json
{
  "mode": "search",
  "specialsCategory": "clearance",
  "detailEnrichment": true,
  "maxItems": 50,
  "proxy": { "useApifyProxy": true }
}
```

### Example output

```json
{
  "id": "978052330",
  "internalId": "9770942",
  "name": "Sample Rejuvenating Face Cream 50ml",
  "brand": "Example Brand",
  "url": "https://www.myer.com.au/p/sample-face-cream-978052330",
  "price": 129.0,
  "listPrice": 149.0,
  "wasPrice": 149.0,
  "savedAmount": 20.0,
  "savingsPercent": 13,
  "promoLabel": "Reduced to clear",
  "promoLabels": ["Reduced to clear"],
  "isOnSale": true,
  "isClearance": false,
  "currency": "AUD",
  "isAvailable": true,
  "category": "skincare-Moisturiser",
  "categories": ["beauty", "skincare", "skincare-Moisturiser"],
  "shortDescription": "A lightweight daily moisturiser.",
  "specifications": { "Formulation": "Cream", "Skin Type": "All" },
  "imageUrl": "https://myer-media.com.au/wcsstore/MyerCatalogAssetStore/images/.../978052330_1_1_720x928.jpg",
  "rating": 4.7,
  "reviewCount": 1811,
  "ratingDistribution": { "5": 1511, "4": 193, "3": 49, "2": 15, "1": 43 },
  "reviews": [
    {
      "reviewId": "396991890",
      "rating": 5,
      "title": "Best cream I have tried",
      "body": "Leaves my skin soft and hydrated.",
      "author": "SampleReviewer",
      "date": "2026-06-01T10:00:00.000+00:00",
      "verifiedPurchase": true,
      "helpfulCount": 3
    }
  ],
  "reviewsCollected": 1
}
```

# Actor input Schema

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

Choose 'search' to use keywords and filters, or 'url' to scrape specific product, search or category URLs you paste below.

## `queries` (type: `array`):

One or more keywords to search, for example 'perfume' or 'coffee machine'. Each keyword is searched separately.

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

Optional. Scrape one of Myer's promotional views (Sale, Clearance or a department sale) instead of, or alongside, a keyword search. Every product returned carries its was-price, saving amount and saving percentage. Leave as 'None' for a normal keyword search. You can also reach these views in URL mode by pasting the sale / clearance category URL.

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

Optional. Keep only products whose brand matches this value, for example 'Chanel' or 'Nespresso'. Combine with a specials category to filter that sale to one brand.

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

Ordering applied to the collected results. Myer serves relevance order; price / name / rating ordering is applied to the collected set.

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

Optional. Only keep products priced at or above this amount (AUD).

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

Optional. Only keep products priced at or below this amount (AUD).

## `minRating` (type: `integer`):

Optional. Only keep products with an average customer rating at or above this value (1 to 5). Requires detail enrichment (the rating is read during enrichment).

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

Include products that are currently unavailable. On by default; turn off to keep only available products.

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

Product, search or category URLs to scrape, for example https://www.myer.com.au/p/some-product, https://www.myer.com.au/search?query=perfume or https://www.myer.com.au/c/beauty/skincare. Multiple URLs supported.

## `detailEnrichment` (type: `boolean`):

For each product, also fetch the product page for the full description, attributes, size/colour variants and identifiers, plus ratings and customer reviews. Adds one request per product. Turn off for a faster, lower-cost run that returns the listing card fields only (no reviews).

## `maxReviewsPerProduct` (type: `integer`):

Cap on reviews collected per product when detail enrichment is on. Use 0 for all available reviews. Products with no reviews leave the rating fields absent.

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

Maximum number of products to return across the whole run. Use 0 for unlimited.

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

Optional safety cap on result pages walked per keyword / URL. Use 0 to walk every page (the run still stops automatically once Max products is reached, or once a page repeats or the store's own result total is reached).

## `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 distinct search/filter setup (or by State key below).

## `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 your search/filter/detail settings — different searches 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 — not when Max products or Max pages capped it, or when Resume was used. This returns — and bills — extra synthetic rows.

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

Apify Proxy is recommended for reliable results. On the free plan, coverage may be limited and some runs may return no results.

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

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

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

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

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

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

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "perfume"
  ],
  "specialsCategory": "",
  "sortBy": "relevance",
  "includeOutOfStock": true,
  "urls": [
    "https://www.myer.com.au/c/beauty/skincare"
  ],
  "detailEnrichment": true,
  "maxReviewsPerProduct": 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",
    "queries": [
        "perfume"
    ],
    "urls": [
        "https://www.myer.com.au/c/beauty/skincare"
    ],
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/myer-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",
    "queries": ["perfume"],
    "urls": ["https://www.myer.com.au/c/beauty/skincare"],
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/myer-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",
  "queries": [
    "perfume"
  ],
  "urls": [
    "https://www.myer.com.au/c/beauty/skincare"
  ],
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/myer-au-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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