# Bahamut 巴哈姆特 Gaming Forum & VOC Scraper (`research_master/bahamut-gaming-forum-voc-scraper`) Actor

Discover Bahamut game boards and collect complete public discussions, floors, comments, GP/BP, available views, media links, crawl audits, and incremental VOC updates.

- **URL**: https://apify.com/research\_master/bahamut-gaming-forum-voc-scraper.md
- **Developed by:** [Research Master](https://apify.com/research_master) (community)
- **Categories:** AI, Agents, Social media
- **Stats:** 1 total users, 1 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.90 / 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/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

## Bahamut Gaming Forum & VOC Scraper

Collect structured, public discussion data from the Bahamut Gaming Forum (`forum.gamer.com.tw`) for game research, community monitoring, and auditable VOC analysis.

This Actor is purpose-built for Bahamut's `bsn`, `snA`, floor, comment, GP/BP, and board-search model. Generic phpBB or Discourse scrapers do not understand those relationships; broad web/forum search Actors usually return snippets instead of complete Bahamut threads.

### Choose this Actor when

- You need to discover a Bahamut game board from a game/board name or start from known `bsn` values.
- You need keyword search inside selected boards with latest or GP-based ordering.
- You need the original post, every available floor, public comments, GP/BP, and available listing view counts in one discussion record.
- You need repeatable post-release monitoring that emits new or updated discussions and preserves a crawl audit.

Do not choose it for logged-in, age-restricted, deleted, private, or permission-gated content. The Actor records those URLs as inaccessible and does not bypass platform controls.

### What it collects

Each successful discussion is one Dataset item containing:

- board `bsn`, discussion `snA`, board name, title, canonical URL, tags, and timestamps;
- original post and all available floors with content text/HTML, author identity handling, GP, BP, and timestamps;
- all public comments per floor with comment IDs, content, timestamps, GP, and BP;
- available view count from board listing discovery;
- public image URLs and external links referenced in content;
- pagination and comment completeness fields;
- source keywords/listings, monitoring status, and optional game version label.

The Actor never downloads images, videos, animations, or linked files. It excludes links hosted by Bahamut Anime (`ani.gamer.com.tw`) and Bahamut Store (`buy.gamer.com.tw`) and never visits external links.

### Inputs

Provide at least one source:

- `boardQueries`: game/board names, such as `原神`, for board discovery;
- `bsns`: known board IDs supplied as numeric strings, such as `"36730"`;
- `startUrls`: direct public `C.php` discussion URLs.

The Console prefill uses one known public discussion and one-item limits so Apify's automated quality test can validate the Actor quickly. These prefill values do not change API, schedule, or Saved Task defaults; those runs must still provide at least one source.

Useful controls:

- `keywords`: searches every selected board. Empty keywords use board listings.
- `sortBy`: `LATEST` or `HOT`. Keyword hot ordering uses Bahamut GP sorting. Without keywords, hot ordering ranks the page-bounded candidates by GP.
- `publishedAfter` / `publishedBefore`: filter using the first floor's Asia/Taipei publication time.
- `maxListPages`, `maxThreads`, `maxThreadPages`: hard collection limits. `maxThreadPages: 0` means all available thread pages.
- `includeComments`, `includeImages`, `includeExternalLinks`: output depth controls.
- `authorMode`: `HASHED` (default), `RAW`, or `OMIT`.
- `authorHashSalt`: optional secret salt for hashes stable across unrelated runs.
- `proxyConfiguration`: defaults to the verified Taiwan residential proxy route. The tested direct and generic data-center routes returned Bahamut HTTP 403 challenge pages; changing the proxy route can affect access and cost.

#### Example: keyword VOC collection

```json
{
  "operation": "SCRAPE_DISCUSSIONS",
  "boardQueries": ["原神"],
  "keywords": ["更新", "卡頓", "閃退"],
  "sortBy": "LATEST",
  "publishedAfter": "2026-08-01",
  "maxListPages": 3,
  "maxThreads": 50,
  "maxThreadPages": 0,
  "includeComments": true,
  "authorMode": "HASHED",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "TW"
  }
}
```

#### Example: known board, popular discussions

```json
{
  "bsns": ["36730"],
  "keywords": ["聖遺物"],
  "sortBy": "HOT",
  "maxListPages": 2,
  "maxThreads": 20,
  "includeComments": true
}
```

### Incremental version monitoring

Run the same input repeatedly with the same monitor key. The Actor stores only fingerprints and monitoring metadata in a named Key-Value Store; successful discussion results remain in the current run's Dataset.

```json
{
  "bsns": ["36730"],
  "keywords": ["7.0", "更新", "BUG"],
  "publishedAfter": "2026-08-12",
  "sortBy": "LATEST",
  "monitoring": {
    "enabled": true,
    "key": "genshin-7-0",
    "onlyNew": true,
    "includeUpdated": true,
    "versionLabel": "7.0"
  }
}
```

- First run: records are `NEW`.
- Later runs: unseen discussions are `NEW`; changed floors/comments/metrics are `UPDATED`; unchanged discussions can be skipped.
- Set `reset: true` only when intentionally starting a new baseline for that monitor key.

### Audit and completeness

Audit records are stored in the default Key-Value Store so they are not mixed with business results:

- `RUN_AUDIT`: sanitized input summary, counts, deduplication, monitoring, and media policy;
- `PAGE_AUDITS`: requested/final URLs, response status, attempts, bytes, and timing;
- `FAILED_URLS`: failed, deleted, sensitive, or login-required URLs and reasons;
- `INCOMPLETE_DISCUSSIONS`: successfully parsed but capped/incomplete discussions. These are deliberately not pushed to the default Dataset.

`completeness.is_complete` requires all detected thread pages, expected floors when known, and requested comments to be present. View count can be `null` for direct URLs and keyword results because Bahamut exposes exact views on board listings, not consistently on every discussion/search response.

### Responsible use

Collect only public data and follow applicable laws, Bahamut terms, and research ethics. Use conservative limits and delays. Hashed author IDs reduce direct exposure but are pseudonymous, not anonymous; use a private salt and restrict access when identity linkage is unnecessary.

# Actor input Schema

## `operation` (type: `string`):

Discover boards only, or discover/select boards and collect discussion records.

## `boardQueries` (type: `array`):

Game or board names used to discover candidate BSNs through Bahamut's public ACG directory.

## `bsns` (type: `array`):

Known Bahamut board IDs as numeric strings. These are validated at runtime, merged with discovered boards, and deduplicated.

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

Optional public Bahamut C.php discussion URLs. Direct URLs are collected before discovered candidates.

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

Search each selected board for these keywords. Leave empty to collect from board listings.

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

Latest uses thread creation/search time. Hot uses GP for keyword results and page-bounded GP ranking for board listings.

## `publishedAfter` (type: `string`):

Optional ISO date or datetime. Filtering uses the first floor's publication time in Asia/Taipei.

## `publishedBefore` (type: `string`):

Optional ISO date or datetime. A date-only value includes the entire local day.

## `maxBoards` (type: `integer`):

Maximum unique boards retained after merging explicit and discovered BSNs.

## `maxListPages` (type: `integer`):

Maximum pages read per board or board-keyword combination.

## `maxThreads` (type: `integer`):

Global maximum unique discussions selected for detail collection.

## `maxThreadPages` (type: `integer`):

Use 0 for every available page. A positive safety cap makes longer discussions incomplete; they are saved to INCOMPLETE\_DISCUSSIONS in the default Key-Value Store and are not pushed to the Dataset.

## `includeComments` (type: `boolean`):

Expand the public comment endpoint for every collected floor.

## `includeImages` (type: `boolean`):

Return image URLs referenced in posts and comments. Images are never downloaded.

## `includeExternalLinks` (type: `boolean`):

Return external URLs without visiting them. Bahamut Anime and Store URLs are excluded.

## `authorMode` (type: `string`):

Hash author IDs by default, retain raw IDs, or omit IDs. Display names follow the same omission rule.

## `authorHashSalt` (type: `string`):

Optional secret salt for stable hashes across unrelated runs. Monitoring runs persist a generated salt when this is empty.

## `monitoring` (type: `object`):

Persist discussion fingerprints across runs and emit only new or updated discussions after a game version marker.

## `requestDelayMs` (type: `integer`):

Polite delay before each request to Bahamut.

## `maxRequestRetries` (type: `integer`):

Retries for transient public-page failures. Inaccessible or sensitive pages are not bypassed.

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

Taiwan residential proxy is the verified default because Bahamut blocks the tested direct and generic data-center exits. Changing it can cause HTTP 403 responses and may change proxy cost.

## Actor input object example

```json
{
  "operation": "SCRAPE_DISCUSSIONS",
  "boardQueries": [],
  "bsns": [],
  "startUrls": [
    {
      "url": "https://forum.gamer.com.tw/C.php?bsn=36730&snA=46445"
    }
  ],
  "keywords": [],
  "sortBy": "LATEST",
  "maxBoards": 10,
  "maxListPages": 1,
  "maxThreads": 1,
  "maxThreadPages": 0,
  "includeComments": true,
  "includeImages": true,
  "includeExternalLinks": true,
  "authorMode": "HASHED",
  "monitoring": {
    "enabled": false,
    "key": "default",
    "onlyNew": true,
    "includeUpdated": true,
    "versionLabel": ""
  },
  "requestDelayMs": 500,
  "maxRequestRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "TW"
  }
}
```

# Actor output Schema

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

Default dataset containing only successfully collected boards or complete discussion records.

## `runAudit` (type: `string`):

Run totals, completeness, deduplication, monitoring, and failure summary.

## `pageAudits` (type: `string`):

One non-billable audit entry per requested page.

## `failedUrls` (type: `string`):

Failed or inaccessible URLs and their final error reasons.

## `incompleteDiscussions` (type: `string`):

Parsed discussions excluded from results because one or more requested pages, floors, or comments were incomplete.

# 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 = {
    "startUrls": [
        {
            "url": "https://forum.gamer.com.tw/C.php?bsn=36730&snA=46445"
        }
    ],
    "maxListPages": 1,
    "maxThreads": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("research_master/bahamut-gaming-forum-voc-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 = {
    "startUrls": [{ "url": "https://forum.gamer.com.tw/C.php?bsn=36730&snA=46445" }],
    "maxListPages": 1,
    "maxThreads": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("research_master/bahamut-gaming-forum-voc-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 '{
  "startUrls": [
    {
      "url": "https://forum.gamer.com.tw/C.php?bsn=36730&snA=46445"
    }
  ],
  "maxListPages": 1,
  "maxThreads": 1
}' |
apify call research_master/bahamut-gaming-forum-voc-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,research_master/bahamut-gaming-forum-voc-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/2WZ6GzetAoNTDrGd7/builds/9ffOT2hpaDaOTy6Na/openapi.json
