# HardwareZone Scraper – SG Forum Threads, Replies & Monitoring (`claude_code_reviewer/hardwarezone-scraper-en`) Actor

Scrape HardwareZone, Singapore's biggest forum, without an API or login: board thread listings with keyword filtering, main posts and all replies, with author, reply count, view count and timestamps. Schedule daily runs for SG brand monitoring. Export JSON/CSV/Excel for social listening.

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

## Pricing

from $2.00 / 1,000 thread listings

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

## HardwareZone Scraper – Singapore's Biggest Forum (No API, No Login)

Scrape HardwareZone (forums.hardwarezone.com.sg) — Singapore's biggest forum: latest threads per board, and full thread content with all replies — via public HTML endpoints, output as structured data.

### Output Fields

#### Board Thread Listing (ListingRow, content is null)

| Field | Type | Description |
|---------|------|------|
| post\_id | string | Thread ID |
| site | string | Always `hardwarezone` |
| board | string | null | Board ID (the forumId used in the query) |
| title | string | null | Title |
| author | string | null | Thread starter |
| reply\_count | number | null | Reply count (the raw page may show abbreviations like "895" or "29K" — converted to an integer) |
| view\_count | number | null | View count (same handling for "104K" / "4M" abbreviations) |
| created\_at | string | null | Post time (ISO 8601, with a +0800 offset) |
| last\_reply\_at | string | null | Last reply time (ISO 8601, with a +0800 offset) |
| post\_url | string | null | Thread URL |
| content | string | null | Body text (null in listing mode) |
| source\_mode | string | Scrape mode |
| source\_query | string | Query used (board ID) |
| scraped\_at | string | Scrape timestamp (ISO 8601) |

#### Thread Content (ThreadRow, same fields as above, plus content populated)

| Field | Type | Description |
|---------|------|------|
| content | string | null | Full thread body text (HTML tags stripped, whitespace collapsed) |

The thread row's `board` is always `null` (thread mode doesn't take a board ID as input, and board info isn't on the thread page); `reply_count` / `view_count` / `last_reply_at` are always `null` (these fields only exist on the board listing page).

#### Replies (ReplyRow, full thread mode only)

