# Woolworths Australia Grocery Products Scraper (`parsebird/woolworths-au-scraper`) Actor

Scrape Woolworths Australia grocery products by keyword or URL: prices, specials, ingredients, nutrition, ratings and reviews.

- **URL**: https://apify.com/parsebird/woolworths-au-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 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?

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

### Woolworths Australia Grocery Products Scraper

Scrape [Woolworths Australia](https://www.woolworths.com.au/) grocery products by keyword search or by pasting product, category, or specials URLs — no coding or API access required.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Search by keyword or crawl a whole department or specials category, then enrich every product with price, unit price, ingredients, nutrition, allergens, ratings and customer reviews — export as JSON, CSV, or Excel.
</td>
</tr></table>

<br>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this Woolworths scraper: `parsebird/woolworths-au-scraper` on Apify. Call it with the `ApifyClient` (Python: `ApifyClient(token).actor("parsebird/woolworths-au-scraper").call(run_input={"mode": "search", "queries": ["milk"], "maxItems": 20, "fetchDetails": True})`) or the equivalent JS client. Key inputs: `mode` ("search" or "url"), `queries` (string array), `specialsCategory` (half-price, lower-shelf-price, online-only-specials, everyday-low-price, seasonal-price, buy-more-save-more, bundles, all-specials, all-specials-complete), `excludeCategories`/`excludeSpecialsCategories`, `sortBy`, `minRating`, `specialsOnly`, `includeMarketplace` (default false), `minPrice`/`maxPrice`, `urls` (product/category/specials/product-group/search links or bare stockcodes), `fetchDetails` (default true), `fetchReviews` (default false), `maxReviewsPerProduct` (default 20, 0 = all), `maxItems` (default 20, 0 = unlimited), `maxPages`, `resumeFromRunId` for incremental delta runs, and `proxy`. Output is one JSON object per product with price, was-price, savings, department taxonomy, ingredients, nutrition, rating, and reviews. Full API reference: https://apify.com/parsebird/woolworths-au-scraper/api. Get an API token at https://console.apify.com/account/integrations.

### What does Woolworths Australia Grocery Products Scraper do?

This Woolworths scraper extracts structured grocery product data from woolworths.com.au without touching the site's anti-bot protection yourself. It works as both a **Woolworths API alternative** and a bulk export tool:

- 🔍 **Search mode** — search by keyword, exactly like the Woolworths search bar, or walk a whole [Specials & offers category](#specials--offers-categories) (Half Price, Buy More Save More, Bundles, and more).
- 🔗 **URL mode** — paste product, department, specials, product-group, or search URLs (or bare product/stockcode numbers) and get every product on those pages.
- 🏷️ **Price & specials data** — current price, was-price, savings amount, unit price, multibuy pricing, and the offer label shown on-site.
- 🧪 **Full product detail** — department/category taxonomy (both the storefront browse taxonomy and Woolworths' internal merchandising hierarchy), ingredients, allergens, nutrition panel, storage instructions, and country of origin.
- ⭐ **Ratings & reviews** — aggregate rating, rating distribution, and individual customer reviews.
- 🛒 **Marketplace control** — Woolworths-sold products only by default; optionally include third-party Everyday Market sellers.
- 📤 **Delta runs** — pass `resumeFromRunId` to fetch only products that weren't in a previous run's dataset.
- 🔌 **Connector notifications** — optionally push new listings into Notion, Linear, Airtable, or another Apify dataset as they're found.

Because it runs on the [Apify platform](https://apify.com), you also get scheduling (run it daily to track price changes), instant API and webhook access, and one-click export to JSON, CSV, Excel, HTML, or XML.

### What data can you extract from Woolworths?

| Field | Description |
|-------|-------------|
| `stockcode`, `barcode` | Woolworths product ID and barcode/GTIN |
| `name`, `displayName`, `brand` | Product name, full display name (with size), and brand |
| `price`, `wasPrice`, `savingsAmount` | Current price, pre-special price, and dollar savings (AUD) |
| `cupPrice`, `cupString`, `packageSize`, `unit` | Unit pricing and pack size |
| `isOnSpecial`, `isHalfPrice`, `offerLabel` | Special flags and the on-site offer label text |
| `multibuyPrice`, `multibuyMinQuantity` | Buy-more-save-more multibuy pricing, when offered |
| `departments`, `departmentIds`, `departmentNames` | Every storefront browse department the product is filed under |
| `department`, `category`, `subCategory` | Woolworths' internal single-valued merchandising hierarchy (needs `fetchDetails`) |
| `ingredients`, `allergenContains`, `containsGluten`, `containsNuts` | Ingredients and allergen flags |
| `nutritionalInformation`, `healthStarRating` | Full nutrition panel and health star rating |
| `rating`, `ratingCount`, `ratingDistribution` | Aggregate rating and star breakdown |
| `reviews` | Individual reviews: rating, title, text, author, date |
| `isMarketProduct` | Whether it's a third-party Everyday Market listing |
| `url`, `smallImage`/`mediumImage`/`largeImage`, `images` | Product URL and image URLs |

### How to scrape Woolworths product data

1. Click **Try for free** on the [Woolworths Australia Grocery Products Scraper](https://apify.com/parsebird/woolworths-au-scraper) page (no credit card needed to start).
2. Choose **search** mode and enter one or more keywords (e.g. `milk`, `pasta sauce`) — or switch to **url** mode and paste product, category, or specials links.
3. Optionally set filters: price range, specials category, minimum rating, departments to exclude.
4. Turn on `fetchDetails` and `fetchReviews` if you need ingredients, nutrition, and customer reviews.
5. Click **Start** and watch results land in the dataset in real time.
6. Export the finished dataset as JSON, CSV, Excel, HTML, or XML, or pull it via the [API](https://apify.com/parsebird/woolworths-au-scraper/api) / [integrations](https://docs.apify.com/platform/integrations).

### Input / Output

The input schema mirrors the Woolworths site's own vocabulary — departments, specials categories, and product codes — see the **Input** tab for the full form. Example input:

```json
{
  "mode": "search",
  "queries": ["milk"],
  "sortBy": "relevance",
  "minPrice": 1,
  "maxPrice": 20,
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviewsPerProduct": 20,
  "maxItems": 20
}
```

Output example (one dataset item per product):

```json
{
  "stockcode": 842806,
  "name": "Pantene Pro V Daily Moisture Renewal Nourishing Shampoo Dry Hair",
  "brand": "Pantene",
  "price": 15.5,
  "wasPrice": 15.5,
  "isOnSpecial": false,
  "url": "https://www.woolworths.com.au/shop/productdetails/842806/pantene-pro-v-daily-moisture-renewal-nourishing-shampoo-dry-hair",
  "department": "PERSONAL CARE",
  "category": "HAIR CARE",
  "rating": 4.5,
  "ratingCount": 333,
  "ratingDistribution": { "5": 204, "4": 107, "3": 13, "2": 3, "1": 6 }
}
```

Download results as **JSON, CSV, Excel, HTML, or XML** from the Console, or via the [Apify API](https://docs.apify.com/api/v2).

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("parsebird/woolworths-au-scraper").call(run_input={
    "mode": "search",
    "queries": ["milk"],
    "maxItems": 20,
    "fetchDetails": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["price"])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('parsebird/woolworths-au-scraper').call({
    mode: 'search',
    queries: ['milk'],
    maxItems: 20,
    fetchDetails: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Specials & offers categories

Pick a category under `specialsCategory` to walk a whole promotion, or paste a specials listing link in URL mode:

| Category value | Covers |
|-----------------|--------|
| `all-specials-complete` | Every currently-discounted product, department by department — including offers with no promotions-menu category. |
| `all-specials` | Every promotions-menu category below, merged. |
| `half-price` | Half Price. |
| `lower-shelf-price` | Lower Shelf Price. |
| `online-only-specials` | Online Only Specials. |
| `everyday-low-price` | Everyday Low Price. |
| `seasonal-price` | Seasonal Price. |
| `buy-more-save-more` | Buy More Save More (multibuy). |
| `bundles` | Bundles. |

The promotions menu is a curated selection, not an index of every markdown, so a genuine discount can appear in none of its categories — `all-specials-complete` reads each department's on-special listing directly and catches those too. Use `excludeSpecialsCategories` to drop a category instead of collecting it (skipped listings are never fetched, so they cost nothing), and `excludeCategories` to skip whole departments (e.g. `beer-wine-spirits`, `pet`) before anything is fetched.

### URL mode: supported link shapes

| Link shape | What you get |
|------------|---------------|
| `/shop/productdetails/<code>` — or just the bare code | That single product |
| `/shop/browse/<department>` | The department, walked in full |
| `/shop/browse/specials/<category>` | That specials category |
| `/shop/productgroup/<id>` | A curated collection / landing page |
| `/shop/search/products?searchTerm=...` | That keyword search |

### Use cases

- **Price monitoring** — track prices and specials on a shopping list or competitor product range over time (schedule daily runs).
- **Market research** — analyze pricing, ingredients, and ratings across a category or brand.
- **Deal hunting / couponing tools** — pull every Half Price or Buy More Save More offer for a comparison site or newsletter.
- **Nutrition and allergen datasets** — build a database of ingredients, allergens, and nutrition panels for grocery products.
- **Assortment tracking** — see which departments a product is cross-listed under, or when new products appear in a category.

### How it works

1. The Actor opens a residential Australian session against woolworths.com.au and calls the same internal search/category APIs the website itself uses.
2. In search mode, it pages through keyword results (or a specials category) applying your price, rating, and department filters as it goes.
3. In URL mode, it classifies each link (product, department, specials, product group, or search) and fetches it the same way.
4. When `fetchDetails` is on, it fetches full product detail (ingredients, nutrition, department hierarchy) and aggregate ratings for each kept product.
5. When `fetchReviews` is on, it fetches individual customer reviews up to your cap.
6. Every result is pushed to the dataset immediately, and optionally forwarded to your Notion, Linear, Airtable, or Apify connectors.

### How much does it cost to scrape Woolworths?

This Actor uses the [Pay-Per-Event](https://docs.apify.com/platform/actors/publishing/monetize#pay-per-event-pricing-model) pricing model — you only pay for what you get, with no separate compute charge.

| Event | Free | Bronze | Silver | Gold |
|-------|------|--------|--------|------|
| Product (per 1,000) | $1.99 | $1.69 | $1.39 | $0.99 |
| Detail (per 1,000) | $0.49 | $0.49 | $0.49 | $0.49 |

A search for 1,000 products with `fetchDetails` on costs roughly $2.48 (Free plan) down to $1.48 (Gold plan). Turning `fetchDetails` off (price/specials data only) roughly halves the cost. Apify's monthly platform usage credits apply to any plan.

### Is it legal to scrape Woolworths?

Yes — scraping publicly available data is generally legal, as confirmed in cases like *hiQ Labs v. LinkedIn*. This Actor only collects product information that's publicly visible on woolworths.com.au to anyone browsing the site. You are responsible for how you use the collected data — always check the target site's terms of service and applicable law (including the Australian Privacy Act, where relevant) before reusing scraped data commercially. See Apify's [blog post on web scraping legality](https://blog.apify.com/is-web-scraping-legal/) for more detail.

### Other ParseBird e-commerce scrapers

- [Walmart Product Scraper](https://apify.com/parsebird/walmart-product-scraper)
- [Target Product Scraper](https://apify.com/parsebird/target-product-scraper)
- [AliExpress Scraper](https://apify.com/parsebird/aliexpress-scraper)
- [MercadoLibre Scraper](https://apify.com/parsebird/mercadolibre-scraper)

### FAQ

**Does this use the official Woolworths API?**
No — Woolworths does not offer a public product API. This Actor reads the same data the woolworths.com.au website itself loads, structured into clean JSON.

**Why is `includeMarketplace` off by default?**
Most departments are dominated by third-party Everyday Market sellers (for example, one department lists over 400,000 marketplace entries against under 2,000 sold directly by Woolworths), so leaving it off keeps runs fast and focused on Woolworths' own range. Turn it on to also include marketplace listings.

**Some products have no `rating` field — is that a bug?**
No. Many grocery lines carry few or no reviews; when a product has no ratings, the field is simply omitted rather than shown as zero.

**I set `minRating` and got fewer products than `maxItems` — why?**
`minRating` is applied after the Max products cap, not before, so a small `maxItems` combined with a rating filter can leave you with fewer (even zero) results if the top-ranked candidates happen to be unrated. Raise `maxItems` to give the filter more candidates to work with.

**Can I get only new products since my last run?**
Yes — set `resumeFromRunId` to a previous run or dataset ID. Products already in that dataset are skipped, so you get a clean delta.

**Can I schedule this to run automatically?**
Yes. Use Apify's [Scheduler](https://docs.apify.com/platform/schedules) to run it daily, weekly, or at any interval, and combine it with [Apify's storage integrations](https://docs.apify.com/platform/integrations) (Google Sheets, Slack, Make, Zapier, webhooks) to get notified of price changes.

**A search with strict filters returned fewer items than I expected — why?**
To avoid walking an entire multi-hundred-thousand-item catalog when a keyword or category is almost entirely filtered out (for example a keyword Woolworths mostly doesn't sell directly, with `includeMarketplace` off), the Actor stops a source after 15 consecutive result pages that matched none of your filters. Loosen the filters, or split the run into narrower keywords/categories, to collect more.

**I found a bug or missing field — where do I report it?**
Open an issue on the Actor's **Issues** tab in Apify Console, or use the [API](https://apify.com/parsebird/woolworths-au-scraper/api) directly for programmatic access.

# Actor input Schema

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

Search by keyword/category, or paste Woolworths URLs directly.

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

Search keywords for search mode. Each keyword is searched separately.

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

Browse a whole specials category (search mode) instead of a keyword. 'All specials (complete)' sweeps every department for anything currently discounted, including offers with no promotions-menu category. Leave blank to skip.

## `excludeSpecialsCategories` (type: `array`):

Drop products in these specials categories instead of collecting them. Skipped listings are never fetched, so they cost nothing.

## `excludeCategories` (type: `array`):

Departments to skip entirely, e.g. beer-wine-spirits, everyday-market, pet. Accepts a browse-URL slug, display name, or full URL. Skipped products are never fetched, so they cost nothing.

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

Order results are collected/kept in.

## `minRating` (type: `string`):

Keep only products rated at least this many stars. Requires product details (fetchDetails is turned on automatically if needed). Applied after Max products, so a small Max products combined with a rating filter can return fewer items than expected.

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

Keep only products currently on special / half price.

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

Also include products shipped by third-party Everyday Market sellers. Off by default: only products sold directly by Woolworths are returned, which is both faster and more complete for most departments.

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

Keep only products priced at or above this amount.

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

Keep only products priced at or below this amount.

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

Product, category, specials, product-group or search URLs, or bare product codes (url mode). See the README for supported link shapes.

## `fetchDetails` (type: `boolean`):

Collect full product detail (department/category, ingredients, nutrition, allergens) plus aggregate rating.

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

Also collect customer reviews for each product.

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

Cap reviews collected per product. 0 = all available reviews.

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

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

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

Optional bound on result pages walked per keyword/category/URL (36 products per page). Leave empty to walk every result page (maxItems still caps the total).

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

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.

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

Woolworths blocks most datacenter IPs, so Residential proxy is used by default.

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

Optionally send results into apps you already use. Each entry needs a 'type' (notion, linear, airtable or apify) and a 'token'; Notion also needs the Notion parent page URL below, Linear needs 'teamId', Airtable needs 'baseId' and 'tableName', Apify needs 'datasetId'. Leave empty to skip - this never changes the dataset output.

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

Notion connector only: URL of the Notion page under which item pages are created.

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

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

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "milk"
  ],
  "specialsCategory": "",
  "excludeSpecialsCategories": [],
  "excludeCategories": [],
  "sortBy": "relevance",
  "minRating": "",
  "specialsOnly": false,
  "includeMarketplace": false,
  "fetchDetails": true,
  "fetchReviews": false,
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AU"
  },
  "mcpConnectors": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `dataset` (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": [
        "milk"
    ],
    "maxItems": 20,
    "mcpConnectors": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/woolworths-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": ["milk"],
    "maxItems": 20,
    "mcpConnectors": [],
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/woolworths-au-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 '{
  "mode": "search",
  "queries": [
    "milk"
  ],
  "maxItems": 20,
  "mcpConnectors": []
}' |
apify call parsebird/woolworths-au-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/woolworths-au-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/WmIw8MzCy1liKGjEV/builds/4SAOfyqRHxGPpbDVp/openapi.json
