# Watsons Health & Beauty Scraper (`crawlerbros/watsons-scraper`) Actor

Scrape Watsons Asia health and beauty products across Singapore, Malaysia, and Hong Kong. Search by keyword, browse by category, fetch by product code, or filter by brand. Returns prices, ratings, ingredients, promotional tags, and stock status

- **URL**: https://apify.com/crawlerbros/watsons-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 4 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Watsons Health & Beauty Scraper

Scrape **Watsons Asia** health and beauty products across Singapore, Malaysia, and Hong Kong. Search by keyword, browse by category, or look up specific products to extract prices, ratings, ingredients, and promotional tags. Uses the Watsons public API — no authentication or proxy required.

### What this actor does

- **Four modes:** `search` (keyword), `byCategory` (category slug), `byProductCodes` (exact lookup), `byUrl` (from a product or search URL)
- **Multi-market:** Singapore (SGD), Malaysia (MYR), Hong Kong (HKD)
- **Full pricing detail:** current price, original price, discount percentage, and currency
- **Rich metadata:** brand, ingredients, size, category hierarchy, halal / clean beauty / organic flags
- **Promotional data:** active promotion tags and stock status
- **Empty fields are omitted** — every record contains only fields that have real values

### Output per product

- `productCode` — Watsons internal product code (e.g. `BP_88725`)
- `name` — full product name
- `url` — direct link to the product page
- `price` — current selling price (numeric)
- `originalPrice` — original price before discount (numeric, when discounted)
- `discountPercent` — percentage saved (numeric, when discounted)
- `currency` — ISO currency code (`SGD`, `MYR`, `HKD`)
- `rating` — average star rating (0–5 scale)
- `reviewCount` — number of customer reviews
- `brand` — brand name
- `category` — top-level category (e.g. `Skincare`)
- `subCategory` — second-level category (e.g. `Serums & Essences`)
- `imageUrl` — primary product image URL
- `size` — content size / quantity (e.g. `40ml`, `60 tabs`)
- `ingredients` — full ingredient list text (when available)
- `isCleanBeauty` — true if labeled as clean beauty product
- `isHalal` — true if halal-certified
- `isOrganic` — true if organic
- `stockStatus` — `inStock`, `outOfStock`, or `lowStock`
- `promotionTags` — active promotional labels (array of strings)
- `market` — market code: `sg`, `my`, or `hk`
- `scrapedAt` — ISO 8601 timestamp of the scrape

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byCategory` / `byProductCodes` / `byUrl` |
| `market` | string | `sg` | `sg` (Singapore), `my` (Malaysia), `hk` (Hong Kong) |
| `searchQuery` | string | `vitamin c` | Keyword to search for (mode=search) |
| `categorySlug` | string | – | Category URL slug, e.g. `skincare` (mode=byCategory) |
| `productCodes` | array | – | Watsons product codes, e.g. `["BP_88725"]` (mode=byProductCodes) |
| `startUrls` | array | – | Product or search page URLs (mode=byUrl) |
| `sortBy` | string | `mostRelevant` | `mostRelevant`, `bestSeller`, `topRated`, `new`, `price-asc`, `price-desc` |
| `minRating` | number | – | Only emit products with rating ≥ this value (0–5) |
| `maxItems` | int | `50` | Hard cap on emitted records (1–1000) |

#### Example: search for moisturizers in Singapore

```json
{
  "mode": "search",
  "market": "sg",
  "searchQuery": "moisturizer",
  "sortBy": "bestSeller",
  "maxItems": 50
}
````

#### Example: browse skincare category in Malaysia

```json
{
  "mode": "byCategory",
  "market": "my",
  "categorySlug": "skincare",
  "sortBy": "topRated",
  "maxItems": 100
}
```

#### Example: fetch specific products by code

```json
{
  "mode": "byProductCodes",
  "market": "sg",
  "productCodes": ["BP_88725", "BP_61864"],
  "maxItems": 10
}
```

#### Example: scrape from a product URL

```json
{
  "mode": "byUrl",
  "startUrls": [
    "https://www.watsons.com.sg/vitamin-c-1000mg-sustained-release-caplets-90s/p/BP_69219"
  ],
  "maxItems": 10
}
```

### Use cases

- **Retail price monitoring** — track Watsons product prices and promotions across markets
- **Beauty brand analytics** — analyze brand presence, rating distribution, and category coverage
- **Health product research** — gather ingredient lists for regulatory or formulation analysis
- **Competitor intelligence** — compare Watsons pricing with other health & beauty retailers
- **Market comparison** — identify price differences between SG, MY, and HK for arbitrage insight
- **Promotion tracking** — monitor active deals and discount percentages over time

### FAQ

**What is the data source?**
This actor uses the public Watsons SAP Commerce Cloud API, which powers the official Watsons websites in Singapore, Malaysia, and Hong Kong. No authentication is required.

**Which markets are covered?**
Singapore (`watsons.com.sg`), Malaysia (`watsons.com.my`), and Hong Kong (`watsons.com.hk`). Each market has independent product listings, prices, and inventory.

