# HKTVmall Scraper – HK E-commerce Products, Prices & Stock (`claude_code_reviewer/hktvmall-scraper-en`) Actor

Scrape HKTVmall (Hong Kong's largest online store) product listings without an API or login: SKU, name, brand, price, rating, stock and category. Bulk-paste keywords; export structured JSON/CSV/Excel. Ideal for e-commerce price monitoring and product research.

- **URL**: https://apify.com/claude\_code\_reviewer/hktvmall-scraper-en.md
- **Developed by:** [Chad](https://apify.com/claude_code_reviewer) (community)
- **Categories:** E-commerce, Automation, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 search results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## HKTVmall Scraper | HK Online Shopping Products, Prices, Stock & Ratings (No API, No Login)

One Actor to scrape **HKTVmall** (Hong Kong's largest online shopping platform) keyword-search product listings: price, original price / discount, stock status, rating, review count and category. It reads the **Algolia product search index** behind HKTVmall's storefront search — no login, no API token — and handles hundreds of bulk-pasted keywords at once. Everything goes through public JSON endpoints with no browser: fast and low-cost.

Who it's for: Hong Kong e-commerce price monitoring / comparison, tracking price and stock changes for specific products, market research reports, cross-border e-commerce data analysis, academic datasets, and engineers building side projects.

***

### What you get

Every product returns the fields below (missing values are always `null` — no field is dropped):

| Field                  | Description                                    | Example                                                   |
| ---------------------- | ---------------------------------------------- | --------------------------------------------------------- |
| `product_code`         | HKTVmall product code (SKU, incl. variant)     | `H6771001_S_K01-C014180FC`                                |
| `base_product`         | Base product code (without variant suffix)     | `H6771001K01-C014180FC`                                   |
| `name`                 | Product name (Chinese, falls back to English)  | `[原箱] Espresso Barista 拿坡利鋁製咖啡粉囊 - 100粒裝`     |
| `brand`                | Brand                                          | `KIMBO`                                                    |
| `selling_price`        | Current price (HK$)                            | `450`                                                     |
| `selling_price_range`  | Price range (when variants differ)             | `400-600`                                                 |
| `saved_price`          | Discount amount (HK$, first discount record)   | `49`                                                      |
| `average_rating`       | Average rating (0-5)                           | `5`                                                       |
| `number_of_reviews`    | Review count                                   | `1`                                                       |
| `in_stock`             | Whether it is in stock                         | `true`                                                    |
| `stock`                | Stock status code                              | `inStock`                                                 |
| `loyalty_point`        | Loyalty points earned on purchase              | `0`                                                       |
| `number_of_variants`   | Number of variants (color / spec)              | `1`                                                       |
| `main_category`        | Main category                                  | `超級市場`                                                |
| `sub_category`         | Sub-category (first level)                     | `飲品 即沖飲品`                                           |
| `category_path`        | Full category path (levels joined by `/`)      | `超級市場/飲品 即沖飲品/即飲咖啡 奶茶/咖啡`               |
| `image`                | Main product image URL                         | `https://cdn-media.hktvmall.com/.../xxx_300.jpg`          |
| `product_url`          | Product URL (see "Notes" disclaimer below)     | `https://www.hktvmall.com/hktv/zh/main/.../p/H6771001_...`|
| `keyword`              | The search keyword that matched this row       | `coffee`                                                  |
| `source_mode`          | Source mode, always `search` in v1.0           | `search`                                                  |
| `source_query`         | Query used when scraping (same as `keyword`)   | `coffee`                                                  |
| `scraped_at`           | Scrape timestamp (ISO 8601)                    | `2026-07-04T05:23:28.617Z`                                |

***

### Modes (v1.0 has search only)

| Mode          | What it does                                              | Billing event            | Price  |
| ------------- | -------------------------------------------------------- | ------------------------ | ------ |
| 🔎 **search** | Keyword search → product listings (price, stock, rating, category) | `search-listing` (per row) | $0.002 |

Each Run also charges a one-time `apify-actor-start` fee of **$0.005**. All charges are billed **only after** data is successfully written to the dataset, and the Run log prints `total_items / charged / skipped` for reconciliation.

`detail` (full single-product data) and `category` (category browsing) are planned for v1.1; v1.0 ships only the validated search-listing mode.

***

### Input fields

| Field       | Type     | Required                        | Default    | Description                                                                                                          |
| ----------- | -------- | :-----------------------------: | :--------: | ------------------------------------------------------------------------------------------------------------------ |
| `mode`      | enum     | optional                        | `search`   | v1.0 supports `search` only.                                                                                        |
| `keywords`  | string\[] | one required (or `bulkInput`)   | —          | Search keywords; one concept per keyword works best. Up to **50** per run.                                          |
| `bulkInput` | string   | optional                        | —          | **One per line** (press Enter, no quotes or commas). Merged into `keywords` at runtime. Fastest is to paste a column from Google Sheets / Excel. |
| `maxItems`  | integer  | optional                        | `50`       | Max results per keyword (1-500).                                                                                    |

***

### Examples

**🔎 Basic keyword search**

```json
{
    "mode": "search",
    "keywords": ["coffee"],
    "maxItems": 20
}
```

**📋 Bulk keywords (one per line)**

```json
{
    "mode": "search",
    "bulkInput": "coffee\nshampoo\ndiapers",
    "maxItems": 30
}
```

**🇭🇰 Chinese keywords (Cantonese / Traditional Chinese search)**

```json
{
    "mode": "search",
    "keywords": ["洗髮"],
    "maxItems": 50
}
```

***

### Notes

- **Public data only.** No login and no HKTVmall account required; it never accesses anything behind authentication.
- **No login / no API token.** Fill in the input and run — no keys to configure. The Algolia key used for search is the public search-only key HKTVmall's front-end hands to every browser; it is re-extracted from the search page on every Run (never hard-coded), so key rotation does not break the scraper.
- **`product_url` disclaimer:** the vast majority of matches include HKTVmall's official product-page URL (100% in tested samples), but if a few results lack it the scraper falls back to a "search page keyed by product code" link rather than the product detail page. This affects only link precision, not the correctness of other fields.
- **Polite to the site.** Per-domain concurrency is naturally limited (keywords are crawled sequentially), failures retry with exponential backoff up to 3 times, and it auto-stops after 5 pages with no new data — no idle burn.
- **A product matching multiple keywords is emitted once per keyword** with different `keyword` / `source_query` (billed per query).
- **Per-review content (reviews) is planned for a later version**; this version only exposes the aggregate `average_rating` / `number_of_reviews` in `search` mode.

***

### FAQ

**Q: Why are some fields `null`?**
HKTVmall's own product data isn't complete for every item (some have no discount record or no reviews). Whenever the source value is missing, the scraper returns `null` honestly rather than fabricating data.

**Q: How is billing calculated?**
Each Run charges `apify-actor-start` once ($0.005); each product listing charges `search-listing` ($0.002). Both are billed only after data is written to the dataset, and the Run log prints the actual charged count.

**Q: What if I get no data?**
Check for typos and try a more common keyword (both Chinese and English are supported). The scraper auto-stops after 5 pages with no new data and logs the reason — no idle burn.

**Q: What is `category_path`?**
It's HKTVmall's category hierarchy (main → sub, up to 4 levels), joined by `/`, skipping any missing levels.

**Q: Do you support the product detail page (full single-product data)?**
v1.0 ships search-listing only. If demand is proven, a `detail` mode is planned for v1.1.

***

### Deploy

```bash
apify login              # first time: paste your Apify token (never written to the repo)
apify push               # build and upload to Apify Store
```

After publishing, set the PPE event prices in Apify Console → Monetization:
`apify-actor-start` $0.005, `search-listing` $0.002.

***

### Disclaimer

This scraper only collects **publicly visible** HKTVmall product search data, for research and personal use, not for any unauthorized commercial resale. Please ensure your use complies with HKTVmall's Terms of Service and your local laws. This Actor makes no guarantee about the accuracy, timeliness or completeness of the data — always refer to the live HKTVmall website for current prices and stock.

***

*HKTVmall scraper, Hong Kong e-commerce, HK online shopping, product price monitor, stock tracker, HKTVmall API, Hong Kong retail data, price comparison Hong Kong*

# Actor input Schema

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

v1.0 supports keyword search only.

## `keywords` (type: `array`):

Keywords for search mode, e.g. coffee, shampoo, diapers. One concept per keyword works best.

## `bulkInput` (type: `string`):

**One keyword per line** (press Enter for a new line, no quotes or commas). Treated as keywords and merged into the Keywords field above at runtime. Fastest way is to copy a whole column from Google Sheets / Excel.

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

Max results per keyword. More items = higher cost.

## `proxyConfiguration` (type: `object`):

HKTVmall is friendly to datacenter requests; it works without a proxy by default. Enable only if you hit blocks during heavy scraping.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "coffee"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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",
    "keywords": [
        "coffee"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("claude_code_reviewer/hktvmall-scraper-en").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",
    "keywords": ["coffee"],
}

# Run the Actor and wait for it to finish
run = client.actor("claude_code_reviewer/hktvmall-scraper-en").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 '{
  "mode": "search",
  "keywords": [
    "coffee"
  ]
}' |
apify call claude_code_reviewer/hktvmall-scraper-en --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,claude_code_reviewer/hktvmall-scraper-en"
        }
    }
}

```

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/yq891F4JXN9b7dvrj/builds/C6u119WXDodrm6SO7/openapi.json
