Woolworths Australia Grocery Product & Reviews Scraper avatar

Woolworths Australia Grocery Product & Reviews Scraper

Pricing

from $1.50 / 1,000 product results

Go to Apify Store
Woolworths Australia Grocery Product & Reviews Scraper

Woolworths Australia Grocery Product & Reviews Scraper

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

Abot API

Maintained by Community

Actor stats

1

Bookmarked

9

Total users

6

Monthly active users

1.8 hours

Issues response

9 days ago

Last modified

Share

Scrape woolworths.com.au grocery products and customer reviews at scale. Search by keyword with filters, browse a whole specials & offers category, or paste product / search / specials links (or bare product codes). Every product comes back as one flat record with price, was-price and discount, unit (cup) price, specials, pack size, availability, images, category, nutrition, allergens, ingredients, rating and - optionally - customer reviews.

What it does

  • Three ways to start
    • Search - one or more keywords, with sort, minimum-rating, price-range and specials-only filters, across all result pages.
    • Specials & offers category - browse a whole Woolworths specials category (Half Price, Online Only Specials, Everyday Low Price, Seasonal Price, Buy More Save More, Lower Shelf Price, Bundles, or all specials at once), or sweep every currently-discounted product in one run - including the markdowns that never get a promotions-menu category.
    • URL - paste product pages (/shop/productdetails/<code>), search pages (/shop/search/products?searchTerm=...), category pages (/shop/browse/fruit-veg, including sub-categories like /shop/browse/fruit-veg/fruit), specials listing pages (/shop/browse/specials/half-price), or bare numeric product codes. Category pages walk the category's full catalog.
  • Was-price & discount - on every discounted product you get the strike-through was-price, the savings amount and percentage, and the offer label (e.g. "Half Price", "Buy More Save More"), alongside the current price and unit (cup) price.
  • Full product detail - collect each product's rich description, barcode (EAN/GTIN), department / category, country of origin, health-star rating, ingredients, allergens, dietary statement, storage instructions, the nutrition panel, images and sibling variants.
  • Ratings & reviews - the aggregate rating (average score, rating count, review count and the 5-star-to-1-star distribution) plus customer reviews: star rating, review text, author display name and date.

Specials & offers

Pick a category under Specials & offers category (search mode) to walk a whole promotion, or paste a specials listing link in URL mode. The categories mirror Woolworths' own specials taxonomy:

Category valueCovers
all-specials-completeEverything currently discounted. Sweeps every department for the products the store flags as on special, instead of walking the promotions menu.
all-specialsEvery promotions-menu category below, merged.
half-priceHalf Price.
lower-shelf-priceLower Shelf Price.
online-only-specialsOnline Only Specials.
everyday-low-priceEveryday Low Price.
seasonal-priceSeasonal Price.
buy-more-save-moreBuy More Save More (multibuy).
bundlesBundles.

Each product on a specials listing carries its was-price, savings and offer label; multibuy offers also carry the buy-more quantity and price.

Which one should you pick? The promotions menu is a curated selection, not an index of every markdown — a genuine discount (say a plain 40% off) can appear in none of its categories. If you need every currently-discounted product, pick all-specials-complete; it reads each department's on-special listing directly, so it also catches the offers that never get a promotions-menu category.

all-specials-complete returns only products whose price is actually reduced right now — you do not need to set specialsOnly yourself. It keeps markdowns (Half Price, percentage-off, seasonal), Buy More Save More multibuy offers and Everyday Rewards member prices.

It deliberately excludes Everyday Low Price, Lower Shelf Price and Bundles. Woolworths files those under /specials, but they are regular low shelf prices rather than offers — measured live, 0 of 44, 0 of 36 and 0 of 7 of their products are flagged on special and all have wasPrice equal to price with zero savings. If you do want them, browse those categories directly with specialsCategory or a /shop/browse/specials/... URL. It returns considerably more than all-specials does, so set Max products to bound the run. Marketplace items stay excluded unless includeMarketplace is on, and excludeCategories still drops whole departments before anything is fetched.

Skipping departments you don't want

To scrape a listing except certain departments, use excludeCategories:

{
"specialsCategory": "half-price",
"excludeCategories": ["beer-wine-spirits", "everyday-market"]
}

A product is skipped if it belongs to any listed department. This matters because the storefront files the same product under several departments at once — roughly half of the products in the specials catalogue are cross-listed — so a product carried under both an excluded and a kept department is still dropped. Accepts the name from a browse link (beer-wine-spirits), the display name (Beer, Wine & Spirits), or a pasted /shop/browse/<department> URL. The decision is made from the listing page, so skipped products are never fetched in detail and cost nothing.

Every record also carries departments and departmentIds listing every department the product sits under, plus departmentNames: the human-readable name for each entry, in the same order (departmentNames[0] is the display name for departments[0], and so on). A product with no browse-taxonomy department carries neither field.

Order is not a priority. Woolworths ships this list in a fixed order per product (the same stockcode returns the same order regardless of which department page you browse it from), but that order does not reliably identify a "primary" department: checked live across 96 cross-listed products in 4 departments, departments[0] matched the department the product was actually browsed under only 47/96 times (about 49%, no better than a coin flip). The actor preserves the storefront's own order as-is and does not reorder it or guess a primary. If your pipeline currently treats departments[0] as "the" department, that assumption is not supported by the data; there is no published primary, so pick your own tie-break rule (e.g. prefer a department from your own allow-list) instead of relying on array position.

Two different category systems: departments vs department/category/subCategory

This actor exposes two unrelated taxonomies, and they do not agree with each other because they come from different Woolworths systems:

  • departments / departmentIds / departmentNames: the storefront browse taxonomy (what you see under Shop > Browse on the website). Read from the listing card itself (AdditionalAttributes.piesproductdepartmentsjson), so it is present on every mode (search, browse and URL) with no extra request, and a product is usually filed under more than one entry.
  • department / category / subCategory: Woolworths' internal SAP merchandising hierarchy (SapDepartmentName / SapCategoryName / SapSubCategoryName). This is a single-valued hierarchy (one department, one category, one sub-category), but it only comes from the product detail page, so it is present only when fetchDetails is on (default true), and it is genuinely blank on some products: the detail record still exists, but the SAP fields themselves come back empty. When absent, department/category/subCategory are simply not in the record; nothing is guessed.