**How fresh is the data?**
The API returns live data — prices and stock status reflect what you see on the Watsons website at the time of scraping.

**Why are some fields missing from some products?**
Watsons product records vary in completeness. Fields like `ingredients`, `isHalal`, and `isCleanBeauty` are only populated when Watsons has that data for a specific product. The actor omits empty fields rather than returning null values.

**How many products can I scrape?**
Set `maxItems` up to 1000 per run. Watsons search returns up to 20 products per page and the actor paginates automatically.

**What category slugs can I use?**
Use the URL path segment after `/c/` on any Watsons category page. Examples: `skincare`, `supplements`, `hair-care`, `baby-care`, `personal-hygiene`. Browse `watsons.com.sg/c/skincare` to discover slugs.

**Is this actor affiliated with Watsons?**
No. This is an independent third-party actor that uses publicly accessible Watsons API endpoints. It is not affiliated with or endorsed by A.S. Watson Group.

**Does the actor handle out-of-stock products?**
Yes. The `stockStatus` field reports `inStock`, `outOfStock`, or `lowStock`. There is no option to exclude out-of-stock items at input — filter in your downstream pipeline using this field.

# Actor input Schema

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

What to fetch from Watsons.

## `market` (type: `string`):

Watsons regional website to scrape.

## `searchQuery` (type: `string`):

Product keyword to search for (mode=search).

## `categorySlug` (type: `string`):

Watsons category code (numeric), e.g. `2002000` (Skincare), `2100000` (Health), `2110000` (Vitamins & Supplements), `2003000` (Makeup). From the `category:XXXXX` filter in Watsons search URLs.

## `productCodes` (type: `array`):

Watsons product codes, e.g. `BP_88725`. Found in the URL of each product page.

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

Watsons product or search page URLs. E.g. https://www.watsons.com.sg/search?text=serum

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

How to sort search and category results.

## `minRating` (type: `number`):

Only emit products with averageRating >= this value.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "market": "sg",
  "searchQuery": "vitamin c",
  "productCodes": [],
  "startUrls": [],
  "sortBy": "mostRelevant",
  "maxItems": 50
}
```

# Actor output Schema

## `products` (type: `string`):

Dataset containing all scraped Watsons product records.

# 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",
    "market": "sg",
    "searchQuery": "vitamin c",
    "productCodes": [],
    "startUrls": [],
    "sortBy": "mostRelevant",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/watsons-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",
    "market": "sg",
    "searchQuery": "vitamin c",
    "productCodes": [],
    "startUrls": [],
    "sortBy": "mostRelevant",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/watsons-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",
  "market": "sg",
  "searchQuery": "vitamin c",
  "productCodes": [],
  "startUrls": [],
  "sortBy": "mostRelevant",
  "maxItems": 50
}' |
apify call crawlerbros/watsons-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Watsons Health & Beauty Scraper",
        "description": "Scrape Watsons Asia health and beauty products across Singapore, Malaysia, and Hong Kong. Search by keyword, browse by category, fetch by product code, or filter by brand. Returns prices, ratings, ingredients, promotional tags, and stock status",
        "version": "1.0",
        "x-build-id": "d4WXwcvWZbEZ0MdNd"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~watsons-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-watsons-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/crawlerbros~watsons-scraper/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-watsons-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/crawlerbros~watsons-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-watsons-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "search",
                            "bycategory",
                            "byproductcodes",
                            "byurl"
                        ],
                        "type": "string",
                        "description": "What to fetch from Watsons.",
                        "default": "search"
                    },
                    "market": {
                        "title": "Market",
                        "enum": [
                            "sg",
                            "my",
                            "hk"
                        ],
                        "type": "string",
                        "description": "Watsons regional website to scrape.",
                        "default": "sg"
                    },
                    "searchQuery": {
                        "title": "Search query",
                        "type": "string",
                        "description": "Product keyword to search for (mode=search).",
                        "default": "vitamin c"
                    },
                    "categorySlug": {
                        "title": "Category code (mode=byCategory)",
                        "type": "string",
                        "description": "Watsons category code (numeric), e.g. `2002000` (Skincare), `2100000` (Health), `2110000` (Vitamins & Supplements), `2003000` (Makeup). From the `category:XXXXX` filter in Watsons search URLs."
                    },
                    "productCodes": {
                        "title": "Product codes (mode=byProductCodes)",
                        "type": "array",
                        "description": "Watsons product codes, e.g. `BP_88725`. Found in the URL of each product page.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "Start URLs (mode=byUrl)",
                        "type": "array",
                        "description": "Watsons product or search page URLs. E.g. https://www.watsons.com.sg/search?text=serum",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "sortBy": {
                        "title": "Sort results by",
                        "enum": [
                            "mostRelevant",
                            "bestSeller",
                            "topRated",
                            "new",
                            "price-asc",
                            "price-desc"
                        ],
                        "type": "string",
                        "description": "How to sort search and category results.",
                        "default": "mostRelevant"
                    },
                    "minRating": {
                        "title": "Minimum rating",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Only emit products with averageRating >= this value."
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Hard cap on emitted records.",
                        "default": 50
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
