Woolworths AU Scraper - Products, Prices & Reviews
Pricing
from $1.50 / 1,000 product results
Woolworths AU Scraper - Products, Prices & Reviews
Scrape Woolworths Australia (woolworths.com.au) grocery products and reviews. Search by keyword or paste product / search links. Returns name, brand, price, was price, unit price, pack size, specials, availability, images, category, nutrition, allergens, ingredients, rating and customer reviews.
Pricing
from $1.50 / 1,000 product results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
3
Bookmarked
41
Total users
18
Monthly active users
1.8 hours
Issues response
5 days ago
Last modified
Categories
Share
Woolworths Scraper: Grocery Prices, Specials and Reviews
Woolworths Scraper turns the Woolworths Australia online supermarket into structured grocery data. Search by keyword, browse a whole specials category, or paste product, category, specials or search links (or bare product codes), and get back price, was price and savings, unit price, pack size, stock and availability, images, department, nutrition, ingredients, allergens, health star rating, and customer ratings and reviews. Export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Three ways to start. Search by keyword with filters, browse a whole Woolworths specials category, or paste product, category, specials or search links, including bare numeric product codes.
- Full price picture. Current price, strike-through was price, savings amount and percentage, unit (cup) price, offer label, and multibuy or member-price details when they apply.
- A separate in-store price. Woolworths prices delivery/pickup and in-store purchases as two independent offers on the same product; this actor returns both, with no extra request needed.
- Deep specials coverage. Walk any single promotions category, or sweep every currently discounted product in one run, including markdowns that never get a promotions-menu category.
- Full product detail on demand. Rich description, department and category, country of origin, health star rating, ingredients, allergens, dietary statement, storage instructions, the nutrition panel, and sibling variants.
- Ratings and reviews. Aggregate rating, star distribution and a capped list of customer reviews per product.
- Built for schedules. Incremental mode returns only new and changed products on recurring runs, and resume continues one interrupted run without re-billing what it already collected.
Use Cases
- Price and specials monitoring: track price, was price and offer labels across a shopping list or a whole department, and catch markdowns the promotions menu never lists.
- Grocery comparison and deal sites: publish weekly specials roundups using savings amount, unit price and multibuy details.
- Nutrition and dietary research: collect ingredients, allergens, health star rating and dietary statements at scale.
- Review and sentiment analysis: gather star ratings and review text per product for brand or category studies.
- Catalog and compliance auditing: filter or flag alcohol and tobacco listings using the built-in restricted-item flags.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
stockcode | "100000" |
name / brand | "Full Cream Milk 2L" / "Example Brand" |
price / wasPrice | 3.1 / 3.9 |
savingsAmount / savingsPercent | 0.8 / 21 |
promoLabel | "Prices Dropped" |
cupString / packageSize | "$1.55 / 1L" / "2L" |
isOnSpecial | true |
isInStock / isAvailable | true / true |
ageRestricted / isTobacco | false / false |
inStorePrice / inStoreIsOnSpecial | 3.5 / true |
departments / departmentNames | ["dairy-eggs-fridge"] / ["Dairy, Eggs & Fridge"] |
department / category / subCategory | "Dairy, Eggs & Fridge" / "Milk" / "Full Cream Milk" |
healthStarRating | "4.5" |
ingredients | "Full cream milk." |
allergenContains / allergenMayContain | "Milk" / "May contain traces of soy" |
slug | "liddells-lactose-free-high-protein-full-cream-long-life-milk" |
breadcrumbs | ["GROCERIES", "BEVERAGES", "LONGLIFE MILK - DAIRY"] (detail enrichment) |
attributes | {"allergencontains": "Milk"} (non-empty storefront attributes, detail enrichment) |
specifications | {"packageSize": "1L", "unit": "Each"} (pack size, unit, weight, dimensions when published) |
dietaryStatement | "Vegetarian" |
nutrition | { "servingsPerPack": "8", "servingSize": "250mL" } |
rating / reviewCount | 4.6 / 54 |
ratingDistribution | { "5": 96, "4": 20, "3": 7, "2": 3, "1": 2 } |
variants | sibling flavours/sizes: stockcode, name, price, URL |
url | product page on woolworths.com.au |
Detail-enriched products also carry richDescription, fullDescription, importantInformation, storageInstructions, countryOfOrigin, barcode, multibuy and memberPrice offer details, an images gallery, and, when reviews are enabled, reviews with each review's rating, text, author display name and date.
Output views
The dataset has four views: Products (price, was price, savings, stock, rating), Product details (barcode, ingredients, allergens, nutrition, health star rating, breadcrumbs; descriptions, attributes and specifications are in the full records), Reviews (one row per review: the review rating and text, author, date and source) and Changes (incremental) (change status and changedFields). The run also saves a run summary under the OUTPUT key of the key-value store.
How to Use
- Pick a mode:
search(keywords, plus an optional specials category) orurl(paste product, category, specials or search links, or bare product codes). - Fill in the fields for that mode, then set the filters that apply to both, such as price range, minimum rating or specials only.
- Turn on Fetch product details and Fetch customer reviews if you need nutrition, ingredients or reviews, then set Max products to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Search a keyword in a price range:
{"mode": "search","queries": ["milk"],"minPrice": 1,"maxPrice": 6,"fetchDetails": true,"maxItems": 20}
Every currently discounted product, biggest savings first:
{"mode": "search","specialsCategory": "all-specials-complete","sortBy": "savings","maxItems": 200}
Paste product and category links, with reviews:
{"mode": "url","urls": ["https://www.woolworths.com.au/shop/productdetails/32731","https://www.woolworths.com.au/shop/browse/fruit-veg"],"fetchReviews": true,"maxReviewsPerProduct": 10}
Daily monitoring of a search, changes only:
{"mode": "search","queries": ["tim tam"],"incrementalMode": true,"stateKey": "tim-tam-watch"}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/woolworths-au-scraper").call(run_input={"mode": "search", "queries": ["milk"]})for product in client.dataset(run["defaultDatasetId"]).iterate_items():print(product["name"], product["price"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/woolworths-au-scraper').call({ mode: 'search', queries: ['milk'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Choosing a specials category
The promotions menu (half-price, buy-more-save-more, and so on) is a curated selection, not an index of every markdown, so a genuine discount can sit in none of its categories. Pick all-specials-complete to sweep every department for products the store currently flags as reduced, including offers the promotions menu never lists. It deliberately excludes Everyday Low Price, Lower Shelf Price and Bundles, since those are regular low shelf prices rather than offers, and it returns considerably more than the promotions menu does, so set Max products to bound the run.
Supported link shapes (URL mode)
| Link shape | Example | Notes |
|---|---|---|
| Product page with name | https://www.woolworths.com.au/shop/productdetails/32731/coca-cola-classic-soft-drink-bottle | One product |
| Product page without name | https://www.woolworths.com.au/shop/productdetails/32731 | One product |
| Bare product code | 32731 | One product |
| Keyword search | https://www.woolworths.com.au/shop/search/products?searchTerm=milk | All result pages |
| Search with page and sort | .../search/products?searchTerm=milk&pageNumber=2&sortBy=PriceAsc | Starts at that page (partial scope, never marks products expired) and uses that sort |
| Top-level category | https://www.woolworths.com.au/shop/browse/fruit-veg | All result pages |
| Sub-category | https://www.woolworths.com.au/shop/browse/fruit-veg/fruit | All result pages |
| Category with page | .../shop/browse/fruit-veg/fruit?pageNumber=2 | Starts at that page (partial scope) |
| Specials bucket | https://www.woolworths.com.au/shop/browse/specials/half-price | All result pages |
| Curated product group | https://www.woolworths.com.au/shop/productgroup/200726-300836-discover-and-shop-our-newest-range | Needs the full id-and-name segment; a bare id logs a warning |
Without www or mobile host | https://woolworths.com.au/..., https://m.woolworths.com.au/... | Same as the www forms |
sortBy in a pasted link accepts TraderRelevance, PriceAsc, PriceDesc, ProductName and SavingsAmountDesc (or the Sort by input values) and overrides Sort by for that link. Unrecognised links, non-numeric pageNumber and unknown sortBy values are logged as warnings, never dropped silently.
Default URLs: if you run URL mode and leave the URLs field untouched, the actor now scrapes one example of each shape (a product page, search, sub-category, specials bucket and product group) instead of nothing. Clear the field or replace it to scrape only your own links.
Resume and recurring updates
- Resume from a previous run (
resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips every product already collected there, so you do not pay twice. - Incremental mode (
incrementalMode) is for scheduled runs over the same search or category. Each product is classifiedNEW,UPDATED(withchangedFieldsnaming what moved, such as price or specials),REAPPEARED, orEXPIRED(only after a run that scanned the whole scope, and only withemitExpired; never after a run limited by Max products or Max pages, started from a pasted link at page 2 or later, or that lost a result page).UNCHANGEDrows are suppressed and not billed unlessemitUnchangedis on. A product counts asUPDATEDwhen its price, was-price and savings, specials and promotion flags, in-store price, availability or stock, size, name, details or rating figures change. Review text, the search path that found the product, image link hosts and the order of variants never causeUPDATED; they are still returned on every row.stateKeynames or deliberately shares a monitoring campaign's stored baseline. - Ignore fields when detecting changes (
ignoreFieldsForChanges, incremental mode only) lists output fields (for examplecupString) that must not make a productUPDATEDand are left out ofchangedFields. They are still returned on every row. Changing the list never re-bills products you already track, because the stored baseline is compared with the current list.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape, the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each product, not the full JSON. Notion gets one page per product; other connectors get a best-effort write. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search (keywords and filters) or url (paste links / product codes). |
queries | array | (none) | Search keywords (search mode). Each keyword is searched separately. |
specialsCategory | string | "" | Browse a whole specials category (search mode), or leave blank to skip. |
urls | array | (none) | Product, category, specials or product-group URLs, search URLs, or bare product codes (url mode). |
sortBy | string | relevance | relevance, price_asc, price_desc, name, or savings. |
minRating | string | 0 | Keep products rated at least this many stars: 0, 3, 4, or 5. Requires fetchDetails. |
specialsOnly | boolean | false | Keep only products currently on special. |
excludeSpecialsCategories | array | (none) | Drop products in these specials categories instead of collecting and paying to enrich them. |
excludeCategories | array | (none) | Departments to skip entirely, so they are never collected or charged. |
includeMarketplace | boolean | false | Also include third-party Everyday Market seller products. |
minPrice | integer | (none) | Keep products priced at or above this amount, in AUD. |
maxPrice | integer | (none) | Keep products priced at or below this amount, in AUD. |
fetchDetails | boolean | true | Collect full product detail plus aggregate rating. |
fetchReviews | boolean | false | Also collect customer reviews. |
maxReviewsPerProduct | integer | 20 | Cap on reviews collected per product (the input accepts up to 1000; values above 500 are treated as 500, 0 = 500). |
maxItems | integer | 20 | Maximum number of products to return across the run (0 = unlimited; hard schema maximum 1,000,000). |
maxPages | integer | (none) | Optional cap on result pages walked per keyword, category or URL. Leave empty to walk every page. |
resumeFromRunId | string | (none) | ID of a previous run or dataset of this actor; already-collected products are skipped. |
incrementalMode | boolean | false | Return only new, updated and reappeared products on scheduled runs. |
stateKey | string | (none) | Name or share an incremental-mode monitoring campaign's stored state. |
emitUnchanged | boolean | false | Also return (and bill) products with no change since the last run. |
emitExpired | boolean | false | Also return (and bill) products from the baseline that are no longer found. |
ignoreFieldsForChanges | array | (none) | Incremental mode only: field names that never count as a change. |
proxy | object | Apify Proxy (standard pool first, residential Australia on a refusal) | Proxy and connection settings. |
mcpConnectors | array | (none) | Optional: send a summary of each product to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which product pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"stockcode": "100000","name": "Full Cream Milk 2L","displayName": "Full Cream Milk 2L","title": "Full Cream Milk 2L","brand": "Example Brand","url": "https://www.woolworths.com.au/shop/productdetails/100000/full-cream-milk","price": 3.1,"wasPrice": 3.9,"savingsAmount": 0.8,"savingsPercent": 21,"isOnSpecial": true,"isHalfPrice": false,"isEdrSpecial": false,"promoLabel": "Prices Dropped","savingsLabel": "Save $0.80","promotionType": "Special","cupPrice": 1.55,"cupMeasure": "1L","cupString": "$1.55 / 1L","packageSize": "2L","unit": "Each","currency": "AUD","barcode": "9300000000000","gtinFormat": 13,"isAvailable": true,"isInStock": true,"isNew": false,"isOnlineOnly": false,"ageRestricted": false,"isTobacco": false,"inStorePrice": 3.5,"inStoreWasPrice": 3.9,"inStoreSavingsAmount": 0.4,"inStoreSavingsPercent": 10,"inStoreIsOnSpecial": true,"inStoreCupPrice": 1.75,"inStoreCupString": "$1.75 / 1L","image": "https://www.woolworths.com.au/wowproductimages/large/100000.jpg","thumbnailImage": "https://www.woolworths.com.au/wowproductimages/small/100000.jpg","departments": ["dairy-eggs-fridge", "lunch-box"],"departmentIds": ["1_C2FCE2B", "1_9E92C35"],"departmentNames": ["Dairy, Eggs & Fridge", "Lunch Box"],"richDescription": "A fresh Australian full cream milk, rich and creamy.","department": "Dairy, Eggs & Fridge","category": "Milk","subCategory": "Full Cream Milk","countryOfOrigin": "Made in Australia","healthStarRating": "4.5","ingredients": "Full cream milk.","allergenContains": "Milk","dietaryStatement": "Vegetarian","storageInstructions": "Keep refrigerated below 4C.","nutrition": { "servingsPerPack": "8", "servingSize": "250mL" },"rating": 4.6,"ratingCount": 128,"reviewCount": 54,"ratingDistribution": { "5": 96, "4": 20, "3": 7, "2": 3, "1": 2 },"reviews": [{"rating": 5.0,"body": "Fresh and creamy, our family buys it every week.","author": "sampleShopper","date": "2025-02-14T06:01:00.000Z","syndicatedFrom": "woolworths"}],"reviewsCollected": 1,"searchMode": "search"}
Plan Requirement
By default the actor uses Apify Proxy: it starts on the standard (datacenter) pool and moves to a residential Australian pool automatically when the store refuses a connection, so you need an Apify plan that includes proxy access (https://apify.com/pricing). Residential Australian exits give more headroom on large walks; pick them under Proxy & connection if you want them from the first request.
An Apify free plan includes no proxy access. On a free plan the run logs "The selected connection is unavailable to this run." and "Apify free plans do not include residential proxies.", continues on a built-in backup connection, and results may be limited or empty. When every connection is refused the run stops with "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid." When the backup connection is reachable but no results page loads, the run stops with "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Woolworths pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again." Choose your proxy under Proxy & connection.
FAQ
How much does it cost?
You pay per product returned in the dataset, plus a one-time detail-enrichment charge for each product where detail and/or review extraction actually ran, and a small run-start charge. The Pricing tab shows the current rates. Use Max products to cap the cost of any run.
Is it legal to scrape Woolworths?
This actor collects only publicly available product information from the Woolworths website. You are responsible for how you use it: follow Woolworths' terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Prices and specials change constantly and are correct only at scrape time.
Can I get only new or changed products on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared products, and unchanged ones are not billed unless you turn on Emit unchanged.
What is the difference between Resume and Incremental mode?
They solve different problems. Resume continues ONE specific interrupted run: paste its run or dataset ID and already-collected products are skipped once. Incremental mode is for running the same search or category again and again, for example daily, and remembers its own baseline between runs so a recurring run returns only what changed. Use Resume to finish a run that stopped partway; use Incremental mode for ongoing monitoring.
Why did my run fail instead of returning an empty dataset?
A run fails only when no connection could be established at all before scraping started (for example a plan without proxy access, see Plan Requirement), or when a Resume from a previous run ID could not be read. A search or category that genuinely matches nothing, because your filters excluded every result or the keyword had no matches, still completes successfully with an empty (or filtered) dataset and a warning in the run log explaining why, rather than showing as failed.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push a summary of your results into Notion, Linear or Airtable.
๐ Want more grocery data?
Pair this actor with these related scrapers from the same team:
| ๐ฅฆ Coles AU Scraper Scrape Coles.com.au grocery products and customer reviews. Search by keyword, browse... | ๐ฅฆ ALDI AU Scraper Scrape ALDI Australia (aldi.com.au) products: name, brand, price, was-price, savings... |
| ๐ฅฆ Carrefour Spain Scraper Scrape Carrefour Spain (carrefour.es) products. Search by keyword, browse a category, or... | ๐ฅฆ Lidl.es Products, Weekly Offers, Prices & Reviews Scraper Scrape Lidl.es grocery and non-food products across weekly offers, tools, home, garden... |
| ๐ฅฆ FoodHero Scraper Scrape FoodHero surplus grocery deals across Canada by area, store or offer ID. Extract... | ๐ท Dan Murphyโs Scraper Scrape Dan Murphyโs products by category, keyword, or specials. Extract 45+ fields... |
๐ Browse all abotapi scrapers
๐ฌ Support
- ๐ Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- ๐ ๏ธ Need another site, extra fields or a private build? Email contact@abotapi.com.
- โญ Enjoying it? A quick review on the actor page helps other users find it.