# China News Feed with Deletion Watch (`china.unofficial/china-news-feed`) Actor

China news from 155 Chinese-language sources in one feed: state media, party-gov, commercial, overseas independent, dissident and censorship trackers, each labeled by outlet type and grouped by story. Plus a deletion watch on Weibo, Baidu, Zhihu, Toutiao and Bilibili hot lists, with evidence.

- **URL**: https://apify.com/china.unofficial/china-news-feed.md
- **Developed by:** [Ownly China Media Feed](https://apify.com/china.unofficial) (community)
- **Categories:** News, Social media
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$8.00 / 1,000 results

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

## China News Feed with Deletion Watch

**Who said what, and what went missing.**

See how the same China story is told by state media, overseas independents and dissident sources, side by side. Every item carries its source type, and stories are grouped across types so you can compare coverage at a glance. How many new items a run returns varies by source and by how long it has been since your last run. Some sources update hourly, and their rows are marked `fetch: "hourly"`.

On top sits a deletion watch on five mainland hot lists: Weibo, Baidu, Zhihu, Toutiao and Bilibili. When a topic drops off while it's still hot, we recheck it and flag it **Censored** only with hard evidence, or **Likely censored** on medium evidence. Topics that come back are marked **Returned**. Every flag shows its evidence, and weaker signals are filtered out before they reach your dataset.

#### What you get

- **Every item is labeled by source type:** State media, Party-gov, Commercial platform, Overseas independent, Dissident, Censorship tracker. Aggregator sites are credited to the original outlet (see below).
- **Cross-source story clusters.** The same story from state media, overseas outlets and censorship trackers shares one `topic_id`, so you can compare the framing side by side.
- **Deletion flags, with evidence.** Every flag has a status, timestamps and the evidence behind it, and flagged stories are listed first.
- **Hot-list rows.** Public, logged-out lists from **Weibo hot search, Baidu hot search, Zhihu hot list, Toutiao hot board and Bilibili hot search** (大陆平台热榜), with rank, heat and time for each topic. Kuaishou and Douyin hot lists are included as hot-list rows only (see below).
- **Deletion watch runs on our side.** We snapshot the hot lists ourselves and compare each snapshot with the ones before it. Your schedule decides how often new rows reach you; it doesn't change which topics get flagged. If our shared snapshots are unavailable or out of date, a run includes no deletion flags rather than guessing.
- **Two feeds:** a **Chinese feed** (original headline and a short excerpt) and an **English feed** (machine-translated headline, excerpt of up to 30 words, generated summary). Flagged stories lead both feeds. English is translated within a daily budget, newest rows first, so not every row gets it. Rows that aren't reached ship in Chinese only, marked `translation_status: translation_pending`.
- **The official line.** For each flagged story you get a state-media item from the same cluster, or "No official comment found" (未找到官方回应).
- **Where it survived.** Other platforms, overseas outlets and trackers where the story is still visible.

#### Statuses: Censored, Likely censored, Returned

We ship **two** censorship statuses plus Returned. Weaker signals are filtered out and never reach your dataset.

| Status (`status`) | Label (`label` / `label_zh`) | What it takes |
|---|---|---|
| `censored` (tier `high`) | **Censored** / 【已被审查】 | The topic left the list while hot **and is still gone after 1 hour**, **and** there is hard evidence: the topic URL returns **404/410**, Weibo shows the **「根据相关法律法规」** notice, or **China Digital Times / CDT 404 Archive** has an entry **dated after we first saw the topic**. Marked `provisional: true` until the 24-hour recheck. |
| `likely_censored` (tier `medium`) | **Likely censored** / 【疑似被审查】 | An abrupt drop from the top of the list while hot (high rank or rising, heat not decaying), still gone at the 10-minute recheck, with medium-strength evidence but **no hard evidence yet**. |
| `returned` | **Returned** | The topic was flagged and then came back. We keep it visible rather than quietly deleting the flag. |

**Zhihu:** Zhihu hot list is checked hourly, so not every removal is caught. A question is flagged only if it drops out of the top 15 and Zhihu itself reports it as removed, which can take up to a day after it leaves the list. Zhihu flags are always **Censored** (there is no Likely censored for Zhihu), and they show two times: **dropped from list at** (`censored_at.first_missing`) and **still missing as of** (`confirmed_gone_at`). Proof that Zhihu reports the question removed is in `evidence`. The flag says the question is gone; it doesn't say when it was removed.

**Kuaishou and Douyin:** Kuaishou hot board is checked hourly, as hot-list rows only, with no deletion watch. Douyin is hot-list rows only, with no deletion watch, credited "Douyin (via anyknew.com)".

**Third-party copies of hot lists:** Some hot-list rows come from a public third-party copy of the list and are credited, for example (via anyknew.com). We never use those rows on their own to mark anything Censored or Likely censored.

**Never shipped:** unconfirmed drops, posts the author deleted (已被作者删除; that's not censorship), and anything from a list that failed to load. A failed fetch is never treated as a deletion. When we miss snapshots, for example during maintenance, items that drop off in that window aren't marked Censored or Likely censored.

**Each flag carries:**

- `censored_at` (`last_seen` and `first_missing`, in UTC and ET)
- `time_on_list` (a lower bound)
- `peak_rank`, `peak_heat`
- `platforms_affected`, `survived_on`
- `evidence[]` (each entry has `check`, `ts`, `signal`, `result`, `url`). A page check (`url_check`) records whether the topic's link still loads or is gone (404/410). A login wall or a blocked check is recorded as `inconclusive`, never as live.
- `official_line`
- `why`

**`why` is filled only from China Digital Times or named overseas reporting, with links. We never guess.** If no source exists, it stays empty ("Unknown / 原因不明").

#### Source-type labels

| Label (`source_type`) | What it covers |
|---|---|
| State media | Mainland China news outlets: central party/state media and market-oriented or business outlets. Privately owned outlets such as Caixin, Sohu, Tencent News, Jiemian and Yicai are shown as "State media (privately owned)" with an ownership note. `label_note` adds a neutral descriptor such as "market-oriented", "business" or "local". `label_display` always names the outlet, so you never see a bare "State media". |
| Party-gov | Government bodies, e.g. MFA regular press conferences (one item per Q\&A) |
| Commercial platform | The Weibo, Baidu, Zhihu, Toutiao and Bilibili hot lists; Kuaishou and Douyin hot-list rows (no deletion watch); other platform content |
| Overseas independent | Overseas Chinese-language outlets, e.g. BBC Chinese, VOA Chinese (Mandarin), DW Chinese, Lianhe Zaobao; Hong Kong/Taiwan/Singapore/Malaysia outlets, with the region in `label_note` |
| Dissident | Outlets openly opposed to the CCP; affiliations are stated in the source row. Includes outlets of the NFSC network (labeled `network: "NFSC"`), which aren't part of deletion watch |
| Censorship tracker | China Digital Times, CDT 404 Archive, China Media Project and other trackers |

Source-type labels describe the outlet, not the story: they say what kind of institution published it, never whether an item is true.

Aggregator sites (Backchina, Creaders, Baidu News) are used only to find stories. Each item is credited to its original outlet and takes that outlet's label, or it's dropped if the outlet isn't named. No row ships as "Aggregator".

**Deleted WeChat articles:** the feed includes deleted WeChat articles collected by China Digital Times, credited to CDT. We don't collect WeChat ourselves.

**Google News route:** Ming Pao, HKET and Sin Chew stories come through Google News' public search feed. They're labelled with the outlet's own name and type, marked `via: "Google News"`, and their links open through Google News before reaching the outlet's article. They count as their outlet for story spread, and deletion watch doesn't cover them.

**Collector sources:** Beijing News, Shenzhen News, Xinhua Daily, China Press and Sydney Today come through our collector. If one of these fails, it keeps showing its last good rows until each is 48 hours old. If our collector is down for more than 3 hours, all five show 0 rows and are marked stale, and old rows aren't brought back when it restarts. Other sources show 0 rows while they're failing.

**YouTube and Telegram:** up to 34 YouTube and 10 Telegram channels, one currently paused. YouTube's own channel feeds are sometimes unavailable, so a run can include rows from fewer channels. They're labeled by outlet type, aren't part of deletion watch, and names of private individuals are replaced with `[redacted-name]` automatically.

**G·HOT reports:** on G·HOT daily and weekly rows, `published` is when the report was released, not the day it covers. The covered day is in the title and the URL (/archive/reports/<day>).

Every run writes `SOURCE_STATUS_JSON`, listing every source, including ones that couldn't be read on that run and why. `ok: false` means the latest fetch failed, not that no rows shipped.

#### Coverage

About **155** maintained news sources (the status file lists every source we try, including blocked ones), plus the Weibo, Baidu, Zhihu, Toutiao and Bilibili hot lists (deletion watch) and Kuaishou and Douyin hot-list rows (no deletion watch).

Sources in the count (working sources only; final list from the same health check):

- **State media:** 36Kr; Cailian Press 财联社; Caixin Global (English); Caixin 财新网; Huxiu 虎嗅; IT Home IT之家; Jiemian 界面新闻; Jiqizhixin 机器之心; LatePost 晚点; National Business Daily 每经网; NetEase News 网易新闻; Phoenix 凤凰网; Securities Times 证券时报; Sina News 新浪新闻; Sohu News 搜狐新闻; Tencent News 腾讯网; Yicai 第一财经; Qiushi 求是网; RTHK 香港電台; Study Times 学习时报; Xuexi Qiangguo 学习强国; Beijing Daily 京报网; CCTV English; CCTV News 央视新闻; CCTV programmes incl. Xinwen Lianbo 新闻联播; CGTN; China Daily (English); China Daily Chinese 中国日报网; China News Service English (ecns.cn); China News Service 中国新闻网; China Radio International 国际在线; China Youth Net 中国青年网; China.org.cn 中国网; Economic Daily / China Economic Net 中国经济网; Global Times Chinese / Huanqiu 环球网; Global Times (English); Guancha 观察者网; Guangming Daily 光明网; Kankan News 看看新闻; Oeeee / Southern Metropolis Daily 奥一网 南都; People's Daily English; People's Daily 人民网; People's Daily print edition 人民日报; PLA Daily / China Military Online 中国军网; Shanghai Observer 上观新闻; Shine / Shanghai Daily; Sixth Tone; Southern Net 南方网; Southern Weekly 南方周末; Ta Kung Pao 大公報; The Paper 澎湃新闻; Wen Wei Po 文匯報; Workers' Daily 中工网; Xinhua English; Xinhua 新华网; China National Radio 央广网; China Youth Daily 中国青年报; CQNews 华龙网; Dazhong Daily 大众日报; Economic Observer 经济观察报; Guangzhou Daily 广州日报; Legal Daily 法治日报; Red Star News 红星新闻; Reference News 参考消息; TechNode 动点科技; Yangcheng Evening News 羊城晚报; Yangzi Evening News 扬子晚报; Beijing News 新京报; People's Daily app 人民日报客户端; People's Daily+ 人民网+; Shenzhen News Net 深圳新闻网; Xinhua Daily 新华日报
- **Party-gov:** CAC 网信办; CCDI 中央纪委国家监委; gov.cn English; gov.cn 中国政府网; MFA press conference 外交部例行记者会; MFA Spokesperson's Remarks (English); Ministry of National Defense 国防部; Party History & Literature Institute 中央党史和文献研究院; Taiwan Affairs Office 国台办
- **Overseas independent:** BBC News Chinese; Central News Agency Taiwan 中央社; China Times 中時新聞網; ChinaFile; DW Chinese 德国之声; FT Chinese FT中文网; HK01 香港01; Hong Kong Free Press; Initium Media 端传媒; Lianhe Zaobao 联合早报; Liberty Times 自由時報; Matters 馬特市; Ming Pao (via Google News); NYT Chinese 纽约时报中文网; on.cc 東網; Pekingnology; RFA Mandarin 自由亚洲电台; RFI Chinese 法广; SCMP; Sing Tao Headline 星島頭條; Sinocism; Storm Media 風傳媒; The News Lens 關鍵評論網; The Reporter 報導者; The Witness 法庭線; United Daily News 聯合新聞網; Up Media 上報; VOA Chinese 美国之音; 8world News 8视界; ACB News 澳华财经在线; Asian Pacific Post; Business Next 數位時代; Chinese Commercial News 菲律賓商報; European Times 欧洲时报; Focus Taiwan; Guang Ming Daily 光明日报 (MY); HKET (via Google News); International Daily News 国际日报 (Indonesia); Jing Daily; Nanyang Siang Pau 南洋商报; NZ Chinese Herald 新西兰中文先驱报; Oriental Daily News Malaysia 东方日报; Sampan 舢舨; Seattle Chinese Times 西城時報; Sin Chew (via Google News); Sing Tao Daily Canada; Sing Tao Daily Europe; Sing Tao Daily USA; Taipei Times; The Standard (HK); The Star (Malaysia); World Journal 世界日報; China Press 中国报 (MY); Sydney Today 今日悉尼
- **Dissident:** Aboluowang 阿波罗新闻网; Bannedbook 禁闻网; ChinaAid 对华援助协会; Epoch Times Chinese 大纪元; Kanzhongguo / Secret China 看中国; Mingjing News 明鏡網; NTD 新唐人電視台; Sound of Hope 希望之声; NFSC network outlets (GETTR accounts, G·HOT reports, Telegram)
- **Censorship tracker:** CDT 404 Archive 404文库; China Digital Space 中国数字空间; China Digital Times 中国数字时代; China Digital Times English; China Media Project; Citizen Lab; FreeWeChat 自由微信; GreatFire.org; OONI; Weibo trending history (GitHub, bhwa233); Weibo trending history (GitHub, justjavac)
- **Commercial platform:** Eastmoney 东方财富; plus the hot lists above
- **Channels:** up to 34 YouTube and 10 Telegram channels, one currently paused (not in the news-source count)

Not included in v1: Sogou WeChat search, Tianshannet, Canyu, The Chinese Weekly, What's on Weibo, Chongqing Daily, Xiaohongshu, and sites that block logged-out readers.

#### Output

- **Dataset:**
  - One row per feed item: `record_type: "item"`, with a compact `censorship` block if the item was flagged.
  - One row per flag: `record_type: "censorship_flag"`.
  - Views: **Flagged stories** (Censored and Likely censored), **English feed**, **Chinese feed**.
- **Key-value store:** `FEED_ZH_JSON`, `FEED_EN_JSON`, `TOPICS_JSON` (clusters), `CENSORED_JSON`, `SOURCE_STATUS_JSON`, `TOP15_EN_MD`, `TOP15_EN_HTML`.

##### Output fields: feed items

| Field | What it is | When present |
|---|---|---|
| `record_type` | `item` for news and hot-list rows | always |
| `id` | Stable item id | always |
| `topic_id` | Story cluster this item belongs to | when clustered |
| `kind` | Row kind (news article, hot-list entry, Q\&A) | always |
| `source_id`, `source_name` | Which source the row came from | always |
| `source_type` | Outlet type | always |
| `outlet`, `outlet_homepage` | Outlet name and homepage | always |
| `label_en`, `label_zh`, `label_display`, `display_en`, `display_zh`, `label_note` | Outlet label text. Describes the outlet, not whether a story is true | always |
| `ownership_checked` | Whether the outlet's ownership label was checked | always |
| `themes` | Theme tags for the item | when tagged |
| `url` | Link to the original page | always |
| `published` | Publish time (UTC) | always |
| `published_estimated`, `published_source` | `published` is estimated, and where the date came from: `url`, `page`, `first_seen`, `url_path` (a date in the link's path), `html_attr` (a date in a page attribute) or `cover` (older name for a cover-image path). An estimated date is not the row's age; the row ages from when we first saw it. | when the page has no publish time |
| `fetched_at` | When we fetched it | always |
| `via` | Third-party copy or feed the row came through, e.g. `Google News`, `anyknew.com` | those rows only |
| `headline_en` | English headline (an empty string until the row is translated) | when translated |
| `headline_original`, `original_language` | Original headline and its language | always |
| `title_zh`, `excerpt_zh` | Chinese title and excerpt | Chinese-language rows |
| `excerpt_en`, `summary_en` | English excerpt and summary | when available |
| `quotes` | Quotes kept verbatim, with attribution | when the item has quotes |
| `translation`, `translation_status`, `translation_model`, `translation_label`, `translation_check`, `translation_failed` | Machine translation and its quality check | `translation` on every row (`none` for English-language sources); the rest on Chinese-language rows |
| `censorship` | Short deletion status block or null | hot-list rows |
| `rank`, `heat`, `peak_rank` | Current rank, heat and best rank on the hot list | hot-list rows |
| `first_seen`, `snapshots_seen` | First time on the list and how many snapshots saw it | hot-list rows |
| `speaker`, `format` | Speaker and format for press-conference Q\&A | Q\&A rows |
| `network`, `repost` | NFSC network label and GETTR repost marker | NFSC rows only |
| `wechat_url` | Original WeChat article link, as listed by China Digital Times. We don't open this link, and the article may no longer be available. | CDT 404 rows about WeChat articles |
| `wechat_account` | WeChat account name, as given in China Digital Times' 404 archive title. Empty when CDT doesn't name one. | CDT 404 rows about WeChat articles |
| `fetch` | How this row is refreshed: `scheduled` (the default, on each run) or `hourly` | always |
| `week_end` | The week-end date G·HOT's weekly report gives, as the report writes it. It is not when the row stops showing or billing. | G·HOT weekly rows only |

##### Output fields: deletion flags (`record_type: "censorship_flag"`, also in `CENSORED_JSON`)

| Field | What it is |
|---|---|
| `item_id`, `list`, `title`, `title_en`, `url` | The hot-list entry that went missing, and which list |
| `tier`, `label`, `label_zh`, `status`, `provisional` | Censored, Likely censored or Returned, and whether the call is still provisional |
| `censored_at` | Last time seen and first time missing (UTC and ET). On Zhihu flags this is **dropped from list at** |
| `confirmed_gone_at` | Still missing as of: roughly the latest snapshot where the item was still absent. Empty for returned items. It is not a confirmation; proof, when we have it, is in `evidence` and `status` |
| `first_seen_at`, `last_seen_at`, `first_seen_et`, `last_seen_et` | Time window on the list |
| `time_on_list` | Minutes and snapshots on the list (a lower bound) |
| `evidence_status` | Only on flags whose evidence check is still running. `not_checked_yet` means the check hasn't reached that flag yet, not "no deletion found". Finished flags don't carry it. |
| `peak_rank`, `peak_heat`, `rank_trail` | Best rank, heat, and the rank path ending where it left the list |
| `evidence`, `url_check`, `cdt_hits` | The evidence for the status: page check (`url_check` is `inconclusive` when a login wall or block stops the check) and China Digital Times matches, including when the entry was first missing and when we last checked its page (UTC). |
| `evidence` text "still on <list>: <title>" | The same story was still showing on another public list when it went missing from this one |
| `impact.co_dropped_terms` ("Dropped at the same time") | Other entries that went missing from the same list in the same snapshot |
| `returned_at`, `returned_rank` | When and where it came back, if it did |
| `platforms_affected`, `survived_on` | Other lists it vanished from or stayed on |
| `impact`, `why`, `official_line`, `official_line_zh` | Short context notes |

`TOPICS_JSON` (sorted by `rank`): `rank`, `topic_id`, `label_en`, `label_zh`, `summary_en`, `n_items`, `items`, `members`, `source_types`, `groups_covering`, `distinct_sources`, `buckets`, `censored`, `censorship_status`, `censorship_flags`, `watch_terms`.

**Sample censorship flag** (EXAMPLE DATA: invented values for illustration, not a real story):

```json
{
  "record_type": "censorship_flag",
  "status": "censored",
  "tier": "high",
  "label": "Censored",
  "label_zh": "【已被审查】",
  "provisional": true,
  "list": "weibo",
  "title": "【示例】某地突发事件",
  "title_en": "[Example] Sudden incident in a city",
  "censored_at": {
    "last_seen": "2026-10-12T06:40:05Z", "last_seen_et": "2026-10-12 02:40 ET",
    "first_missing": "2026-10-12T06:45:11Z", "first_missing_et": "2026-10-12 02:45 ET"
  },
  "confirmed_gone_at": "2026-10-12T07:46:30Z",
  "time_on_list": {"minutes": 95, "snapshots": 19, "note": "lower bound: counted from our first snapshot"},
  "peak_rank": 3,
  "peak_heat": 1250000,
  "evidence": [
    {"check": "rank_history", "ts": "2026-10-12T06:45:11Z", "signal": "abrupt_drop_while_hot",
     "result": "left weibo at #4 (peak #3), heat near peak", "url": null},
    {"check": "url_recheck_1h", "ts": "2026-10-12T07:46:30Z", "signal": "censor_notice",
     "result": "根据相关法律法规", "url": "<topic search URL>"}
  ],
  "platforms_affected": ["weibo"],
  "survived_on": [{"where": "baidu", "type": "platform", "title": "【示例】…", "url": null}],
  "why": null,
  "official_line": "No official comment found",
  "official_line_zh": "未找到官方回应"
}
```

**Sample English feed item** (EXAMPLE DATA):

```json
{
  "record_type": "item",
  "topic_id": "c0012",
  "kind": "news",
  "source_type": "Overseas independent",
  "source_name": "BBC News Chinese",
  "outlet": "BBC News Chinese",
  "label_display": "BBC News Chinese (Overseas independent)",
  "headline_en": "[Example] Headline in English",
  "headline_original": "【示例】中文标题",
  "excerpt_en": "(up to 30 words, machine-translated)",
  "summary_en": "(generated by the Actor, not source text)",
  "quotes": [{"text": "(verbatim, original language)", "speaker": "…", "role": "…", "outlet": "…"}],
  "translation_status": "ok",
  "url": "<original article URL>",
  "published": "2026-10-12T02:20:26Z",
  "censorship": null
}
```

#### English feed: how it's written

- Headlines and excerpts are **machine-translated**, with automatic checks on numbers and dates. Names and slang can still come out wrong, so check against `headline_original`. Not every row gets English: rows outside the daily translation budget are marked `translation_status: translation_pending` and keep only the Chinese. `translation_status` is `ok` when translated, `translation_pending` when not yet translated (`translation_label`: "Translation pending; original shown"), and `failed` when the generated English summary came out garbled and was withheld (`translation_failed: true`; the English headline is still shown). Rows from English-language sources have `translation: "none"` and no `translation_status`.
- **Quotes stay verbatim** in the original language, attributed to speaker, role and outlet. They ship only after a fact check. Everything else is rephrased, and no facts are added.
- Summaries are generated by the Actor and never copy article text.

#### Use cases

- **Censorship research:** a timestamped record of topics that disappeared from hot lists, with the URL rechecks and tracker cross-references behind each flag.
- **China desks and newsrooms:** a lead sheet of hot-list topics that disappeared overnight, each with its evidence, the state-media line and where the story survived.
- **Analysts and risk teams:** compare state vs overseas framing of the same story in one cluster.
- **AI/LLM builders:** a structured, labeled Chinese/English feed with source types, for RAG grounding, evals, or a censorship-aware news tool via the Apify API or MCP.

#### Input (main fields)

| Field | What it does |
|---|---|
| `hotLists` | Lists to include: `weibo`, `baidu`, `zhihu`, `toutiao`, `bilibili`. Controls hot-list and deletion rows on its own, whatever `sourceTypes` is set to. `douyin` (on by default) adds Douyin hot-list rows, credited "Douyin (via anyknew.com)", with no deletion watch; they count as Commercial platform under `sourceTypes` |
| `newsSources` | `"all"` (default) or a list of source ids |
| `sourceTypes` | News items only (hot lists are set by `hotLists`). Only news credited to these types: `State media`, `Party-gov`, `Commercial platform`, `Overseas independent`, `Dissident`, `Censorship tracker`. Default: all. Rows you filter out aren't charged. Narrower selections also run faster: we fetch only those sources, then match them against a shared record we rebuild regularly from every source, so deletion evidence, statuses, story clusters and overseas pickup are the same whatever you filter here |
| `maxItems` | Caps how many new items one run returns and bills; anything over the cap carries to your next run. Leave it empty for no limit |
| `snapshotCount` | Use 1 with a schedule; higher values poll repeatedly in one run |
| `snapshotIntervalMinutes` | Minutes between in-run snapshots |
| `highRank` | Rank threshold for a "dropped while hot" candidate (default 15) |
| `recheckUrls` | Recheck vanished topics' URLs (default on) |
| `useApifyProxy` | Off by default |

##### Other settings

Most buyers can leave these at their defaults.

- **Emit only new rows** (`emitOnlyNew`, default on): each run returns only rows that are new since your last run, so you only pay for new rows. A deletion flag comes back again when its status changes, for example from Likely censored to Censored, or to Returned. Turn it off to get a full snapshot. Every row in a full snapshot is billed, including ones you got before.
- **Max items per news source** (`maxItemsPerSource`, default 30, 1 to 100): the most news items kept from any one source in a run. Lower it for a lighter, more balanced feed. It applies to NFSC network rows (GETTR and the mirrors) too. A few app-only sources, such as the People's Daily app, aren't capped by it.
- **Include hot-list items up to rank** (`maxHotRank`, default 50, 5 to 50): hot-list rows ranked below this are left out. Set it to 10 or 20 if you only want the top of each list.

#### Pricing

Pay per event:

- **$8.00 per 1,000 new items (billed per event).** No start fee. Apify platform usage is included, so there's no separate compute charge.

**Example run:** with `maxItems` at 200, a run costs at most 200 items at $8 per 1,000, which is $1.60. How many items a run returns varies by source and by how long it has been since your last run. Narrower `sourceTypes` or `hotLists` settings return fewer items, and `maxItems` caps a run's bill.

You only pay for new rows. A row is billed once. A story cluster is billed when it first appears. A hot-list topic is billed once per platform, even if its rank changes. A run with nothing new returns no billable items. Now and then a source lists the same article again, for example when a search page re-indexes it. When that happens, the item can bill one more time, at most once every 30 days.

#### Limits: what this Actor does not do

- **Platforms curate their hot lists,** so a topic can leave for commercial or editorial reasons. That's why only hard evidence earns **Censored**, every flag shows its evidence, and `returned` stays visible.
- **Logged-out URL rechecks are often inconclusive.** Weibo search needs a login, so many disappearances can't be confirmed and stay at **Likely censored**.
- **Zhihu is checked hourly,** so not every removal is caught, and a Zhihu flag can arrive up to a day after the question leaves the list.
- **Kuaishou and Douyin are hot-list rows only,** with no deletion watch.
- **Some outlets block logged-out requests** and are **not bypassed**: Wenxuecity, US China Press and others. They appear in `SOURCE_STATUS_JSON` with the reason.
- **Ming Pao, HKET and Sin Chew arrive through Google News,** so we may miss stories Google News doesn't surface, and deletion watch doesn't cover them.
- **Most JavaScript-only sites aren't covered yet.** A few, such as the People's Daily app, are fetched for you ahead of time and may be missing from a run when shared data is unavailable.
- **No Xiaohongshu in v1, and no WeChat collection of our own.** The only WeChat-related rows are deleted WeChat articles collected by China Digital Times. There's also no mainland-IP view: we see what a logged-out visitor outside the mainland sees.
- **We don't promise unbroken coverage.** When we miss snapshots, for example during maintenance, items that drop off in that window aren't marked Censored or Likely censored. Sources can fail on a given run; `SOURCE_STATUS_JSON` shows which.
- `time_on_list` is a lower bound: it starts at our first snapshot.
- **Story matching leans toward caution.** We only group items when the evidence that they cover the same event is strong, so very short hot-list titles, and English-language coverage of a Chinese-language story, are sometimes left ungrouped. `survived_on` can therefore miss some pickups, especially by English-language outlets.
- **If part of our shared data can't be reached,** the run's status message reads: "Some sources, story matching and English translations are temporarily unavailable in this run."

#### Ethics and responsible use

- **Public, logged-out pages only.** No accounts, no login-wall bypass, **no paywall bypass**.
- **No personal data:** no usernames, user IDs, profile URLs, comments or media files. Cross-checks store aggregate counts only. Names of private individuals in channel posts are replaced with `[redacted-name]`.
- Short excerpts with links back to the source; request rates are kept low.
- A "Censored" label is a documented, evidence-based judgment about a hot-list topic, not a claim about any person. Read the evidence before you publish.

#### FAQ

- **Why "Likely censored" rather than "Censored"?** Because we don't have a 404, a 根据相关法律法规 notice or a dated CDT entry yet. If hard evidence arrives and the topic is still gone at 1 hour, it moves up to Censored.
- **Can a Censored item change?** Yes. It stays `provisional` until the 24-hour recheck. If the topic comes back, its status becomes `returned`.
- **How often should I run it?** As often as you want new rows. Deletion watch runs on our side, so your schedule decides when new items and flags reach you, not which topics get flagged. A run takes a few minutes.
- **Why does a source show `ok: false` but still have rows?** `ok: false` means its latest fetch failed. Collector sources keep showing their last good rows until each is 48 hours old.

# Actor input Schema

## `hotLists` (type: `array`):

Public trending lists fetched logged-out. The default is every list. A list you leave out is not fetched, and its hot-list rows and deletion flags are not pushed or billed. An empty selection includes none.

## `sourceTypes` (type: `array`):

Which news rows to push and bill, by the type each row is credited to after aggregator handling. When a cluster_context record from the last 2 hours is available and this selection is narrower than every type, only sources of the selected types are fetched. If that record is missing, stale, or unusable, or this selection is every type, every approved news source is fetched. Hot lists follow hotLists. Evidence, clusters, and overseas pickup stay the same whatever you select here, using the stored context when the fetch is narrowed. The default is every type, including Commercial platform, and does not drop rows. Leaving the field unset does the same. A Commercial platform news row ships when you select that type and is left out when you select other types only. Douyin mirror rows also require douyin in hotLists; that list is in the default, so a default run still ships them, and leaving douyin out drops them even when Commercial platform is selected. Aggregator items are credited to the original outlet's type or dropped, and a credited row is kept only when that type is selected. A news row of an unselected type is not pushed and is not remembered. An empty list selects no news types.

## `newsSources` (type: `array`):

"all" (default) = every approved outlet that can be read logged-out (about 110). Or list source ids from data/sources/news_notion.json, e.g. mfa, xinhua, bbc.

## `snapshotCount` (type: `integer`):

Use 1 with a schedule (every 5-10 min). Higher values keep one run alive and poll repeatedly.

## `emitOnlyNew` (type: `boolean`):

Push only dataset rows that are new since the last run. A deletion flag is pushed again when its status changes (for example likely censored to censored, or to returned). Turn off to push a full snapshot. Apify bills each pushed dataset row.

## `snapshotIntervalMinutes` (type: `integer`):

Minutes to wait between extra snapshots when snapshotCount is greater than 1.

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

Optional cap on the total number of billed rows this run. Leave empty for no limit.

## `maxItemsPerSource` (type: `integer`):

Maximum number of news items kept from each source in one run.

## `maxHotRank` (type: `integer`):

Hot-list rows ranked worse than this are left out of the feed.

## `highRank` (type: `integer`):

A topic that vanishes at or above this rank (or while rising) is flagged.

## `recheckUrls` (type: `boolean`):

Kept for compatibility. URL rechecks run on our side, not in this actor. The actor joins the stored result for each flag. A flag with no stored result stays pending.

## `freeweiboCheck` (type: `boolean`):

Kept for compatibility. FreeWeibo lookups run on our side, not in this actor. The actor joins stored aggregate counts. A flag with no stored result leaves freeweibo empty. Post text is not stored.

## `topN` (type: `integer`):

How many topics to include in the readable top-stories report.

## `clusterBudgetSeconds` (type: `integer`):

Maximum seconds spent clustering items in one run. If this runs out, items not yet assigned are left as their own clusters, a warning is logged, and the run continues. The default is 120 seconds.

## `sourceRoutes` (type: `object`):

Optional overrides of catalog ingest.route. Each value is direct or sidecar. China Press and Sydney Today default to sidecar: the poller fetches them on the box and this actor reads the store. Set a source to direct to use its actor fetcher instead. An empty object keeps the catalog route.

## `includeNfsc` (type: `boolean`):

When true (the default), the nine NFSC Dissident rows in the public sidecar record are merged into the dataset. Set false to leave them out without a new build. Telegram and YouTube NFSC rows still follow the channel redaction gate and stay internal until that sign-off.

## `useApifyProxy` (type: `boolean`):

Most sources work without a proxy. Enable if lists start rate-limiting.

## `proxyGroups` (type: `array`):

e.g. RESIDENTIAL. Leave empty for the default datacenter pool.

## `sidecarStoreId` (type: `string`):

Optional. Overrides the SIDECAR_STORE_ID environment variable. Not shown to buyers.

## `historyStore` (type: `string`):

Internal testing only. Owner runs upload trimmed history here. Buyer runs do not open this store. Leave as default.

## `simulateBuyer` (type: `boolean`):

Internal testing only. When true, this run skips china-feed-history and uses an in-run temp file, the same as a buyer, even on the owner's account. It cannot turn history on.

## `apifyRetentionDays` (type: `integer`):

Internal testing only. Days of timestamped rows kept in Apify on each upload. The default is 7. The APIFY_RETENTION_DAYS environment variable overrides this.

## `contextKey` (type: `string`):

Internal testing only. Leave as default; changing it disables cross-run clustering.

## Actor input object example

```json
{
  "hotLists": [
    "weibo",
    "baidu",
    "zhihu",
    "toutiao",
    "bilibili",
    "douyin",
    "kuaishou"
  ],
  "sourceTypes": [
    "State media",
    "Party-gov",
    "Commercial platform",
    "Overseas independent",
    "Dissident",
    "Censorship tracker"
  ],
  "newsSources": [
    "all"
  ],
  "snapshotCount": 1,
  "emitOnlyNew": true,
  "snapshotIntervalMinutes": 5,
  "maxItemsPerSource": 30,
  "maxHotRank": 50,
  "highRank": 15,
  "recheckUrls": true,
  "freeweiboCheck": true,
  "topN": 15,
  "clusterBudgetSeconds": 120,
  "sourceRoutes": {},
  "includeNfsc": true,
  "useApifyProxy": false,
  "historyStore": "china-feed-history",
  "simulateBuyer": false,
  "apifyRetentionDays": 7,
  "contextKey": "cluster_context"
}
```

# Actor output Schema

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

Every row from this run: news items, hot-list items and deletion flags.

## `censored` (type: `string`):

Deletion-watch flags only, each with its status (Censored, Likely censored or Returned) and the evidence behind it.

## `feedEn` (type: `string`):

News rows with English headlines and short summaries, machine-translated. Rows not yet translated are marked translation_pending.

## `feedZh` (type: `string`):

News rows in the original Chinese, each labeled by outlet type.

## `topics` (type: `string`):

Story clusters: the same story grouped across state, commercial, overseas and dissident outlets.

## `sourceStatus` (type: `string`):

Every source with its status for this run, the number of items it returned, and the error for any that failed.

## `top15` (type: `string`):

The run's top 15 stories as an English HTML report, with original-language headlines and quotes. A Markdown copy is also saved.

# 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("china.unofficial/china-news-feed").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("china.unofficial/china-news-feed").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 china.unofficial/china-news-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,china.unofficial/china-news-feed"
        }
    }
}
```

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/CeTIPfpcWcDrEhrPV/builds/0cuRbA7UWJyDbbBP0/openapi.json
