# Woolworths Scraper: Products, Prices, Specials & Nutrition (`hyperbach/woolworths-scraper`) Actor

Scrape Woolworths Australia products by search words, category, specials or product URL: stockcode, barcode, name, brand, size, price, was-price, specials, cup price, availability, images, category, ingredients, allergens and nutrition. Several searches per run, a max per search. No login.

- **URL**: https://apify.com/hyperbach/woolworths-scraper.md
- **Developed by:** [Hyperbach](https://apify.com/hyperbach) (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 $0.30 / 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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Woolworths Scraper: Products, Prices, Specials & Nutrition

**Woolworths Australia products, logged out: search words, Woolworths search, category or specials URLs, a specials list by kind, or product URLs in, one row per product out — the stockcode, barcode and URL, name, brand and package size, the price with the was-price and the saving, the half-price special and the promotion text, the cup (unit) price, availability, the image URLs, the department, category and subcategory, and the ingredients, allergens and nutrition panel — several searches in one run, a max per search.** One free `query` row per input carries a completeness verdict: COMPLETE (every product of Woolworths' count), CAPPED (your limit), TRUNCATED (Woolworths' own depth limit, with its count) or PARTIAL. No login, no API key, no browser, proxies handled for you.

### Why this Woolworths scraper

- **Searches, categories, specials and products in one run.** Give search words (`milk`), search URLs from your browser, category URLs (`/shop/browse/dairy-eggs-fridge/milk`), a specials list by kind (half price, lower shelf price, everyday low price, seasonal, buy more save more, online only), or product URLs and stockcodes. Each list gets its own cap (`maxItemsPerQuery`), and the run's cap sits on top (`maxItems`).
- **Prices and specials as Woolworths shows them.** The shelf price, the was-price and the saving when the product is on special, the half-price flag, the promotion line and the multi-buy offer (`2 for $17.00`), the tile's labels (`Half Price`, `Lower Price Always`), and the cup price with its measure (`$1.65 / 1L`).
- **The product's details in the same row.** The barcode, the ingredients, the allergens and may-contain lists, the dietary claims, the Health Star Rating and the whole nutrition panel come with every product of a list: no second request per product, so a 1,000-product category costs the same per row as a search.
- **Every product of a list, checked.** Woolworths' own order, 36 products a page, until every product of Woolworths' count is met: the free `query` row says COMPLETE with the count. A search serves at most 10,000 products (measured 2026-10-23); a run that reaches that end says TRUNCATED with Woolworths' count. A product a later page or another search repeats is delivered and charged once; sponsored products are kept and flagged.
- **Honest runs.** A stockcode Woolworths does not know is a free `not_found` row, checked twice; a search with no match a free `no_results` row; a URL that is not Woolworths a free `invalid` row. Every input gets a row.

### Who it's for

- **Grocery price analysts** — the prices, was-prices and cup prices of a category or a search's products, read again every week to follow specials and price moves.
- **Brands and suppliers** — where their products and their competitors' sit in Woolworths' search for their words, with the special, the saving and the sponsored placements.
- **Nutrition and food apps** — barcodes with ingredients, allergens, dietary claims, Health Star Ratings and nutrition panels for whole categories.

### Quick start

**The first 100 products of a search**

```json
{
  "searchTerms": [
    "milk"
  ],
  "maxItemsPerQuery": 100
}
```

**This week's half-price specials**

```json
{
  "specials": "half-price",
  "maxItemsPerQuery": 500
}
```

**A whole category and two products by URL and by stockcode**

```json
{
  "startUrls": [
    "https://www.woolworths.com.au/shop/browse/dairy-eggs-fridge/milk",
    "https://www.woolworths.com.au/shop/productdetails/888140/woolworths-full-cream-milk",
    "6081704"
  ],
  "maxItemsPerQuery": 0
}
```

### Output

One row per product (and one free query row per input):

| field | meaning |
|---|---|
| `row_type` | `product` (one product, charged) or `query` (the input's row with the walk's verdict; free). |
| `input_index` | The 1-based position of the input this row answers: `startUrls` first, then `searchTerms`, then `specials`. |
| `input_value` | The input as you gave it (the URL, the search words or the specials list). |
| `input_kind` | Which input it came from: `url` (`startUrls`), `query` (`searchTerms`) or `specials`. |
| `search_url` | The list (or the product) on woolworths.com.au, as a URL you can open. |
| `status` | A query row: `ok`, `no_results`, `not_found`, `invalid`, `duplicate`, `failed` or `not_read` (see the FAQ). A product row: `ok`. |
| `status_detail` | Why a query row is not `ok`, in a sentence. |
| `scraped_at` | When the row was read (UTC). |
| `position` | The product's place among this input's delivered products (1 = first); 1 for a product URL. |
| `page` | The list page the product was on, 36 products a page (empty for a product URL). |
| `stockcode` | Woolworths' stockcode (the number in the product URL). |
| `barcode` | The product's barcode (EAN/GTIN), as Woolworths gives it. |
| `url` | The product's page on woolworths.com.au. |
| `name` | The product's name (`Woolworths Full Cream Milk`). |
| `display_name` | The name with the size, as the shelf tile shows it (`Woolworths Full Cream Milk 3L`). |
| `brand` | The brand. |
| `package_size` | The package size as Woolworths writes it (`3L`, `900g`, `10 Pack`). |
| `description` | Woolworths' product description, without markup, when it gives one. |
| `price` | The current shelf price, in `currency` (empty when Woolworths shows no price: an unavailable product). |
| `currency` | The price's currency (`AUD`). |
| `was_price` | The earlier price Woolworths strikes through when the product is on special (empty when it is not). |
| `save_amount` | The saving against the was-price, in dollars. |
| `on_special` | True when the product is on special. |
| `half_price` | True when the special is half price. |
| `promotion_text` | The promotion line of the tile (`2 for $17.00 - $8.97/1L`, `Buy 1 get a bonus Container credit^`). |
| `multibuy_quantity` | A multi-buy offer: how many to buy for `multibuy_price`. |
| `multibuy_price` | A multi-buy offer: the price of `multibuy_quantity` products, in AUD. |
| `tags` | The tile's labels as Woolworths shows them (`Half Price`, `Lower Price Always`, `Australian Milk`). |
| `cup_price` | The cup (unit) price: the price per `cup_measure`, in AUD. |
| `cup_measure` | The measure the cup price is for (`1L`, `100G`, `1EA`). |
| `cup_price_text` | The cup price as the shelf label writes it (`$1.65 / 1L`). |
| `unit` | How the product is sold: `Each`, or `KG` for products priced by weight. |
| `in_stock` | True when Woolworths shows the product in stock. |
| `available` | True when Woolworths shows the product as available to buy. |
| `purchasable` | True when the product can be added to a trolley. |
| `supply_limit` | The most of this product one order may hold. |
| `online_only` | True when the product (or its special) is online only. |
| `is_new` | True when Woolworths marks the product as new. |
| `marketplace` | True for an Everyday Market product (sold by a third-party seller through Woolworths). |
| `image_url` | The product's main image (large). |
| `image_urls` | Every image URL the list tile names, the main image first. |
| `department` | The department (`Dairy, Eggs & Fridge`). |
| `category` | The category inside the department (`Milk`). |
| `subcategory` | The subcategory inside the category (`Full Cream Milk`). |
| `category_path` | Department > category > subcategory. |
| `ingredients` | The ingredients as Woolworths lists them. |
| `allergens` | The allergens the product contains (`Milk`, `Soy`). |
| `may_contain` | The allergens that may be present. |
| `dietary` | The lifestyle and dietary claims (`Gluten Free`, `Vegetarian`). |
| `health_star_rating` | The Health Star Rating (0.5 to 5), when the product carries one. |
| `nutrition` | The nutrition panel: each line's name and value (`Energy kJ per 100g`: `264.0kJ`, `Serving Size`: `250.0 ML`). |
| `rating` | The average customer rating, when the product has ratings. |
| `reviews_count` | The number of customer reviews. |
| `sponsored` | True when the product was a sponsored placement in the list (false for a product URL). |
| `products_count` | A query row: Woolworths' own count of products for the list (sponsored ones included). |
| `products_delivered` | A query row: the product rows this input delivered. |
| `pages_read` | A query row: the list pages read. |
| `repeats_skipped` | A query row: products skipped because an earlier page or another input of the run already delivered them. |
| `verdict` | A query row: `COMPLETE` (every product of Woolworths' count, or Woolworths' own end of the list), `CAPPED` (your limit), `TRUNCATED` (the list ended below Woolworths' count: a search serves at most 10,000 products) or `PARTIAL` (a refusal or the time limit stopped it). |
| `verdict_detail` | A query row: the verdict in a sentence, with the counts. |

Example record:

```json
{
  "row_type": "product",
  "input_index": 8,
  "input_value": "half-price",
  "input_kind": "specials",
  "search_url": "https://www.woolworths.com.au/shop/browse/specials/half-price",
  "status": "ok",
  "status_detail": null,
  "scraped_at": "2026-10-23T05:26:34Z",
  "position": 6,
  "page": 1,
  "stockcode": "679122",
  "barcode": "9300675084581",
  "url": "https://www.woolworths.com.au/shop/productdetails/679122/coca-cola-zero-sugar-soft-drink-mini-bottles",
  "name": "Coca-Cola Zero Sugar Soft Drink Mini Bottles",
  "display_name": "Coca-Cola Zero Sugar Soft Drink Mini Bottles 300mL x 12 pack",
  "brand": "Coca-Cola",
  "package_size": "300mL x 12 pack",
  "description": "Coca-Cola Zero Sugar Soft Drink Multipack Bottles 12 x 300mL Coca-Cola Zero Sugar delivers the classic Coke taste with no sugar, offering a lighter option without compromising on f …(truncated for display)",
  "price": 12.0,
  "currency": "AUD",
  "was_price": 24.0,
  "save_amount": 12.0,
  "on_special": true,
  "half_price": true,
  "promotion_text": null,
  "multibuy_quantity": null,
  "multibuy_price": null,
  "tags": [
    "Half Price"
  ],
  "cup_price": 3.33,
  "cup_measure": "1L",
  "cup_price_text": "$3.33 / 1L",
  "unit": "Each",
  "in_stock": true,
  "available": true,
  "purchasable": true,
  "supply_limit": 12,
  "online_only": false,
  "is_new": false,
  "marketplace": false,
  "image_url": "https://cdn1.woolworths.media/content/wowproductimages/large/679122.jpg",
  "image_urls": [
    "https://cdn1.woolworths.media/content/wowproductimages/large/679122.jpg"
  ],
  "department": "Lunch Box",
  "category": "Healthier Lunch Box",
  "subcategory": "Soft Drink Bottles",
  "category_path": "Lunch Box > Healthier Lunch Box > Soft Drink Bottles",
  "ingredients": "Carbonated water, colour (150d), food acids (338, 331), sweeteners (951, 950), flavour, caffeine.",
  "allergens": null,
  "may_contain": null,
  "dietary": [
    "Gluten Free",
    "Low Fat",
    "Low Salt",
    "Low Sugar",
    "Vegan",
    "Vegetarian"
  ],
  "health_star_rating": 3.5,
  "nutrition": {
    "Carbohydrate per 100g": "0.03g",
    "Carbohydrate per Serve": "0.1g",
    "Dietary Fibre per 100g": "0.0g",
    "Dietary Fibre per Serve": "0.0g",
    "Energy kJ per 100g": "1.2kJ",
    "Energy kJ per Serve": "3.6kJ",
    "Fat Saturated per 100g": "0.0g",
    "Fat Saturated per Serve": "0.0g",
    "Fat Total per 100g": "0.0g",
    "Fat Total per Serve": "0.0g",
    "Protein per 100g": "0.02g",
    "Protein per Serve": "0.07g",
    "Serving Size": "300.0 ML",
    "Servings Per Pack": "12.0",
    "Sodium per 100g": "4.1mg",
    "Sodium per Serve": "12.3mg",
    "Sugars per 100g": "0.0g",
    "Sugars per Serve": "0.0g"
  },
  "rating": null,
  "reviews_count": 0,
  "sponsored": false,
  "products_count": null,
  "products_delivered": null,
  "pages_read": null,
  "repeats_skipped": null,
  "verdict": null,
  "verdict_detail": null
}
```

### Pricing

**Pay for the products a run delivers**, plus one run start; no platform usage is billed to you. The product price falls with your Apify plan.

| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
| Product (`product`) | per 1,000 | $0.60 | $0.50 | $0.40 | $0.30 |
| Run start (`start`) | per run | $0.008 | $0.008 | $0.008 | $0.008 |

A product is **$0.60 per 1,000** on the Free plan ($0.0006 a product). Each run that delivers a charged product also pays the **run start, $0.008 once**; a run that delivers no charged product pays nothing at all. So one search of 100 products costs $0.068 on the Free plan, and several searches in one run share one start. The free `query` row of every input, a value that is not a Woolworths URL (`invalid`), a stockcode or category Woolworths does not know (`not_found`), a search with no match (`no_results`), a repeated input (`duplicate`), an input left at the cap or the time limit (`not_read`) and a refusal the run could not pass (`failed`) are never charged. A product is charged once a run, also when several searches list it. A run that stops early (a timeout, an abort) is charged for the products it delivered. `maxItems` counts the charged rows; before the first request the log names the price of each row at your plan and the most the run can cost. Enterprise plans have their own rates: the Actor's Pricing tab shows the price for your plan.

### Usage patterns

- **Searches, categories, specials and products** — `searchTerms` takes words, one search a line. `startUrls` takes search URLs as your browser shows them (their search words are read; the list comes in Woolworths' own order), category URLs (`/shop/browse/<department>/<category>/<subcategory>`), specials lists (`/shop/browse/specials/<list>`) and product URLs (`/shop/productdetails/<stockcode>/<name>`) or bare stockcodes. `specials` adds one specials list. woolworths.com.au only.
- **What a row is** — `row_type` = `product`: one product, in Woolworths' order (`position`, and the `page` it was on). `row_type` = `query`: the free row of one input value — `products_count` (Woolworths' own count), `products_delivered`, `pages_read`, `repeats_skipped`, the `verdict` with its `verdict_detail`, and the `status` with its reason.
- **How far a list goes** — `maxItemsPerQuery` (default 100; 0 = every product the list serves) stops each list after that many new products. A category or a specials list is read to its end; a search serves at most 10,000 products, and a run that reaches that end says TRUNCATED with Woolworths' count (a category or other words read a narrower list). `maxItems` caps the charged rows of the whole run.

### Input configuration

| field | type | default | what it does |
|---|---|---|---|
| `searchTerms` | `array` |  | Words to search on woolworths.com.au, one search a line (`milk`, `tim tam`), as you would type them in Woolworths' search box. Each line is one list, read page after page. Words Woolworths matches with nothing give a free row with no product. |
| `startUrls` | `array` |  | Woolworths pages to read, one a line: a search URL (`https://www.woolworths.com.au/shop/search/products?searchTerm=milk`: its search words are read, in Woolworths' own order), a category URL (`https://www.woolworths.com.au/shop/browse/dairy-eggs-fridge/milk`), a specials list (`https://www.woolworths.com.au/shop/browse/specials/half-price`), or a product URL (`https://www.woolworths.com.au/shop/productdetails/888140/woolworths-full-cream-milk`, or the stockcode alone). A URL that is not a woolworths.com.au list or product gets a free `invalid` row; a URL given twice a free `duplicate` row. |
| `specials` | `none` / `half-price` / `lower-shelf-price` / `everyday-low-price` / `seasonal-price` / `buy-more-save-more` / `online-only-specials` | `"none"` | Read one of Woolworths' specials lists too: half price, lower shelf price, everyday low price, seasonal price, buy more save more, or the online-only specials. None = no specials list (search words and URLs only). |
| `maxItemsPerQuery` | `integer` | `100` | Stop each search, category or specials list after this many new products. 0 = every product the list serves: Woolworths serves at most 10,000 products of a search, a category or specials list to its end. Product URLs are not counted here. |
| `maxItems` | `integer` | `0` | Stop the whole run after this many product rows (the charged rows). 0 = no run cap; each list still stops at its own limit above. |

### Errors

**A run does not fail because of your input.** When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends **Succeeded**, charges nothing, and says what to change:

- the status message starts with `INPUT REJECTED`;
- the dataset holds one row, `{"error": true, "code": "…", "message": "…"}`, and no results;
- the key-value store record `ERROR` holds the same object.

From code, check `error` on the first row before reading results.

A URL that is not a Woolworths search, category, specials or product URL (an account page, a recipe, another shop) is not an error: it gets one free `query` row with `status` invalid that says why, and the run goes on with the others. A run that ends **Failed** is a fault on our side, never your input; it charges nothing, and we are alerted.

### FAQ

**Which status is which?**

A query row's `status` is `ok` (products served), `no_results` (Woolworths lists no product for it; read on two connections), `not_found` (Woolworths has no product with that stockcode, checked on two connections, or no category at that URL), `invalid` (an empty value, or a URL that is not a Woolworths search, category, specials or product URL), `duplicate` (the same list or product again in the input: read once; or a product another input already delivered), `failed` (Woolworths refused every try; free) or `not_read` (left at `maxItems`, the charge limit or the run's time limit). A product row's `status` is `ok`.

**Are the prices for my store?**

No. The prices and availability are the ones woolworths.com.au shows a visitor who has not chosen a store or a delivery address. Prices per store or postcode are not read.

**Does it give the barcode, nutrition and ingredients?**

Yes, when Woolworths gives them: the barcode, ingredients, allergens, may-contain, dietary claims, Health Star Rating and the nutrition panel come with every product of a list (measured on 1,392 products: barcode on 1,384, ingredients on 1,147, nutrition on 1,038). Non-food products have none of the food fields.

**Why are some products marked sponsored?**

Woolworths places sponsored products in its category and specials lists; they count in Woolworths' count of the list and keep their place, with `sponsored` true. Filter on it if you want the organic results only.

**Does it need a Woolworths account or API key?**

No. Everything is read from Woolworths' public pages, logged out.

### Integration

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/woolworths-scraper').call({"searchTerms": ["milk"], "maxItemsPerQuery": 100});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/woolworths-scraper').call(run_input={'searchTerms': ['milk'], 'maxItemsPerQuery': 100})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

#### CLI

```bash
apify call hyperbach/woolworths-scraper --input '{"searchTerms": ["milk"], "maxItemsPerQuery": 100}'
```

#### REST

```bash
curl -X POST "https://api.apify.com/v2/acts/hyperbach~woolworths-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' -d '{"searchTerms": ["milk"], "maxItemsPerQuery": 100}'
```

### Support

apify@hyperbach.com

*This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.*

# Actor input Schema

## `searchTerms` (type: `array`):

Words to search on woolworths.com.au, one search a line (`milk`, `tim tam`), as you would type them in Woolworths' search box. Each line is one list, read page after page. Words Woolworths matches with nothing give a free row with no product.

## `startUrls` (type: `array`):

Woolworths pages to read, one a line: a search URL (`https://www.woolworths.com.au/shop/search/products?searchTerm=milk`: its search words are read, in Woolworths' own order), a category URL (`https://www.woolworths.com.au/shop/browse/dairy-eggs-fridge/milk`), a specials list (`https://www.woolworths.com.au/shop/browse/specials/half-price`), or a product URL (`https://www.woolworths.com.au/shop/productdetails/888140/woolworths-full-cream-milk`, or the stockcode alone). A URL that is not a woolworths.com.au list or product gets a free `invalid` row; a URL given twice a free `duplicate` row.

## `specials` (type: `string`):

Read one of Woolworths' specials lists too: half price, lower shelf price, everyday low price, seasonal price, buy more save more, or the online-only specials. None = no specials list (search words and URLs only).

## `maxItemsPerQuery` (type: `integer`):

Stop each search, category or specials list after this many new products. 0 = every product the list serves: Woolworths serves at most 10,000 products of a search, a category or specials list to its end. Product URLs are not counted here.

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

Stop the whole run after this many product rows (the charged rows). 0 = no run cap; each list still stops at its own limit above.

## Actor input object example

```json
{
  "searchTerms": [
    "milk"
  ],
  "specials": "none",
  "maxItemsPerQuery": 10,
  "maxItems": 50
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped records in the default dataset. One row per product (and one free query row per input):

## `runSummary` (type: `string`):

How the run went: product rows charged, free rows, inputs by status, the walk per list (products delivered, pages read, repeated products skipped, Woolworths' count, the verdict), the source counters (calls, served, refused, exits, rotations, bytes) and the memory watch.

# 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 = {
    "searchTerms": [
        "milk"
    ],
    "maxItemsPerQuery": 10,
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("hyperbach/woolworths-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 = {
    "searchTerms": ["milk"],
    "maxItemsPerQuery": 10,
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("hyperbach/woolworths-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 '{
  "searchTerms": [
    "milk"
  ],
  "maxItemsPerQuery": 10,
  "maxItems": 50
}' |
apify call hyperbach/woolworths-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hyperbach/woolworths-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/6MEPZnN3sYutfzPae/builds/F9JwNrPOxEReBBInA/openapi.json
