# Weibo Scraper: Posts, Comments & Hot Search (`sz022/weibo-posts-comments-scraper`) Actor

Scrape public Weibo (微博) posts by keyword or account, full comment threads with commenter region and floor number, public profiles and the live hot search list. Video play counts, edit counts, AI labels and expanded links included. No login. Export CSV, Excel or JSON.

- **URL**: https://apify.com/sz022/weibo-posts-comments-scraper.md
- **Developed by:** [CHEN-SHU-CHEN](https://apify.com/sz022) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 post scrapeds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What is Weibo Scraper?

Weibo (微博) is where Chinese public opinion moves first, and its web pages are built for scrolling, not for counting. Copying posts, comments and numbers into a spreadsheet by hand stops working after a few dozen.

This Actor reads **public Weibo data** without a login and gives you clean rows:

- **Posts by keyword** — Weibo's real-time search, newest first.
- **Posts by account** — an account's recent posts, plus its **public profile**.
- **Posts by URL, with their comments** — every comment with the commenter's **region (来自 X)**, its **floor number**, its like count and whether the **post's author liked it**, plus replies if you want them.
- **The hot search list (微博热搜)** — the live top 50 with heat values, labels and the pinned entry.

Every post row carries what makes Weibo data useful beyond the text: **video play counts**, **how many times the post was edited**, **AI-generated / reposted content labels**, **t.cn short links expanded** to where they point, all picture sizes and video files, hashtags, mentions, the province it was posted from, and the full original when it is a repost.

Because it runs on Apify, you can **schedule** a daily keyword or hot-search snapshot, call it from the **API**, connect it to Make, Zapier or Google Sheets, and export as **CSV, Excel or JSON**.

### How to scrape Weibo

1. Open the **Input** tab. Fill in any of the sections; they all work together in one run.
   - **Search keywords**: `瑞幸咖啡`, `#新能源汽车#`, a brand name.
   - **Accounts**: `1669879400`, `https://weibo.com/u/1669879400` or `@Dear-迪丽热巴`.
   - **Post URLs**: `https://weibo.com/1669879400/RlZog45UR` or `https://m.weibo.cn/detail/5352408760976057`.
   - **Hot search**: tick the box.
2. Set how many posts and comments you want. Each row is charged, so the limits are also your budget.
3. Click **Start**. The prefilled example (10 posts, one post with 10 comments, the hot search list) finishes in about half a minute.
4. Open the **Output** tab. There is one view per row type: Posts, Comments, Profiles, Hot search, and Inputs with no rows. A view picks the columns, not the rows: rows of other types appear in it with those columns empty, so filter on `type` when you export.

### What data does it return?

Every row has a `type` (`post`, `comment`, `profile`, `trend` or `status`), the `input` that produced it, and `scrapedAt`. Times are ISO-8601 in Beijing time (`2026-10-18T11:35:55+08:00`). Counts are numbers. A value Weibo does not show is `null`, never a made-up `0`.

#### Posts (`type: "post"`)

| Field | Notes |
|---|---|
| `mid`, `bid`, `url` | Numeric ID, short ID and link |
| `createdAt` | When it was posted |
| `text`, `textHtml` | Plain text and Weibo's HTML |
| `isLongText`, `textExpanded` | Long posts are cut short in feeds; with **Expand long posts** on, the full text is fetched |
| `repostsCount`, `commentsCount`, `likesCount` | Exact numbers |
| `countsCapAt`, `cappedCounts` | Weibo stops counting publicly at 1,000,000 ("100万+"). A count at the cap is listed in `cappedCounts`, so you know it is a lower bound |
| `videoPlayCount`, `videoPlayCountText` | Video plays as a number, and Weibo's text ("10.5万次观看") |
| `videos` | Every video: title, duration, play count, cover, every quality's file URL |
| `pics` | Every picture with all sizes Weibo serves (thumbnail to `mw2000`), live-photo videos included |
| `editCount`, `isEdited` | How many times the author edited it |
| `aiTags` | Weibo's labels such as "博主声明：该内容使用AI生成技术" (AI-generated) or "内容为转载" (reposted content) |
| `contentLabels` | Declarations such as "自主创作" (original work) |
| `links` | Every link with the t.cn short link, the expanded long URL and its title |
| `hashtags`, `topics`, `superTopic`, `mentions` | |
| `regionName`, `regionRaw` | "河北" from "发布于 河北": the province the post was published from |
| `source` | Device or client, e.g. "iPhone 18 Pro" |
| `card`, `audio` | Attached topic, live stream or web card; attached audio |
| `isRepost`, `retweetedStatus` | The original post, with all the same fields |
| `isAd`, `isPaid`, `coAuthors` | |
| `author` | `uid`, `screenName`, `profileUrl`, `avatarUrl`, `verified`, `verifiedType`, `verifiedReason`, `memberRank`, `followersCount` (see below) |

Feeds do not include an author's follower count, so `author.followersCount` is `null` unless you turn on **Add author profiles to posts**.

#### Comments (`type: "comment"`)

| Field | Notes |
|---|---|
| `id`, `postMid`, `postUrl` | |
| `level`, `rootId`, `replyToCommentId`, `replyToUser` | `level` 0 is a comment, 1 a reply |
| `createdAt`, `text`, `textHtml` | Emoticons kept as `[name]` |
| `likesCount`, `repliesCount` | |
| `region`, `regionRaw` | "福建" from "来自 福建": where the commenter posted from |
| `floorNumber` | The comment's floor (楼) under the post |
| `isLikedByMblogAuthor` | Whether the post's author liked this comment |
| `picUrls`, `links` | Pictures attached to the comment, links in it |
| `previewReplies` | The first replies Weibo shows under a comment, nested (free) |
| `author` | The commenter's public account fields, as for posts |

#### Profiles (`type: "profile"`)

`uid`, `screenName`, `profileUrl`, `customUrl`, `avatarUrl`, `coverImageUrl`, `description`, `location`, `ipLocation`, `followersCount` (+ `followersCountText` such as "8255.1万"), `followingCount`, `postsCount`, `totalInteractions`, `totalLikes`, `totalComments`, `totalReposts`, `verified`, `verifiedType`, `verifiedReason`, `memberRank`, `isSvip`, `website`, `registeredAt`, `sunshineCredit`, and Weibo's influence `labels` ("V指数 文娱 87.49分", "近30天视频播放量240.2万").

#### Hot search (`type: "trend"`)

`rank`, `position`, `word`, `note`, `query`, `url` (the search page), `hotValue`, `label` (新, 热, 沸, 爆), `category`, `isTopic`, `isAd`, `isPinned`, `isGovernment`, `capturedAt`. Ads in the list are kept, marked `isAd`, and have no `rank`.

#### Inputs with no rows (`type: "status"`)

Every input is accounted for. An input that produced no rows, or stopped early, gets a free row with `status` and a plain `error`:

`no_results`, `not_found`, `invalid_input`, `duplicate_input`, `blocked`, `partial`, `parse_error`, `not_processed`. The key-value store record `INPUT_SUMMARY` lists every input with its status and row count.

### How much does it cost to scrape Weibo?

You pay per row, and nothing for time spent waiting on Weibo.

| Event | Price | Per 1,000 |
|---|---|---|
| Post (`post-scraped`) | $0.008 | $8 |
| Comment or reply (`comment-scraped`) | $0.004 | $4 |
| Profile (`profile-scraped`) | $0.008 | $8 |
| Hot search entry (`trend-scraped`) | $0.002 | $2 |
| Run start (`apify-actor-start`, per GB of memory) | $0.001 | — |

Examples: 500 keyword posts cost $4. One post with 1,000 comments costs $4.008. A daily hot-search snapshot (about 52 entries) costs about $0.10.

Status rows, posts or comments Weibo served in a broken shape (skipped and counted in the input's `error`), expanded long text, the preview replies nested under each comment, reposts you chose to skip and residential proxy traffic are free. A post that appears under two keywords is written, and charged, once.

#### How do I cap what a run can spend?

Set a maximum cost per run in the run options. Before each page it checks that the limit can still pay for a row, and rows are written and charged together, so a page that only partly fits writes and charges just the rows that fit. Inputs it did not get to come back as `not_processed` rows. If writing or charging fails, the run stops instead of working unpaid, and the charge is not sent a second time.

You are never charged for a row that is not in your dataset. If Apify moves the run to another server mid-way, the restarted run checks its dataset and does not write or charge a row a second time.

### Input example

```json
{
  "keywords": ["瑞幸咖啡"],
  "maxPostsPerKeyword": 100,
  "users": ["1669879400"],
  "maxPostsPerUser": 20,
  "postUrls": ["https://weibo.com/1669879400/RlZog45UR"],
  "maxCommentsPerPost": 200,
  "commentsSort": "hot",
  "includeHotSearch": true
}
```

### Limits worth knowing

- **Keyword search reaches about 1,000 posts per keyword**, newest first: about 24 pages. For a busy keyword that is the last few hours. Weibo's own "hot" and date filters live on s.weibo.com, which refuses logged-out visitors, so there is no sort option; use **Only posts published on or after** to cut old posts.
- **Account posts can have gaps.** Logged out, Weibo refuses the account timeline itself, so posts come from Weibo's search index of that account. It returns about 50 posts a page and goes back years, but it can skip posts: for one account we tested, the index held 1,018 of its 1,937 posts. Use it for recent activity and trends, not as a complete archive.
- **Reposts of a post (转发列表) are not available** logged out; the repost count is.
- **Custom profile addresses** (weibo.com/name) cannot be resolved logged out. Use the numeric ID or @screen name.
- **Counts of 1,000,000 or more are lower bounds**, because Weibo shows "100万+". They are flagged in `cappedCounts`.
- **The original inside a repost is not expanded** when it is long: `retweetedStatus.text` is Weibo's preview. Pass its `url` under **Post URLs** for the full text.
- **Picture and video URLs are signed** and expire after a while (the `Expires` parameter). Download files you need soon after the run.
- **Weibo throttles visitors.** When it answers "前方有点拥堵", the Actor waits, takes a new IP and a new visitor cookie, and retries. If datacenter IPs keep getting refused, it moves to residential IPs for the rest of the run, at no extra cost to you. Failures are reported per input rather than crashing the run.
- This reads undocumented web JSON, which Weibo can change without notice. If a response no longer has the expected shape, the input is reported as `parse_error` rather than writing wrong data.

### Privacy and responsible use

This Actor reads only what Weibo shows any logged-out visitor. It does not log in, and takes no cookies or credentials.

To keep personal data to what an analysis needs:

- Post and comment authors come with their **public account fields only**: name, link, avatar, verification and follower count. No gender, bio or location for people who are not the subject of your request.
- **Email addresses and phone numbers are removed** from all text (posts, comments, bios) and replaced with `[email removed]` / `[phone removed]`. This is the input **Mask emails and phone numbers** (`maskContactInfo`), on by default. Turn it off only if you have a lawful basis to process contact details; the text is then kept exactly as posted.
- **Exact GPS coordinates** that Weibo attaches to some posts are dropped; only the province label ("发布于 河北") is kept.
- Profiles carry account information only: **no gender, birthday, school or employer**.

Public posts and comments are still personal data under laws such as China's **PIPL** and the EU's **GDPR**. **You are responsible for having a lawful basis for collecting and using this data**, for how long you keep it, and for respecting Weibo's terms. This is not legal advice.

### FAQ

#### Why did an input come back blocked?

Weibo refused every retry, on fresh IPs and visitor cookies. It happens in waves; run it again later. If many inputs in a row are refused, the run stops early (see **Stop after this many refused inputs in a row**) and the rest come back `not_processed`, free.

#### Why is a post not_found?

It was deleted, made private, or restricted by Weibo; or the link is mistyped. Weibo's own message is in `error`.

#### Can I get comments for posts found by keyword?

Run the keyword search first, then pass the `url` of the posts you care about into **Post URLs** in a second run. This keeps keyword runs cheap.

#### Why is memory limited to 1 GB?

The Actor reads JSON over plain HTTP and needs little memory; 512 MB is the default. More would not make it faster, only more expensive.

#### Something broke or a number looks wrong

Open an issue on the **Issues** tab with the input and the run link.

# Actor input Schema

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

Words or #topics# to search Weibo for, one per line, in Chinese or any other language. Results come newest first, as Weibo's real-time search returns them. Weibo's search window reaches about 1,000 posts per keyword; for a busy keyword that is the last few hours.

## `maxPostsPerKeyword` (type: `integer`):

Stop each keyword after this many posts. Weibo serves 20 to 50 posts per page.

## `includeReposts` (type: `boolean`):

Weibo's search also returns reposts whose comment mentions the keyword. Turn off to keep original posts only. Reposts that are skipped are not charged.

## `users` (type: `array`):

Weibo accounts as a numeric user ID (1669879400), a profile URL (https://weibo.com/u/1669879400, m.weibo.cn/profile/1669879400) or @screen name. Custom addresses such as weibo.com/name cannot be resolved logged out: open the profile and copy the numeric ID instead.

## `maxPostsPerUser` (type: `integer`):

Recent posts to read for each account, newest first. Set 0 to read profiles only. Logged out, Weibo serves an account's posts from its search index, which can skip some posts; see the README.

## `includeProfiles` (type: `boolean`):

One profile row per account: followers, following, post count, verification, bio, location, total likes, comments and reposts received, and Weibo's influence labels.

## `postUrls` (type: `array`):

Posts to read in full, with their comments: https://weibo.com/1669879400/RlZog45UR, https://m.weibo.cn/detail/5352408760976057, or the bare ID.

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

Read the comments of each post above. Each comment is one row, charged separately.

## `maxCommentsPerPost` (type: `integer`):

Top-level comments to read for each post.

## `commentsSort` (type: `string`):

Weibo's own two orders: most liked first, or newest first.

## `includeReplies` (type: `boolean`):

Off: each comment carries the first two replies Weibo shows under it, nested and free. On: replies are read in full, each as its own comment row (charged as a comment).

## `maxRepliesPerComment` (type: `integer`):

Only used when all replies are included.

## `includeHotSearch` (type: `boolean`):

The live top-50 hot search list with heat values and labels, plus the pinned entry. Ads are included and marked isAd.

## `postedAfter` (type: `string`):

Optional, YYYY-MM-DD in Beijing time. Applies to keyword and account posts. Paging stops at the first page that is entirely older.

## `expandLongText` (type: `boolean`):

Weibo cuts long posts short in feeds with a 全文 link. On: the full text is fetched (one small extra request per long post, no extra charge).

## `scrapeAuthorProfiles` (type: `boolean`):

Feeds do not include an author's follower count. On: each distinct author's profile is read once, written as a profile row (charged as a profile) and its follower count is copied into author.followersCount on their posts.

## `maskContactInfo` (type: `boolean`):

On: email addresses and mainland Chinese phone numbers in post, comment and bio text are replaced with \[email removed] / \[phone removed]. Turn off only if you have a lawful basis to process contact details (see Privacy in the README).

## `abortAfterConsecutiveFailures` (type: `integer`):

Ends the run early when Weibo stops answering. Posts or accounts that do not exist do not count. 0 never stops early.

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

Apify's datacenter proxy by default. If Weibo keeps refusing datacenter IPs, the run moves to Apify's residential proxy (see below), at no extra charge to you.

## `residentialFallback` (type: `boolean`):

Only applies with Apify Proxy. After two refusals in a row on datacenter IPs, the rest of the run uses residential IPs. Turn off to stay on datacenter IPs only.

## Actor input object example

```json
{
  "keywords": [
    "瑞幸咖啡"
  ],
  "maxPostsPerKeyword": 10,
  "includeReposts": true,
  "maxPostsPerUser": 20,
  "includeProfiles": true,
  "postUrls": [
    "https://weibo.com/1669879400/RlZog45UR"
  ],
  "includeComments": true,
  "maxCommentsPerPost": 10,
  "commentsSort": "hot",
  "includeReplies": false,
  "maxRepliesPerComment": 20,
  "includeHotSearch": true,
  "expandLongText": true,
  "scrapeAuthorProfiles": false,
  "maskContactInfo": true,
  "abortAfterConsecutiveFailures": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": true
}
```

# Actor output Schema

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

Posts, comments, profiles and hot search entries, each row tagged with its type and the input that produced it.

## `inputSummary` (type: `string`):

Every input with its status (ok, no_results, not_found, blocked, partial, invalid_input, duplicate_input, not_processed), row count and reason.

# 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 = {
    "keywords": [
        "瑞幸咖啡"
    ],
    "maxPostsPerKeyword": 10,
    "postUrls": [
        "https://weibo.com/1669879400/RlZog45UR"
    ],
    "maxCommentsPerPost": 10,
    "includeHotSearch": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("sz022/weibo-posts-comments-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 = {
    "keywords": ["瑞幸咖啡"],
    "maxPostsPerKeyword": 10,
    "postUrls": ["https://weibo.com/1669879400/RlZog45UR"],
    "maxCommentsPerPost": 10,
    "includeHotSearch": True,
}

# Run the Actor and wait for it to finish
run = client.actor("sz022/weibo-posts-comments-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 '{
  "keywords": [
    "瑞幸咖啡"
  ],
  "maxPostsPerKeyword": 10,
  "postUrls": [
    "https://weibo.com/1669879400/RlZog45UR"
  ],
  "maxCommentsPerPost": 10,
  "includeHotSearch": true
}' |
apify call sz022/weibo-posts-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sz022/weibo-posts-comments-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/a8HbbL43s98QTQfnu/builds/cqmsXEW7cwFR17Y16/openapi.json
