Skip to content

fix(route/zhihu): obtain __zse_ck from a browser session#22319

Open
DzmingLi wants to merge 2 commits into
DIYgod:masterfrom
DzmingLi:fix/zhihu-zse-ck-browser-refresh
Open

fix(route/zhihu): obtain __zse_ck from a browser session#22319
DzmingLi wants to merge 2 commits into
DIYgod:masterfrom
DzmingLi:fix/zhihu-zse-ck-browser-refresh

Conversation

@DzmingLi

@DzmingLi DzmingLi commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Involved Issue / 该 PR 相关 Issue

Close #20402

Example for the Proposed Route(s) / 路由地址示例

NOROUTE

New RSS Route Checklist / 新 RSS 路由检查表

  • New Route / 新的路由
  • Anti-bot or rate limit / 反爬/频率限制
    • If yes, do your code reflect this sign? / 如果有, 是否有对应的措施?
  • Date and time / 日期和时间
    • Parsed / 可以解析
    • Correct time zone / 时区正确
  • New package added / 添加了新的包
  • Puppeteer

Note / 说明

Two related fixes for Zhihu's tightened anti-crawler:

1. __zse_ck from a browser session. __zse_ck is generated at runtime by Zhihu's JS from the device fingerprint and d_c0, rotates every few days, and is cross-checked against d_c0 by the backend, so it has to come from a real browser session. This drives a headless browser, seeded with the configured cookies, to compute a fresh __zse_ck, harvests the cookie jar, and caches it for 30 minutes so it is refreshed automatically. getSignedHeader signs x-zse-96 with the same d_c0 that is sent.

Most content (column items, answers, activities) now also requires the z_c0 login cookie. Recommended config: ZHIHU_COOKIES=d_c0=...; z_c0=... (omit __zse_ck so it is refreshed automatically; a pinned __zse_ck is trusted as-is and will expire). A fully pinned d_c0 + __zse_ck pair is still honored, so no browser is needed in that case.

2. /zhihu/posts profile via API. The route scraped the user's HTML homepage (www.zhihu.com/people/:id) for the feed title/avatar; that page is now rate-limited (403) more aggressively than the API, breaking the route even though the article-list API works. It now reads the profile from /api/v4/members/:id instead.

Deployed and verified end-to-end: /zhihu/zhuanlan/<id>, /zhihu/people/activities/<id> and /zhihu/posts/people/<id> return 200 with full items; the harvested cookie is served from cache within the TTL (cold ~18s for the browser launch, warm ~2s).

Supersedes #21321.

`__zse_ck` is computed at runtime by Zhihu's JS from the device fingerprint
and `d_c0`, rotates every few days, and is cross-checked against `d_c0` by
the backend, so it has to come from a real browser session. Drive a browser
seeded with the configured cookies (including the `z_c0` login cookie that
most endpoints now require) to compute a fresh, consistent `__zse_ck`,
harvest the cookie jar, and cache it for 30 minutes so it is refreshed
automatically.

Recommended ZHIHU_COOKIES: "d_c0=...; z_c0=..." (omit `__zse_ck`).
The user's HTML homepage (www.zhihu.com/people/:id) is now rate-limited
(403) more aggressively than the API, which broke /zhihu/posts on the
profile fetch even though the article-list API works. Read the profile
(name, headline, avatar) from /api/v4/members/:id instead.
@github-actions

Copy link
Copy Markdown
Contributor

Auto Review

No clear rule violations found in the current diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

知乎路由又一次403

1 participant