# Myer Product & Sale Price Scraper (Australia) (`superslowsloth/myer-products`) Actor

Myer scraper: search terms or category pages to one row per product with AUD price and price range, price before reduction, discount percent, MYER one member price, promo labels, brand, colour, barcode, stock and image. For department-store markdown watching.

- **URL**: https://apify.com/superslowsloth/myer-products.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (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 $0.49 / 1,000 product scrapeds

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

## Myer Product & Sale Price Scraper (Australia)

Search [Myer](https://www.myer.com.au) (the Australian department store) by
keyword, or read a category page, and get one flat row per product: the current
price and its range in **AUD**, the price before Myer's reduction, the discount
in dollars and percent, the **MYER one member price**, the promotion labels,
brand, colour, barcode, whether it can be bought, the product link and the
photo. Run it on a schedule and diff the dataset to get a **department-store
markdown watch**: which dresses, perfumes or sheet sets were reduced since last
week, and by how much.

No account, no API key, no login, no browser. One request returns 48 products.

### Input

| Field | Notes |
|---|---|
| `searchTerms` | One or more search terms, one per line (`dress`, `perfume`, `sheet set`). A term Myer recognises is sent to its category page, and that whole list is read; any other term is read as search results. A product found by two terms is returned once, under the first. |
| `startUrls` | Myer pages to read in full: a category (`https://www.myer.com.au/c/women/clothing/dresses`) or a search URL (`/search?query=...`, read as that search term). A filter copied from the site (`?facets=...`) is kept. A top-level category such as `/c/women` shows only 16 products, cannot be paged and is refused; use a sub-category (`/c/women/clothing`). Product pages are not accepted. Give terms, URLs or both. |
| `maxItems` | Products to read per term or page (default 100, up to 10,000). 48 per page. |
| `onlyOnSale` | Return only products that are reduced (`on_sale`). Products that are not reduced are read, not returned and not charged, and do not count toward `maxItems`. |
| `sort` | `relevance` (default), `price-asc`, `price-desc`, `brand-asc`, `brand-desc`: the choices of the site's own sort menu. |
| `proxyConfiguration` | Apify datacenter proxy by default. |

Example input:

```json
{
  "searchTerms": ["dress", "perfume"],
  "maxItems": 200,
  "onlyOnSale": true,
  "sort": "price-asc"
}
```

### Output

Prices are numbers in Australian dollars; `currency` is `AUD` (every page
measured).

| Field | Notes |
|---|---|
| `query`, `position` | The search term or page URL that first found the product, and its place in Myer's list for that source and sort (1 is first). |
| `product_id`, `url` | Myer's product id (`373990960`; a few carry two joined by an underscore) and the product link. A product is one colour of a style: other colours are separate products (`has_more_colours`). |
| `name`, `brand` | As the page shows them. `brand` is null if the page sends none. |
| `price`, `price_max` | The lowest and highest current price across the product's sizes or variants. Equal for the many products with one price. |
| `original_price`, `original_price_max` | The lowest and highest price **before** Myer's reduction. Equal to the current price when nothing is reduced. |
| `on_sale` | True when the current price is below the price before reduction at either end of the range. |
| `discount_amount`, `discount_amount_max` | Dollars off at the low and the high end of the range, as the page sends them. **Null when the product is not on sale**, never 0. |
| `discount_percent` | `(1 - price / original_price) * 100`, one decimal place, from the low ends of the two ranges. Worked out from the prices, not sent. Null when the low end is not reduced. |
| `member_price`, `member_price_max` | The **MYER one member price** (low and high end) where Myer shows one, mostly on beauty and fragrance. Null on everything else. It is not part of `price` and not a reduction: `on_sale` ignores it. |
| `labels` | The promo labels on the card (`MYER one double points`, `Bonus gift`, `Spend & save`). Empty list when there are none. |
| `trade_label` | `New` and similar tags. `exclusive`: `online_only` on marketplace lines. Null when the page sends none. |
| `ean`, `part_number` | The barcode and the supplier's part number as the page lists them. |
| `colour`, `has_more_colours`, `variant_count` | The supplier colour name (null for most homewares and beauty), whether the style has other colours, and how many variants the page lists for the product (sizes). |
| `merch_category` | Myer's internal merchandising path (`WW Womenswear/...`). Not the shop menu. |
| `in_stock` | True when the page marks the product available and buyable. |
| `image_url` | The first photo, 720x928 JPEG on `myer-media.com.au`. |

Example row (real values, 2026-10-16):

```json
{
  "query": "dress",
  "position": 1,
  "product_id": "373990960",
  "name": "Sheer Blossom Trapeze Gathered Neck Dress",
  "brand": "Veronika Maine",
  "url": "https://www.myer.com.au/p/veronika-maine-sheer-blossom-trapeze-gathered-neck-dress",
  "image_url": "https://myer-media.com.au/wcsstore/MyerCatalogAssetStore/images/70/742/2534/100/1/373990960/373990960_1_720x928.jpg",
  "currency": "AUD",
  "price": 239.2,
  "price_max": 239.2,
  "original_price": 299.0,
  "original_price_max": 299.0,
  "on_sale": true,
  "discount_amount": 59.8,
  "discount_amount_max": 59.8,
  "discount_percent": 20.0,
  "member_price": null,
  "member_price_max": null,
  "labels": ["MYER one double points"],
  "trade_label": "New",
  "exclusive": null,
  "ean": "9362481028531",
  "colour": "Multi",
  "has_more_colours": false,
  "variant_count": 7,
  "part_number": "M93118S26",
  "merch_category": "CO Concessions/WW 44-59 Cnc/VERONIKA MAINE CNC/VERONIKA MAINE CNC/VERONIKA MAINE CNC",
  "in_stock": true
}
```

#### Price ranges

One Myer product can hold several sizes at different prices, so every price
comes as a low and a high end. The two ranges are independent: a sheet set can be
69.95 to 239.00 now against 69.95 to 459.95 before, reduced only at the top end.
Such a row has `on_sale` true and a `discount_amount` and `discount_amount_max`
from the page, but `discount_percent` null, because the cheapest size is not
reduced. The page's dollar figures on a range product are its own and need not
equal `original_price - price`.

#### Honest nulls

A field the page did not send is `null`, never `0` or `""`. `labels` is an empty
list when there are none.

- **No rating or review count.** Myer's list carries neither, so the rows do not.
- **No stock levels.** `in_stock` says the product can be bought, nothing more.
- **`colour` is the supplier's name** and is null where the supplier gave none.

### Pricing

Pay per event:

- **$0.002** per run (`actor-start`), charged only after your input is
  validated, so a run that fails on bad input costs nothing.
- **$0.00049** per product row written (`product-scraped`), i.e. $0.49 per
  1,000 products. A row that is not written is not charged: rows filtered by
  `onlyOnSale`, and repeats of a product another term already returned, are free.

### How it fetches

It reads the product list that myer.com.au's own search and category pages embed
in their page data. Measured 2026-10-16: HTTP 200 HTML (about 1.2 MB a page) from
a plain home connection and, for a search page, from an Apify datacenter
address, no key or cookie needed. A refusal (403, 429, 5xx), a 200 that is not a
Myer page or whose list did not load, or a dropped connection is treated as the
address being blocked, and the actor rotates to a fresh one and retries.

Things worth knowing, all measured:

- **A search does not always return search results.** `perfume` is redirected to
  `/c/beauty/all-fragrance` (2,412 products), `lego` to `/c/all-toys/brand-lego`,
  `sheet set` to `/c/home/bedding/sheets`. A term Myer does not redirect is
  answered in place (`dress`: 5,849 products), and one it cannot match gets no
  results (not an error; it is logged). The actor reads whatever list Myer lands
  on, all its pages. `query` stays the term you typed. A broad term can therefore
  return a whole category; `maxItems` bounds it. A term sent to a page with no
  product list (`gift card` goes to a content page) fails at no charge.
- **The redirect drops `sort`.** The actor reads the first page again from the
  category when you asked for a sort, so the order you chose is the order you get.
- **The sort is checked, not trusted.** Myer ignores a sort name it does not know
  and answers in relevance order. The page says which sort it applied, and a run
  that did not get the sort it asked for fails that source rather than return the
  wrong order. The price sorts followed the lowest price strictly: 384 products
  over 8 pages of `dress` had no pair out of order in either direction.
- **Depth.** Myer lists 48 products per page and has no page-size setting. The
  deepest list measured has 470 pages; page 300 answered in full. A page past the
  last is an empty list and the actor stops there; the last page is also
  recognised from the list's total. At most 10,000 products per term or page.
- **Totals drift by one.** The same category reported 22,553 and then 22,552
  products on two requests, which is why an empty page ends a walk as well.
- **Top-level categories are not lists.** `/c/women` shows 16 products and
  ignores paging and sorting; it is refused with a message. Use a sub-category.
- **Photos.** The page names photos with a size placeholder. 720x928 and 540x696
  answer; other sizes tried are refused, so 720x928 is the one linked.

If Myer changes its page data, the run fails with a message instead of returning
empty rows.

# Actor input Schema

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

What you would type into the Myer search box, one term per line (for example dress, perfume or sheet set). Each term is read separately. A term Myer recognises is sent to its category page and that whole list is read (perfume goes to /c/beauty/all-fragrance); any other term is read as search results. A product that two terms both find is returned once, under the first.

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

Myer pages to read in full, for example https://www.myer.com.au/c/women/clothing/dresses or https://www.myer.com.au/search?query=perfume. Use a category that lists products: a top-level page such as /c/women shows only 16 products, cannot be paged, and is refused; use a sub-category such as /c/women/clothing. A filter copied from the site (a facets= parameter) is kept. Product pages (/p/...) are not accepted. Leave empty to use search terms only.

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

Read at most this many products for each search term or page. Myer lists 48 per page, so 100 reads three pages. Up to 10,000 are accepted.

## `onlyOnSale` (type: `boolean`):

Return only products whose current price is below the price before reduction at either end of their price range (the on_sale field). Products that are not reduced are read but not returned and not charged, and do not count toward Max products. A MYER one member price is not a reduction; read the member_price field for those.

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

The order Myer lists the products in, the same choices as its own sort menu. 'Relevance' is its default. The price sorts follow the lowest price of each product.

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

Use Apify's automatic datacenter proxy (the default). myer.com.au answered an Apify datacenter address with HTTP 200 when this actor was built; the residential group was not needed. A refused request is retried from a fresh address.

## Actor input object example

```json
{
  "searchTerms": [
    "dress"
  ],
  "startUrls": [],
  "maxItems": 100,
  "onlyOnSale": false,
  "sort": "relevance",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (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 = {
    "searchTerms": [
        "dress"
    ],
    "startUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/myer-products").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": ["dress"],
    "startUrls": [],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/myer-products").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": [
    "dress"
  ],
  "startUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call superslowsloth/myer-products --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,superslowsloth/myer-products"
        }
    }
}
```

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/rRAPGS125jRYJ2W54/builds/AHwqnESzV3q9lGh6n/openapi.json