departments[0] is not a substitute for category. They are different systems that classify the same product independently, so they can disagree (e.g. a product's browse department might be "Cleaning & Maintenance" while its SAP category is "Garden Aids/Seeds/Bulbs"; both are genuine, they just answer different questions). If your baseline needs the merchandising hierarchy, use department/category/subCategory with fetchDetails on; if it needs the storefront navigation, use departments/departmentNames. Don't use one to fill a gap in the other.

Use excludeSpecialsCategories to do the opposite: drop products in the categories you list instead of collecting and paying to enrich them. It uses the same category values as above; excluding all-specials drops every on-special product. Applied to the Specials & offers category, a pasted specials URL, and keyword searches; a dedicated specials listing is skipped before any page is fetched, so an excluded category costs nothing. Dropped products are never pushed or charged.

Set mode to url and paste any mix of these into urls. Listing links are walked across all their result pages, and every filter above still applies.

Link shapeWhat you get
/shop/productdetails/<code> — or just the bare codeThat single product.
/shop/browse/<department>The department, walked in full.
/shop/browse/specials/<category>That specials category.
/shop/productgroup/<id>A curated collection — the merchandised landing pages such as "Discover and shop our newest range". These are hand-picked selections that are not part of the category tree, so they can only be reached by their own link.
/shop/search/products?searchTerm=...That keyword search.

Ratings & reviews: what you get

Woolworths shows an aggregate rating (average score, rating count, review count and the 5-star-to-1-star distribution) and a customer review list on product pages. This actor captures both:

  • The aggregate rating and star distribution are collected during detail enrichment (fetchDetails), so every enriched product carries rating, ratingCount, reviewCount and ratingDistribution when it has ratings.
  • The review list is collected when fetchReviews is on, up to your maxReviewsPerProduct cap. Each review carries star rating, text, author display name and date.

Note: many grocery lines carry few or no reviews. When a product has no ratings, the rating fields are omitted (not guessed) and reviews comes back empty. Products with reviews return them in full.

Input

FieldTypeDescription
modeselectsearch (keyword + filters) or url (paste links / product codes).
queriesstring[]Search keywords (search mode). Each keyword is searched separately.
specialsCategoryselectBrowse a whole specials category: half-price, lower-shelf-price, online-only-specials, everyday-low-price, seasonal-price, buy-more-save-more, bundles, or all-specials. Use all-specials-complete to catch every currently-discounted product, including offers with no promotions-menu category. Leave blank to skip.
excludeSpecialsCategoriesselect (multi)Drop products in these specials categories instead of collecting them. Same values as specialsCategory (minus blank); excluding all-specials drops every on-special product.
excludeCategoriesstring[]Optional. Departments to skip entirely, e.g. beer-wine-spirits, everyday-market, pet. Skipped products are never collected, so they cost nothing.
sortByselectrelevance, price_asc, price_desc, name, savings.
minRatingselectKeep products rated at least 3, 4 or 5 stars (requires details).
specialsOnlybooleanKeep only products currently on special / half price.
includeMarketplacebooleanAlso include products shipped by third-party Everyday Market sellers. By default only products sold directly by Woolworths are returned, and they are excluded at the source — the third-party range dominates most departments (Home & Lifestyle lists 444,872 entries against 1,935 sold by Woolworths), so leaving it off makes a category walk both far faster and far more complete. Default false.
minPrice / maxPriceintegerKeep products within an AUD price range.
urlsstring[]Product, category, specials, product-group or search URLs, or bare product codes (url mode). See URL mode for the link shapes.
fetchDetailsbooleanCollect full product detail + aggregate rating. Default true.
fetchReviewsbooleanAlso collect customer reviews. Default false.
maxReviewsPerProductintegerCap reviews per product (0 = all). Default 20.
maxItemsintegerPrimary limit: max products for the whole run (0 = unlimited). Default 20.
maxPagesintegerOptional bound on result pages walked per keyword/category/URL (36 products/page). Empty walks every result page (does not cap products; maxItems does).
resumeFromRunIdstringOptional. 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.
proxyobjectProxy configuration. Apify Proxy is used by default and works on every plan.

Example input

{
"mode": "search",
"queries": ["milk"],
"sortBy": "relevance",
"specialsOnly": false,
"minPrice": 1,
"maxPrice": 20,
"fetchDetails": true,
"fetchReviews": true,
"maxReviewsPerProduct": 20,
"maxItems": 20,
"proxy": { "useApifyProxy": true }
}

Example input - specials category

{
"mode": "search",
"specialsCategory": "half-price",
"sortBy": "savings",
"fetchDetails": true,
"maxItems": 50,
"proxy": { "useApifyProxy": true }
}

Output

One record per product. Example (values below are illustrative):

{
"stockcode": "100000",
"name": "Example Full Cream Milk 2L",
"displayName": "Example Full Cream Milk 2L",
"title": "Example Full Cream Milk 2L",
"brand": "ExampleBrand",
"url": "https://www.woolworths.com.au/shop/productdetails/100000/example-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,
"variety": "Full Cream",
"offerId": "24000000",
"isMarketProduct": false,
"image": "https://cdn0.woolworths.media/content/wowproductimages/large/100000.jpg",
"thumbnailImage": "https://cdn0.woolworths.media/content/wowproductimages/small/100000.jpg",
"images": ["https://cdn0.woolworths.media/content/wowproductimages/large/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"
}

Field reference

FieldDescription
stockcodeWoolworths product code (the SKU).
name, displayName, title, brand, urlProduct name, display name, fuller canonical title (includes pack size), brand, product page URL.
price, wasPrice, savingsAmount, savingsPercent, isOnSpecial, isHalfPrice, isEdrSpecialCurrent price, strike-through was-price, savings amount + percentage, and specials flags (including Everyday Rewards member specials). price and isInStock are captured independently and neither is derived from the other: the actor does not assume a price implies stock, or that being in stock implies a nonzero price; whatever the storefront publishes for each field is what you get.
promoLabel, savingsLabel, promotionType, promotionInfoOffer label (e.g. "Half Price"), savings tag (e.g. "Save $7.00"), promotion type and the human-readable promotion sentence. Present on discounted products.
multibuy, memberPriceBuy-more-save-more offer (quantity, price, cupString) and Everyday Rewards member price when applicable.
cupPrice, cupMeasure, cupString, packageSize, unit, currencyUnit (cup) price, pack size and currency (AUD).
barcode, gtinFormatEAN/GTIN barcode and its GTIN format code. The dataset stores barcode as text (e.g. "9335390000141"), quoted correctly in both the JSON and CSV exports. If a long digit string like this looks truncated or turns into scientific notation (9.34E+12) after opening the CSV in Excel or Google Sheets, that is the spreadsheet app coercing the column to a number on import, not a data problem on our end. Import the CSV with that column set to Text (Excel: Data > From Text/CSV > change the column's data type to Text before loading; Sheets: paste with "Text" formatting, or add a leading apostrophe) to keep the full barcode intact.
isAvailable, isInStock, isNew, isOnlineOnly, productLimit, isMarketProduct, vendor, variety, offerIdAvailability, new/online-only flags, purchase limit, market-seller info, variety and the offer id. isOnlineOnly and isMarketProduct are independent flags, not a spectrum. isOnlineOnly means the product is only sold through the website (no physical store listing), while isMarketProduct means it is sold by a third-party Everyday Market seller rather than by Woolworths itself. A Woolworths own-brand product that is only sold online is still first-party: it has isOnlineOnly: true and isMarketProduct: false. If you are building a first-party-only dataset, filter on isMarketProduct/includeMarketplace, not on isOnlineOnly: excluding isOnlineOnly: true products will drop genuine first-party Woolworths SKUs, not just marketplace listings.
image, thumbnailImage, imagesPrimary image, thumbnail and the image list.
departments, departmentIds, departmentNamesEvery storefront browse-taxonomy department the product is filed under (a product is commonly filed under more than one), their opaque node ids, and the matching human-readable name for each departments entry (same index). Present whenever the listing card carries this data, in search, browse and URL mode alike, with no detail fetch required. This is a different taxonomy from department/category/subCategory below; see Two different category systems above.
richDescription, department, category, subCategory, countryOfOriginDescription, and Woolworths' internal SAP merchandising hierarchy (single-valued: one department, one category, one sub-category). Present only when fetchDetails is on (needs the detail page), and even then some products' SAP fields come back genuinely empty, so department/category/subCategory are omitted for those (see Two different category systems).
healthStarRating, ingredients, allergenContains, allergenMayContain, dietaryStatement, storageInstructions, nutritionGrocery labelling and nutrition (with details).
variantsSibling products (flavours / sizes) with code, name, price and URL.
rating, ratingCount, reviewCount, ratingDistributionAggregate rating and the 5★→1★ split (with details, when the product has ratings).
reviews, reviewsCollectedCollected reviews and their count (present when reviews are enabled).

Whenever a value is not published for a product, the field is omitted or null rather than guessed.

Marketplace records (includeMarketplace: true) carry isMarketProduct: true and name their third-party seller in vendor.

Proxy

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

Notes

  • Prices, specials, ratings and stock are captured as shown on the storefront at scrape time.
  • Filters (minRating, minPrice, maxPrice, specialsOnly, includeMarketplace) are applied to each product's own values, so exact numeric ranges work independently of the on-site filters.
  • Department listings mix the supermarket's own range with a much larger third-party marketplace catalog (some departments list 50,000+ marketplace items), so an uncapped category walk can legitimately run for hundreds of pages. The page log shows how many unique products have been seen against the listing's own total. Marketplace items are excluded by default; set includeMarketplace: true to collect them too.
  • The run periodically checkpoints its progress, so if the platform restarts the run (a server migration, or you use Resurrect) it picks up where it left off instead of starting over, with no duplicate products and no double charges. No input is needed for this; it is automatic.