# Officeworks Products, Prices, Stock & Reviews Scraper (`abotapi/officeworks-scraper`) Actor

Scrape Officeworks (officeworks.com.au) products: name, brand, price, GST, stock by state, category, images, specifications, identifiers, plus ratings and reviews with star distribution. Search by keyword with brand, price and rating filters, or paste product, search or category URLs.

- **URL**: https://apify.com/abotapi/officeworks-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product results

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/platform/actors/running/actors-in-store#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

## Officeworks Australia Scraper - Products & Reviews

Scrape **Officeworks** products from
[officeworks.com.au](https://www.officeworks.com.au) into a clean, structured
dataset. Search by keyword with brand, price and rating filters, browse the
**Deals** and **Clearance** specials collections, or paste product, search and
category URLs directly. Capture the current price plus any **was / original
price and discount**, a canonical product **title**, the **variant** matrix, and
optionally the full product detail plus customer ratings and reviews with an
aggregate rating summary and a star-rating distribution for every product.

Officeworks is Australia's leading retailer of office supplies, technology,
furniture, print and stationery. This actor turns any Officeworks search,
category or product page into structured rows you can analyse, monitor or feed
into your own tools.

### What you get

One flat record per product, including:

- **Identity** - `name`, `title` (canonical, brand-prefixed), `brand`, `sku`,
  `seoPath`, `urlKeyword`, `gtin`, `manufacturerPartNumber`, `productType`
- **Price** - `price`, `edlpPrice`, `gstRate`, `hasBusinessPrice`, `currency`
- **Specials & discount** - `isOnSpecial`, `promoLabel` (the store's own badge,
  e.g. Deal / Clearance / Low Price), `isNew`, and, when a product is genuinely
  reduced below its everyday price, `wasPrice`, `savingsAmount`, `savingsPercent`
- **Availability** - `availableStates` (in-stock states), `isAvailableInStore`,
  `availableOnline`, `isClearance`
- **Variants** - `variants` (per-variant sku, url, distinguishing attributes and
  thumbnail), `variantAxes`, `variantCount`
- **Category** - `category`, `categories` (full breadcrumb path), `categoryPath`,
  `categoryHierarchy` (full category chains)
- **Descriptions** - `shortDescription`, `longDescription`, `metaDescription`,
  `features` (feature bullets)
- **Attributes** - `specifications` and `attributes` (name/value pairs)
- **Media** - `imageUrl`, `images` (full gallery)
- **Ratings & reviews** - `rating` (0-5), `reviewCount` on every card, and with
  detail enrichment also `ratingDistribution`, `recommendedCount` and
  `reviews[]` with per-review rating, title, body, author, ISO-8601 date,
  helpful count, pros/cons and secondary ratings, plus `reviewsCollected`

### Modes

#### Search by keyword + filters

Set **Mode = search** and add one or more **Search keywords**. Each keyword is
searched separately. Refine with:

- **Specials / offers collection** - browse **Deals** or **Clearance** instead
  of (or alongside) your keywords; brand, price, rating and sort still apply
- **Brand** - keep only a given brand
- **Minimum / maximum price** (AUD)
- **Minimum rating** (1-5)
- **Include unavailable products** - on by default
- **Sort by** - relevance, newest, name A-Z, price low-to-high, price
  high-to-low, or rating low-to-high / high-to-low

#### Scrape pasted URLs

Set **Mode = url** and paste **Officeworks URLs**:

- A **product URL** (`/shop/officeworks/p/<slug>`, e.g.
  `https://www.officeworks.com.au/shop/officeworks/p/some-product-sku`) returns
  that single product.
- A **search URL** (e.g.
  `https://www.officeworks.com.au/shop/officeworks/search?q=laptop`) or a
  **category URL** (e.g.
  `https://www.officeworks.com.au/shop/officeworks/c/office-supplies/pens`)
  returns multiple pages of results, continuing forward from the page in the URL.
- A **specials URL** works the same way - paste
  `https://www.officeworks.com.au/shop/officeworks/c/deals` or
  `https://www.officeworks.com.au/shop/officeworks/c/clearance`.

### Specials, was-price & discount

Officeworks groups its promotions into two storefront collections - **Deals**
(curated featured offers) and **Clearance** (reduced-to-clear stock). Pick one
in **Specials / offers collection** in search mode, or paste its URL in URL mode.
Each product carries `isOnSpecial` and the store's own `promoLabel` badge (e.g.
`Deal`, `Clearance`, `Low Price`).