| Field | Type | Description |
|---------|------|------|
| reply\_id | string | Reply ID (the floor post's element ID; falls back to `{threadId}-{floor}` when missing) |
| post\_id | string | Parent thread ID |
| site | string | Always `hardwarezone` |
| floor | number | null | Floor number (1-based, numbered continuously across pages; `null` when the floor can't be read because the post sits behind the age-verification wall — see Notes below) |
| author | string | null | Author |
| content | string | null | Reply content (HTML tags stripped, whitespace collapsed; `null` when hidden behind the age-verification wall) |
| created\_at | string | null | Reply time (ISO 8601, with a +0800 offset; `null` when hidden behind the wall) |
| scraped\_at | string | Scrape timestamp (ISO 8601) |

### Modes

| Mode | Input | Output | Billing |
|-----|------|------|------|
| forum | forumIds (board IDs) | Thread listing | $0.002/row |
| thread | threadIds / threadUrls | Thread content ($0.008/thread) + all replies ($0.003/reply) | by volume |

### Input Fields

| Field | Type | Default | Description |
|-----|------|------|------|
| mode | enum | forum | Mode: forum / thread (required) |
| forumIds | array | `["16"]` | Board IDs, e.g. 16 (Eat-Drink-Man-Woman), 234 (Chill-out/Happenings), 9 (Mobile Communication Technology). Find more boards at forums.hardwarezone.com.sg |
| threadIds | array | — | Thread IDs |
| threadUrls | array | — | Thread URLs; the thread ID is extracted automatically |
| bulkInput | textarea | — | Bulk paste, one item per line, auto-merged into the matching field based on the current mode |
| keywords | array | — | Board thread mode: title keyword filter (leave empty for no filtering) |
| maxItems | integer | 50 | Board thread mode: max items per board; full thread mode: max threads to scrape (replies per thread are not limited by this). Maximum 2000 |
| dateFrom | string | — | Applies to board thread mode, based on thread post time or last reply time (whichever is newer). Format `3d`, `12h`, `2w` (relative) or `MM/DD/YY` (absolute date). When set, paging also stops early (pinned threads are exempt from this filter and early-stop check), keeping scheduled monitoring cheaper |
| proxyConfiguration | proxy | Apify datacenter proxy | On by default; without a proxy you share egress IPs with other runs and get rate-limited by the forum. Turn it off only for local testing or your own proxy |

### Input Examples

#### Board Thread Listing

```json
{
  "mode": "forum",
  "forumIds": ["16", "234"],
  "maxItems": 50
}
```

#### Full Thread and Replies

```json
{
  "mode": "thread",
  "threadUrls": [
    "https://forums.hardwarezone.com.sg/threads/official-blood-donation-thread-give-blood-save-lives.7166857/"
  ]
}
```

### Singapore Social Listening

HardwareZone — especially its casual-chat board EDMW — is Singapore's biggest forum, and the source most often bundled into local social-listening monitoring. Want a fuller picture of Asian forum sentiment? Pair it with the author's other Traditional-Chinese sentiment actors: LIHKG (`lihkg-scraper`, Hong Kong) and PTT (`ptt-scraper`, Taiwan). All three actors share the same output conventions (snake\_case, null for missing values, ISO timestamps), making it easy to merge and analyze together.

### Notes

- Only public content is scraped — no account or token required
- Uses public HTML endpoints (XenForo forum engine) — no browser required, so it's fast and low-cost
- Body text has HTML tags automatically stripped, with whitespace collapsed to single spaces
- Board IDs / thread IDs can be plain numbers (e.g. `forumIds: ["16"]`) — the actor builds the URL automatically; HardwareZone redirects a plain-number URL to the full URL with the board/thread name, so the result is the same
- **Some posts sit behind an age-verification wall**: HardwareZone requires login and age verification to view certain content in full (not limited to adult boards). When scraped without login, these posts only yield `author` (still populated); `content` / `created_at` / `floor` are honestly reported as `null` rather than faked. The thread's first post (the main body) has not been observed to be affected by this restriction
- `reply_count` / `view_count` are often shown as abbreviations like "104K" / "4M" on the raw page (not just for very large numbers — mid-sized ones can be abbreviated too), and are uniformly converted to integers
- Auto-stops after 5 consecutive pages with no new data — no idle burn. When `dateFrom` is set, paging stops immediately once every non-pinned thread on a page is older than `dateFrom` (cheaper still; applies to forum mode only — pinned threads are always kept and are not subject to this filter)
- If HardwareZone (XenForo) redesigns its site or adds anti-scraping measures in the future, this is judged by Apify Cloud smoke test results (go/no-go); if blocked, the fallback is to switch to Apify residential proxy — not over-engineered in advance

### FAQ

**Q: Do I need to log in to view this data?**

A: No. This actor only scrapes public thread listings and posts — nothing that requires login. A small number of posts sit behind an age-verification wall (see Notes above); their content simply isn't retrievable without login in the first place, so it's out of scope.

**Q: Why is `content` / `created_at` / `floor` null for some replies?**

A: These replies are hidden behind HardwareZone's age-verification wall — content and time can't be read without login. We honestly report `null` instead of fabricating data; `author` is still available, and `reply_id` is always populated.

**Q: Can I scrape multiple boards at once?**

A: Yes. Add multiple IDs to `forumIds`, or paste them one per line via `bulkInput`.

**Q: What's the difference between `threadIds` and `threadUrls`?**

A: Same effect — `threadUrls` automatically extracts the numeric ID. Both support the plain-number URL (`/threads/{id}/`) and the full URL (`/threads/{title-slug}.{id}/`).

**Q: Why is the `board` field null in full thread mode?**

A: The thread page itself doesn't carry board info (the board ID only appears in the board listing page's URL), and full thread mode's input is just a `threadId` — there's no way to know which board it belongs to, so we honestly return `null`.

### Disclaimer

This tool is for academic research and lawful business analysis only. Users must comply with HardwareZone's Terms of Service and applicable laws. Do not use this tool to invade others' privacy, spread false information, or engage in any other unlawful activity. The author accepts no responsibility for any misuse.

***

*HardwareZone scraper, Singapore forum, HWZ, EDMW, SG social listening, brand monitoring Singapore, forum sentiment*

# Actor input Schema

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

What do you want to scrape? Pick a mode and fill in the matching fields below.

## `forumIds` (type: `array`):

HardwareZone board IDs (numeric, the `{id}` in the URL forums/{slug}.{id}/), e.g. 16 (Eat-Drink-Man-Woman), 234 (Chill-out/Happenings), 9 (Mobile Communication Technology). Find more boards at forums.hardwarezone.com.sg. Used by board thread mode.

## `threadIds` (type: `array`):

HardwareZone thread IDs (numeric, the `{id}` in the URL threads/{slug}.{id}/), e.g. 7166857. Used by full thread mode.

## `threadUrls` (type: `array`):

Full HardwareZone thread URLs, e.g. https://forums.hardwarezone.com.sg/threads/official-blood-donation-thread-give-blood-save-lives.7166857/. The thread ID is extracted automatically.

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

**One item per line** (press Enter for a new line, no quotes or commas). Treated as board IDs, thread IDs, or thread URLs depending on the current mode, and merged into the matching field above at runtime. Fastest way is to copy a whole column from Google Sheets / Excel.

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

(Optional) Board thread mode: only keep items whose title contains at least one keyword. Leave empty for no filtering.

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

Board thread mode: max items per board. Full thread mode: max threads to scrape (replies per thread are not limited by this). Maximum 2000.

## `dateFrom` (type: `string`):

Applies to board thread mode, based on thread post time or last reply time (whichever is newer). Formats: relative 3d (last 3 days), 12h (last 12 hours), 2w (last 2 weeks), or an absolute date MM/DD/YY. Leave empty for no filtering. When set, paging also stops early (pinned threads are exempt from this filter and early-stop check), which keeps scheduled monitoring cheap.

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

Apify datacenter proxy is on by default: without a proxy your run shares the platform's egress IPs with every other run, so the forum site rate-limits you (429s, missing pages). HTML responses are small, so proxy bandwidth cost is negligible. Turn it off only for local testing or your own proxy.

## Actor input object example

```json
{
  "mode": "forum",
  "forumIds": [
    "16"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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": "forum",
    "forumIds": [
        "16"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("claude_code_reviewer/hardwarezone-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": "forum",
    "forumIds": ["16"],
}

# Run the Actor and wait for it to finish
run = client.actor("claude_code_reviewer/hardwarezone-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": "forum",
  "forumIds": [
    "16"
  ]
}' |
apify call claude_code_reviewer/hardwarezone-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/hardwarezone-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/cEvtPwvdJIhcowXee/builds/3lv1L6CXBHM6EvveK/openapi.json
