China Hot Lists: Douyin, Weibo, Baidu, Bilibili, Zhihu avatar

China Hot Lists: Douyin, Weibo, Baidu, Bilibili, Zhihu

Pricing

Pay per usage

Go to Apify Store
China Hot Lists: Douyin, Weibo, Baidu, Bilibili, Zhihu

China Hot Lists: Douyin, Weibo, Baidu, Bilibili, Zhihu

Full top-N snapshots of Chinese trending boards with no keywords needed. Per-board status, heat in native units, ad and pinned flags, board update time and cache age.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Sergey Faraday

Sergey Faraday

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

15 minutes ago

Last modified

Share

China Hot Lists: Douyin, Weibo, Baidu, Bilibili, Zhihu, Toutiao

Full top-N snapshots of Chinese trending boards, no keywords needed. Use it to see what China is talking about right now and to track how topics rise and fall between snapshots.

Each board is fetched and reported separately, so one failing board never hides behind an overall success.

Boards

BoardValue in boardsRanking signal
Douyin hot searchdouyin_hotheat
Douyin risingdouyin_risingposition (the source reports heat as 0, returned as null)
Weibo hot searchweibo_hotheat
Baidu hot searchbaidu_hotheat
Bilibili hot searchbilibili_hot_searchheat
Bilibili popularbilibili_popularvideo counters (views, likes, coins, shares, comments)
Zhihu hot listzhihu_hotheat
Toutiao hot boardtoutiao_hotheat

How to use

  1. Run it as is to get six boards, or choose them in boards.
  2. Schedule it a few times a day with a snapshotId per run and compare snapshots on your side to see topics rise and fall. The actor does not compare runs itself: a run cannot read other runs' datasets under limited permissions.

Input

FieldDefaultMeaning
boards6 boardswhich boards to snapshot
topN50ranked rows with position up to N; pinned and ad rows are always kept
staleAfterMinutes180a board older than this is reported as partial and its rows carry data.stale: true; set staleIsPartial to false to only flag it
snapshotId<actor>.<runId>your id for this snapshot; re-running with the same id gives the same row keys, so it does not create duplicates
maxItemsnonehard cap on rows. It is a cut, not a pause: a board the budget cannot reach is not fetched at all. A cut keeps ranked rows first, pinned and ad rows after them
{ "boards": ["douyin_hot", "weibo_hot", "baidu_hot"], "topN": 50 }

Output

One rank_entry row per topic:

{
"recordType": "rank_entry",
"platform": "douyin",
"sourceRecordId": "douyin_hot:s2724502",
"canonicalUrl": "https://www.douyin.com/hot/2724502",
"time": {
"publishedAt": null,
"sourceUpdatedAt": "2026-11-01T17:41:56.000Z",
"sourceUpdatedAtBasis": "data.active_time (Asia/Shanghai)",
"observedAt": "2026-11-01T17:43:33.007Z",
"observedAtBasis": "response_received",
"availableAt": "2026-11-01T17:41:56.000Z",
"availableAtReason": null,
"collectedAt": "2026-11-01T17:43:33.014Z",
"runStartedAt": "2026-11-01T17:43:31.000Z"
},
"metrics": {
"position": { "value": 1, "sourceName": "platform_position", "unit": "rank", "kind": "rank" },
"heat": { "value": 12111620, "sourceName": "hot_value", "unit": "douyin_hot_value", "kind": "index", "window": "snapshot" }
},
"data": { "board": "douyin_hot", "term": "...", "termIdStable": true, "position": 1, "isAd": null, "adEvidence": "not_provided_by_source", "isPinned": false, "stale": false, "labels": ["label_code_3"] },
"sampling": { "boardFetchId": "f_edd2551d83e0", "topNRequested": 50, "visibleSize": 49, "rankedVisible": 49, "sourceAgeSeconds": 97 }
}

The MANIFEST record in the key-value store reports the status of every board (ok, partial, blocked, failed), visible size, rows selected and kept (applied.selected, applied.kept), truncation, cache age and errors. applied.attempted: false marks a board the run never fetched. Every requested board stands in every MANIFEST, also after an abort or a crash. http counts the requests of all workers of the run, and a request in flight when a worker was killed is not counted; sources[].http says what each board took. On bilibili_popular, reading stopped by topN while the source says more exists is truncated: true with topN_requested; a shorter list the source did not end is partial with fewer_rows_than_topN_before_no_more. With keepRaw, raw holds no account ids on any board.