Officeworks runs an **every-day-low-price** model and generally does **not**
publish a strike-through "was" price. When a product is genuinely reduced below
its everyday price, `wasPrice`, `savingsAmount` and `savingsPercent` are
populated; otherwise they stay `null` (they are never fabricated). The current
`price` is always present.

### Ratings & reviews

Every product card already carries the aggregate `rating` (0-5) and
`reviewCount`. Keep **Fetch full product detail + reviews** on (the default) to
also attach each product's full detail, the star-rating distribution and its
customer reviews. Use **Max reviews per product** to cap how many are collected
per product (0 = all available).

For example, a popular product might carry `reviewCount: 128` with a `rating` of
4.6 and a `ratingDistribution` of `{ "5": 96, "4": 20, "3": 6, "2": 3, "1": 3 }`,
each review including rating, title, body, author, date and a helpful count.
Products with **no reviews** simply leave `rating`, `reviewCount`,
`ratingDistribution` and `reviews` absent (these fields are never faked);
`reviewsCollected` reads `0`. Some reviews are ratings-only, in which case only
the rating and date are present. Officeworks does not publish a verified-purchase
flag, so `verifiedPurchase` is omitted; where a reviewer indicated where they
bought the item, that appears as `purchaseLocation`.

Turn detail enrichment **off** for a faster, lower-cost run that returns the
listing card fields only (name, brand, price, images, category, aggregate rating
and review count) with no reviews.

### Output limits

- **Max products** - overall cap across the run (0 = unlimited)
- **Max pages per search** - safety cap on result pages per keyword / URL

### Send results into your apps (MCP connectors)

Optionally pipe results into the apps you already use via Model Context Protocol
(MCP) connectors - Notion, Linear, Airtable or Apify. Authorize a connector under
**Apify → Settings → API & Integrations**, then select it in the input. Notion
gets a rich page-per-item export; other connectors get a best-effort write or
digest. This never changes the dataset output.

### Plan Requirement

Runs on any Apify plan. Using Apify Proxy is recommended for reliable results; on
the free plan, coverage may be limited and some runs may return fewer results.

### Example input

```json
{
  "mode": "search",
  "queries": [],
  "specialsCategory": "clearance",
  "sortBy": "priceAsc",
  "detailEnrichment": true,
  "maxReviewsPerProduct": 10,
  "maxItems": 50,
  "proxy": { "useApifyProxy": true }
}
```

### Example output

```json
{
  "sku": "EXAMPLE123",
  "name": "Example 14 inch Notebook 16GB 512GB",
  "title": "Example Brand Example 14 inch Notebook 16GB 512GB",
  "brand": "Example Brand",
  "url": "https://www.officeworks.com.au/shop/officeworks/p/example-notebook-example123",
  "price": 897.0,
  "edlpPrice": 897.0,
  "wasPrice": null,
  "savingsAmount": null,
  "savingsPercent": null,
  "isOnSpecial": true,
  "promoLabel": "Clearance",
  "isNew": false,
  "gstRate": 10.0,
  "currency": "AUD",
  "gtin": "9300000000000",
  "availableStates": ["NSW", "VIC", "QLD", "WA", "SA"],
  "availableOnline": true,
  "isClearance": true,
  "category": "Laptops",
  "categories": ["Technology", "Computers", "Laptops"],
  "categoryHierarchy": [["Technology", "Computers", "Laptops"]],
  "variantAxes": { "Colour": ["Silver", "Space Grey"] },
  "variantCount": 2,
  "variants": [
    {
      "sku": "EXAMPLE123",
      "url": "https://www.officeworks.com.au/shop/officeworks/p/example-notebook-example123",
      "attributes": { "Colour": "Silver" },
      "imageUrl": "https://www.officeworks.com.au/images/example-thumb.jpg"
    }
  ],
  "shortDescription": "A lightweight everyday notebook.",
  "features": ["14 inch display", "16GB memory", "512GB storage"],
  "specifications": { "Brand": "Example Brand", "Storage": "512GB" },
  "imageUrl": "https://www.officeworks.com.au/images/example.jpg",
  "rating": 4.6,
  "reviewCount": 128,
  "ratingDistribution": { "5": 96, "4": 20, "3": 6, "2": 3, "1": 3 },
  "recommendedCount": 110,
  "reviews": [
    {
      "reviewId": "1000000001",
      "rating": 5,
      "title": "Great value",
      "body": "Fast and light, exactly what I needed.",
      "author": "SampleReviewer",
      "date": "2026-06-01T10:00:00.000+00:00",
      "helpfulCount": 3
    }
  ],
  "reviewsCollected": 1
}
```

