# WeChat Universal Search Scraper (`opspilot.cc/wechat-universal-search-scraper`) Actor

EN — Search WeChat ecosystem (公众号 / 视频号 / 文章 / 账号) by keyword. 18 business\_type filters, cursor auto-pagination, normalized output with large IDs preserved as strings. 5 free runs/day. ZH — 微信「搜一搜」综合搜索 — 公众号·视频号·文章·账号 一键抓取,18 个 business\_type 筛选,cursor 自动翻页,大整数 ID 全保 string。

- **URL**: https://apify.com/opspilot.cc/wechat-universal-search-scraper.md
- **Developed by:** [wang wei](https://apify.com/opspilot.cc) (community)
- **Categories:** Social media
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.10 / actor start

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

## WeChat Universal Search Scraper

**EN — Find WeChat content across 公众号 / 视频号 / 文章 / 账号 in 30 seconds.** Drop one keyword, get up to 50 ranked results (5 pages × ~10) with engagement metrics (likes, comments, duration), publisher profile, shareable URLs, and cover images. No login, no captcha, no headless browser.

**ZH — 微信「搜一搜」综合搜索 — 公众号·视频号·文章·账号 一键抓取。** 一个关键词,最多 50 条结果(5 页 × ~10),含点赞数/评论/时长、发布者资料、可分享链接、封面图。无登录、无验证码、无 headless 浏览器。

Built for **cross-border e-commerce sourcing**, **influencer discovery**, **trend monitoring**, and **KOL prospecting** on WeChat — China's #1 super-app with 1.3 billion monthly users. Output exports as JSON / CSV / Excel — pipe directly into your CRM, BI tool, or another Apify Actor.

**5 free runs / day — no API key required.** Open on Apify Console, drop a keyword, get results in 30 seconds.

### What you can search

| `businessType` | What you get | EN | 中文 |
|---|---|---|---|
| `all` (default) | All verticals mixed | All | 综合 |
| `account` | 公众号 / 服务号 / 视频号 accounts | Accounts | 公众号账号 |
| `article` | 公众号 articles | Articles | 公众号文章 |
| `video` | 视频号 Channels videos | Videos | 视频号视频 |
| `sticker` | 表情 stickers | Stickers | 表情包 |
| `underline` / `encyclopedia` / `live_stream` / `comment` / `listen` / `news` / `photos` / `book` / `moments` / `image` / `mini_game` / `weixin_index` / `ai_search` | (TikHub documents these verticals but they currently return empty due to server-side geographic / account gating) | — | 实测空 |

All inputs also support:

- `keyword` (1-100 chars, e.g. `美食`, `人民日报`, `跨境电商`)
- `sort`: `default` (relevance) / `latest` / `hot`
- `publishTime`: `all` / `day` (24 h) / `week` (7 d) / `half_year` (6 mo)
- `maxPages`: 1-5 pages, default 3 (cost control)
- `cursor`: opaque token from a previous run's `SUMMARY.nextCursor` for resumable pagination
- `raw`: include the unprocessed upstream `data` envelope on each pushed item (off by default)

### Input

```json
{
  "keyword": "美食",
  "businessType": "video",
  "sort": "default",
  "publishTime": "all",
  "maxPages": 3,
  "cursor": "",
  "raw": "false"
}
```

### Output

Each pushed item is a normalized row keyed by `businessType` + `docId` (string — base64 may exceed JS Number safe range):

```json
{
  "keyword": "美食",
  "page": 1,
  "rank": 1,
  "businessType": "video",
  "businessTypeRaw": 7,
  "docId": "finderobjv0iGrW2Ju7cmIl5Q2m0E",
  "exportId": "export/UzFfAEDovIKb9q9zJ4...",
  "hashDocId": "17711004180000001",
  "feedNonceId": "1717...",
  "title": "家常菜快手菜...",
  "titleRaw": "...<em class=\"highlight\">美食</em>...",
  "coverUrl": "https://wx.qlogo.cn/...",
  "duration": "03:42",
  "pubTime": 1757365200,
  "dateLabel": "2小时前",
  "likeNum": "10万+",
  "source": {
    "name": "刘小妹正餐",
    "iconUrl": "https://wx.qlogo.cn/...",
    "verified": true
  },
  "collectedAt": "2026-09-09T00:00:00Z"
}
```

Article-shaped items add `docUrl` (公众号原文链接) and `description`; account-shaped items add `description` (account intro) and use `coverUrl = iconUrl`. The `businessTypeRaw` integer field echoes the upstream `business_type` code so you can route / segment downstream (7 = video, 2 = article, **33554499 = account** — the actual upstream magic number, not 14).

The run also writes a `SUMMARY` to the Key-Value Store with `pushed / pagesFetched / nextCursor / businessTypeRaw / hasMoreInSource / tier / runsToday / dailyLimit / startedAt / finishedAt` — use `nextCursor` on the next run for resumable pagination.

### Use cases

- **Cross-border e-commerce sourcing / 跨境电商内容监控**: find 公众号 + 视频号 KOLs posting about your category, capture `exportId` (video) or `docUrl` (article) to download the media, push to your CRM.
- **Influencer discovery (视频号) / KOL 调研**: filter by `businessType=video` + `publishTime=week` to surface emerging Channels creators before they saturate.
- **Trend monitoring / 舆情追踪**: run daily with the same keyword, diff `docId` sets between runs to spot new entrants.
- **Brand monitoring / 品牌账号监测**: track 公众号 articles mentioning your brand or product category, paginate via `nextCursor`.
- **Account prospecting / 公众号账号挖掘**: `businessType=account` returns account metadata + icon, ideal for building a target publisher list.

### Pagination

The Actor auto-paginates via the upstream `cursor` + `continue_flag` envelope. Set `maxPages` (1-5) to cap requests per run (5 pages ≈ 50 items). To resume a previous run, copy `SUMMARY.nextCursor` from the previous run into `cursor` on the next run.

| `maxPages` | Items per run (avg) | Cost control / 成本控制 |
|---:|---|---|
| 1 | ~10 | smoke test / 冒烟测试 |
| 3 (default) | ~30 | sweet spot / 推荐值 |
| 5 | ~50 | hard cap (cost & quota safety) |

### Quick start

Open the [Actor on Apify Console](https://console.apify.com/), fill in `keyword` (e.g. `美食`), click **Start**. Results land in the Dataset tab in ~30 seconds.

Want to run from the CLI?

```bash
apify call wechat-universal-search-scraper -i '{"keyword": "美食", "businessType": "video"}'
```

The upstream API key is wired into the Actor — no Secrets tab setup, no env vars to set. Apify free users get 5 runs / day.

### Sister Actor — Channels video search

For 视频号 Channels-only video search with `duration` filter (short / medium / long) and `sort` (latest / hottest), see the sister Actor:

→ [WeChat Channels Video Search Scraper](https://console.apify.com/search?q=wechat-channels-video-search-scraper) — same keyword, dedicated video endpoint with time / length filters.

### Tests

```bash
npm test
```

Runs 23 unit assertions (input validation, request body shape, normalization across video / article / account shapes) plus 7 integration scenarios (mock fetch drives the full `run()` flow against captured upstream fixtures).

```
✅ unit.js: 23 assertions passed.
✅ integration.js: 7 scenarios passed.
```

### Notes on upstream behavior

- **business\_type is an integer code per upstream / business\_type 是上游整数代码**: `7` = video (视频号), `2` = article (公众号文章), **`33554499` = account** (the actual upstream magic number — TikHub's docs mention `14` for account but the live API returns `33554499`). The Actor accepts the upstream's code verbatim and exposes it as `businessTypeRaw`; the matched `businessType` string comes from your input.
- **13 verticals return empty pages / 13 个分类返空**: TikHub documents 18 `business_type` values but only 5 (`all` / `account` / `article` / `video` / `sticker`) currently return real results; the other 13 are server-side gated by geography / account. The Actor exposes all 18 per `AGENTS-apify-archive.md §40` (open enum = no surprises).
- **30-second hard timeout / 30 秒硬超时**: TikHub documents that the upstream takes up to 30 s. The Actor enforces this with `AbortController` + exponential backoff (3 retries: 500 ms / 1 s / 2 s).
- **Large integer IDs preserved as string / 大整数 ID 保 string**: `docID` is base64, `hashDocID` is a 19-digit number, `likeNum` includes Chinese units like `10万+`. All kept as strings to avoid JS Number precision loss.

### Changelog

See [CHANGELOG.md](./CHANGELOG.md).

### License

Apache-2.0

# Actor input Schema

## `keyword` (type: `string`):

WeChat search keyword, 1-100 characters. Whitespace trimmed. Examples: 美食, 人民日报, 跨境电商.

## `businessType` (type: `string`):

Which content vertical to search. Default `all` covers everything. Verified results: all / account / article / video / sticker. Other 13 verticals return empty (TikHub documents them as server-side geographic/account restrictions).

## `sort` (type: `string`):

Result ordering. Default = relevance.

## `publishTime` (type: `string`):

Filter by publish time. Default = all time.

## `maxPages` (type: `integer`):

Cap on pages fetched per run (1-5). Each page = ~10 items.

## `cursor` (type: `string`):

Opaque token from a previous run's SUMMARY.nextCursor (resumable pagination). Leave empty to start fresh.

## `raw` (type: `string`):

Add the unprocessed upstream data object as rawData on every pushed item. Default false keeps datasets small; turn on for debugging or downstream pipelines that need the raw response.

## Actor input object example

```json
{
  "keyword": "美食",
  "businessType": "all",
  "sort": "default",
  "publishTime": "all",
  "maxPages": 3,
  "cursor": "",
  "raw": "false"
}
```

# Actor output Schema

## `dataset` (type: `string`):

One normalized dataset item per unique WeChat result. Video / article / account items normalized to a common field set (docId, title, coverUrl, source.name, source.iconUrl). Video adds exportId/duration/likeNum; article adds docUrl; account adds description. Large IDs preserved as strings.

## `summary` (type: `string`):

Run-level summary: keyword, businessType, sort, publishTime, pagesFetched, requests, pushed, receivedFromSource, businessTypeRaw (raw int from upstream), hasMoreInSource, nextCursor, startedAt, finishedAt, tier, runsToday, dailyLimit.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("opspilot.cc/wechat-universal-search-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("opspilot.cc/wechat-universal-search-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 '{}' |
apify call opspilot.cc/wechat-universal-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,opspilot.cc/wechat-universal-search-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/0Gl2Wi2L7vo9GLF1T/builds/obPDDx9tEgTnc9CA8/openapi.json