How to read the data

Time. These are different events, and an unknown one stays null:

FieldMeaning
runStartedAtthe platform started the run; the same on every row, also after a restart
observedAtthe response of this board arrived; on a paged board, the response of this row's page
collectedAtthis collector built the row; use only this field to ask "what did we know at time T"
sourceUpdatedAt, availableAtthe board's own update time, Douyin data.active_time and Baidu cards[0].updateTime. Elsewhere null, and sourceUpdatedAtBasis and availableAtReason say why

On every row runStartedAt <= observedAt <= collectedAt. A board's update time says when the platform refreshed the board, not when this collector knew the value.

Staleness. data.stale is true or false where the source publishes an update time and null where it does not: unknown is not fresh. A stamp more than 5 minutes ahead of the read says nothing about freshness either: data.stale and the age are null, and a note SOURCE_STAMP_IN_FUTURE names it.

Ads. data.isAd is true or false only on Weibo. null means the source gives no ad flag: unknown, not organic, so a paid row could sit in a ranked list unmarked. Weibo sets is_ad on ad rows only: 1, "1" and true mean an ad, 0, "0" and false mean none, and any other value gives isAd: null on that row with SCHEMA_CHANGED. A response with no ad slot is told by its rows: every row has a platform rank and none has is_ad, ad_type, ad_channel or topic_ad, so all are isAd: false. If no row carries a known flag and that does not hold, every listed row gets isAd: null, a row without a platform rank gets no position, and the board reports SCHEMA_CHANGED as partial.

Changed sources. A row of a board is defined by its term or title, its platform id and rank where the board has them, and its heat or counters. If one of these is absent or unreadable on every row, at any size, or on 10% or more of the rows from 10 rows up, the board reports SCHEMA_CHANGED and is partial while rows hold a term or an id, failed when none does. A value that cannot be read is null with unparseable and its raw text kept. A field holding null or an empty text is source_null or source_empty, and a field that is gone is not_provided_by_source. Zero on every ranked row is no measurement: null with zero_not_confirmed_as_real and SCHEMA_CHANGED; one zero among values stays 0. A missing pinned block (data.hotgov, fixed_top_data, Baidu isTop and topContent) or a missing no_more is reported the same way; null or an empty block says nothing is pinned. A row with neither a term nor an id is not delivered: it is listed in sources[].excluded with its place, with ROWS_EXCLUDED, and the board is partial. A row with a platform id and no term stays with data.term: null and a note ROWS_WITHOUT_TERM.

Heat. Heat is in each platform's native units and is not comparable between boards. The platforms do not define these numbers in their responses, and no normalization is applied or promised.

Topic identity. Ids are the platform's own where they exist (Douyin sentence_id, Zhihu question id, Toutiao ClusterId, Bilibili bvid). Elsewhere (Weibo, Baidu, Bilibili hot search, pinned rows) the id is a hash of the normalized text, marked termIdStable: false: it identifies a wording, not a topic, so a reworded topic gets a new id.

Leaving the list. Dropping out of the top N means leaving the visible part of the board, not zero interest.

Restarts. One board holds one fetch (data.boardFetchId). The rows of a fetch are saved in the run checkpoint before they are written, so a restart during the write delivers the rest of the same fetch under the same id and the board is not read again; the rows keep the times of the worker that received them. A board is read again only if the process died before that checkpoint. If the report of a fetch was lost with the process, the board is partial with RESTART_REPORT_LOST. If a run cannot read its own dataset back after a restart, a board whose rows were on their way is partial with OWN_ROWS_UNREAD. A cut made by maxItems is final: the run ends there, and a repeat with a larger limit under the same snapshotId reads the boards again.

FAQ

Can I compare heat between boards? No. Each platform has its own units.

Why is heat null on Douyin rising? The source reports 0 for every rising topic, so the number says nothing. The position is real.

Does isAd: null mean the row is organic? No, it means unknown. Only Weibo marks ad rows.

Why did a topic get a new id between two snapshots? On boards without a platform id, the id follows the text. Check data.termIdStable.

Cost

Runs in seconds. A measured 8-board snapshot at top 50 cost $0.0025 of platform usage at 512 MB; 6-board snapshots at top 50 cost $0.0010 to $0.0018. At $0.0025, four snapshots a day come to about $0.30 a month.

Limits

Only openly served board endpoints are used. If a source blocks access, the board is reported as blocked, and no bypass is attempted.