# Actor input Schema

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

Choose 'search' to use keywords and filters, or 'url' to scrape specific product, search or category URLs you paste below.

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

One or more keywords to search, for example 'laptop' or 'printer ink'. Each keyword is searched separately.

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

Optional. Scrape one of Officeworks' promotional collections instead of (or alongside) your keywords: Deals (curated featured offers) or Clearance (reduced-to-clear stock). Brand, price, rating filters and sort still apply. Leave empty to skip. Note: Officeworks uses an every-day-low-price model, so most products do not carry a strike-through 'was' price.

## `brand` (type: `string`):

Optional. Keep only products whose brand matches this value, for example 'HP' or 'Keji'.

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

Ordering applied to the results by the store's product-search service.

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

Optional. Only keep products priced at or above this amount (AUD).

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

Optional. Only keep products priced at or below this amount (AUD).

## `minRating` (type: `integer`):

Optional. Only keep products with an average customer rating at or above this value (1 to 5).

## `includeOutOfStock` (type: `boolean`):

Include products that are not currently available in-store or online. On by default; turn off to keep only available products.

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

Product, search or category URLs to scrape, for example https://www.officeworks.com.au/shop/officeworks/p/some-product-sku, https://www.officeworks.com.au/shop/officeworks/search?q=laptop or https://www.officeworks.com.au/shop/officeworks/c/office-supplies/pens. Multiple URLs supported.

## `detailEnrichment` (type: `boolean`):

For each product, also fetch the product page for the full description, feature bullets, specifications, identifiers and image gallery, plus the star-rating distribution and customer reviews. Adds one request per product. Turn off for a faster, lower-cost run that returns the listing card fields only (name, price, brand, aggregate rating and review count) with no reviews.

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

Cap on reviews collected per product when detail enrichment is on. Use 0 for all available reviews. Products with no reviews leave the review fields absent.

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

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

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

Optional safety cap on result pages walked per keyword / URL. Use 0 to walk every page (the run still stops automatically once Max products is reached, or once a page repeats or the store's own result total is reached).

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

Optional. 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.

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

Apify Proxy is recommended for reliable results. On the free plan, coverage may be limited and some runs may return no results.

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

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

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

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

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

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

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "laptop"
  ],
  "sortBy": "relevance",
  "includeOutOfStock": true,
  "urls": [
    "https://www.officeworks.com.au/shop/officeworks/c/office-supplies/pens"
  ],
  "detailEnrichment": true,
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "maxPages": 0,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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": [
        "laptop"
    ],
    "urls": [
        "https://www.officeworks.com.au/shop/officeworks/c/office-supplies/pens"
    ],
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/officeworks-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": ["laptop"],
    "urls": ["https://www.officeworks.com.au/shop/officeworks/c/office-supplies/pens"],
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/officeworks-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "laptop"
  ],
  "urls": [
    "https://www.officeworks.com.au/shop/officeworks/c/office-supplies/pens"
  ],
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/officeworks-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=abotapi/officeworks-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/d3t3Sp02RUsHSWrZ7/builds/kjIeB8wdgmkJgyFa2/openapi.json
