Harvey Norman Australia Scraper - Products & Reviews avatar

Harvey Norman Australia Scraper - Products & Reviews

Pricing

from $1.00 / 1,000 product results

Go to Apify Store
Harvey Norman Australia Scraper - Products & Reviews

Harvey Norman Australia Scraper - Products & Reviews

Scrape Harvey Norman Australia products: name, brand, price, was-price / discount, specifications, image gallery, GTIN, department, stock, dimensions, rating and customer reviews. Search by keyword with brand, price and rating filters, or paste product / listing URLs.

Pricing

from $1.00 / 1,000 product results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

7 hours ago

Last modified

Share

Harvey Norman Australia Scraper — Products & Reviews

Extract product data from harveynorman.com.au — Australia's electrical, computer, furniture and bedding retailer. Search by keyword with filters, or paste product and listing URLs, and get one clean record per product with an optional full detail extraction that adds specifications, image gallery, department, dimensions and customer reviews.

What you can collect

  • Identity — canonical title, name, brand, SKU, product id, GTIN, product URL
  • Pricing — current price, was / original price, discount amount and percent, an isOnSpecial flag, currency and the promotion label
  • Specials — scrape the store-wide Super Deals or Clearance collections directly, or paste any sale listing URL
  • Ratings — average rating and review count on every product
  • Detail (optional) — full specifications, image gallery, description, department, category path, stock status, dimensions
  • Reviews (optional) — per-review rating, title, body, author, date, verified-purchase flag, helpful votes, pros/cons, plus an aggregate summary (rating, count, star distribution, recommended count)
  • 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

Give one or more keywords (for example oled tv, gaming laptop). Each keyword resolves to its best-matching department listing, which is then walked page by page. Narrow results with brand, minimum / maximum price and minimum rating filters, and order them with sort by.

Pick a Specials / offers category to scrape a promotional collection instead of (or alongside) your keywords:

  • Super Deals — the store-wide hottest-deals grid
  • Clearance — the run-out / reduced-to-clear range

Discounted products carry the was / original price, the discount amount and percent, an isOnSpecial flag and the promotion label straight from the listing — no detail fetch required. Products that are not discounted return isOnSpecial: false and wasPrice: null; a markdown is never fabricated.

🔗 URL

Paste product URLs (ending in .html) to scrape single products, or paste department / listing URLs to walk multiple pages of products — including any specials or department-scoped sale listing URL (for example a TV sale or laptop sale page). Both are supported in the same run.

Detail enrichment & reviews

Turn on Fetch full product detail + reviews to open each product page and collect the full specification set, image gallery, description and an aggregate review summary plus a reviews[] array. Cap the number of reviews per product with Max reviews per product (0 = all available). With detail off, each record still carries identity, price and the aggregate rating from the listing.

Products with no reviews simply omit the review fields — they are never faked.

Example input

{
"mode": "search",
"queries": ["oled tv"],
"brand": "LG",
"minPrice": 1000,
"maxPrice": 6000,
"sortBy": "priceDesc",
"detailEnrichment": true,
"maxReviewsPerProduct": 20,
"maxItems": 50,
"proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "AU" }
}

Scrape the store-wide clearance range with was-prices and reviews:

{
"mode": "search",
"specialsCategory": "clearance",
"detailEnrichment": true,
"maxReviewsPerProduct": 10,
"maxItems": 50,
"proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "AU" }
}

Example output

Example data below is illustrative.

{
"productId": 900123,
"sku": "OLED65EXAMPLE",
"title": "Acme 65-inch 4K OLED Smart TV",
"name": "Acme 65-inch 4K OLED Smart TV",
"brand": "Acme",
"url": "https://www.harveynorman.com.au/acme-65-inch-4k-oled-smart-tv.html",
"imageUrl": "https://hnau.imgix.net/media/catalog/product/a/c/acme-65-oled.jpg",
"price": 3495.0,
"wasPrice": 3995.0,
"discountAmount": 500.0,
"discountPercent": 12.5,
"isOnSpecial": true,
"promotion": "Save $500",
"currency": "AUD",
"rating": 4.7,
"reviewCount": 128,
"brandUrl": "https://www.harveynorman.com.au/brands/acme",
"description": "Key Features Vivid OLED panel with deep blacks and lifelike colour...",
"shortDescription": "A 65-inch 4K OLED television with smart features and low-latency gaming.",
"specifications": {
"Product Type": "OLED TVs",
"Screen Size": "65 inch",
"Resolution": "4K Ultra HD",
"Barcode (GTIN)": "9312345678900"
},
"images": [
"https://hnau.imgix.net/media/catalog/product/a/c/acme-65-oled-front.jpg",
"https://hnau.imgix.net/media/catalog/product/a/c/acme-65-oled-side.jpg"
],
"stockStatus": "IN_STOCK",
"gtin": "9312345678900",
"department": "Audio Visual",
"category": "OLED TVs",
"categoryPath": "tv-blu-ray-home-theatre/tvs-by-type/oled-tvs",
"dimensions": { "height": 82.6, "depth": 4.5, "width": 144.4, "weight": 22.1, "colour": "Black" },
"ratingDistribution": { "5": 96, "4": 20, "3": 6, "2": 3, "1": 3 },
"recommendedCount": 110,
"reviewsCollected": 2,
"reviews": [
{
"reviewId": "100000001",
"rating": 5,
"title": "Stunning picture",
"body": "Deep blacks and vivid colour, exactly what I hoped for.",
"author": "SampleReviewer",
"location": "NSW",
"date": "2026-06-20T09:15:00.000+00:00",
"verifiedPurchase": true,
"isRecommended": true,
"helpfulCount": 4,
"notHelpfulCount": 0,
"isSyndicated": false,
"pros": ["Picture quality"],
"cons": null
}
]
}

Tips

  • Keep Max products modest while you dial in your keywords and filters, then raise it for a full pull.
  • Australian residential proxy is required for reliable results. On the free plan, coverage may be limited and some runs may return no results.
  • Use URL mode with a department URL to scrape an entire category.
  • Set Max pages per listing to 0 (the default) to walk the whole catalogue for a keyword or URL — the run still stops naturally once the storefront's own result total is reached or a page repeats with no new products, so there is no artificial page cap.
  • Resume a large run: pass a prior run's ID (or dataset ID) as resumeFromRunId and the scraper seeds its de-duplication set from that run, appending only products it hasn't seen — handy for topping up a full-catalogue crawl without re-paying for duplicates.

Resume & recurring updates

There are two different things here — pick the one that matches what you're doing:

NeedUse
A crawl stopped and should continueresumeFromRunId / automatic checkpoint recovery
Run the same search every day and receive only changesincrementalMode
Keep separate daily campaigns for similar searchesdistinct stateKey values
Run a normal full snapshotleave 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/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:

FieldDescription
changeTypeNEW | UPDATED | UNCHANGED | REAPPEARED | EXPIRED
changedFieldsTop-level fields that changed since last seen; non-empty only for UPDATED
firstSeenAtWhen this product was first observed by this monitoring campaign
lastSeenAtWhen this product was last observed

Scheduled-run example — same search, run daily:

Day 1 (first run ever for this search):

{ "mode": "search", "queries": ["oled tv"], "incrementalMode": true }

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

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

{ "mode": "search", "queries": ["oled tv"], "incrementalMode": true }

→ products whose 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 (optional)

Pipe results straight into the tools you already use via Model Context Protocol (MCP) connectors — Notion (a rich page per product), Linear, Airtable or Apify. Authorize a connector under Apify → Settings → API & Integrations, then select it in the input. This never changes the dataset output.