DIYgod/RSSHub · error
zhihu: JSDOM did not provide document.cookie accessors
Error message
zhihu: JSDOM did not provide document.cookie accessors
What it means
Thrown when the JSDOM environment constructed to execute Zhihu's challenge script does not expose `document.cookie` getter/setter accessors on `Document.prototype`. The generator needs to intercept `document.cookie` writes to capture the `__zse_ck` token the script sets, so if JSDOM's cookie descriptor is missing or non-functional, it closes the window and aborts.
Source
Thrown at lib/routes/zhihu/utils.ts:157
runScripts: 'outside-only',
pretendToBeVisual: true,
virtualConsole: new VirtualConsole(),
});
const { window } = dom;
Object.defineProperties(window.navigator, {
userAgent: { value: ua, configurable: true },
webdriver: { value: false, configurable: true },
});
window.TextEncoder = TextEncoder;
window.TextDecoder = TextDecoder as typeof window.TextDecoder;
window.atob = (value: string) => Buffer.from(value, 'base64').toString('binary');
window.btoa = (value: string) => Buffer.from(value, 'binary').toString('base64');
Object.assign(window, { __g: {} });
const cookieDescriptor = Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie');
if (!cookieDescriptor?.get || !cookieDescriptor.set) {
window.close();
throw new Error('zhihu: JSDOM did not provide document.cookie accessors');
}
const tokenPromise = new Promise<string>((resolve) => {
Object.defineProperty(window.document, 'cookie', {
configurable: true,
get: cookieDescriptor.get,
set(value: string) {
Reflect.apply(cookieDescriptor.set!, window.document, [value]);
const token = value.match(/__zse_ck=([^;]+)/)?.[1];
if (token?.includes('-')) {
resolve(token);
}
},
});
});
let zseCk: string | undefined;
try {
// Zhihu's challenge is intentionally delivered as executable JavaScript.View on GitHub (pinned to bed535e087)
Solutions
- Pin or upgrade `jsdom` to a version known to expose a functional `document.cookie` accessor on `Document.prototype` (check the version currently working in RSSHub's lockfile).
- Ensure the JSDOM instance is constructed with a real `url` and `runScripts: 'outside-only'` so cookie APIs are initialized.
- If the new JSDOM defines `cookie` elsewhere (e.g. on `window.document` directly rather than the prototype), adjust the descriptor lookup target accordingly.
Example fix
// before
const cookieDescriptor = Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie');
if (!cookieDescriptor?.get || !cookieDescriptor.set) {
window.close();
throw new Error('zhihu: JSDOM did not provide document.cookie accessors');
}
// after — fall back to the instance if the prototype has no descriptor
const cookieDescriptor =
Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie') ??
Object.getOwnPropertyDescriptor(window.document, 'cookie');
if (!cookieDescriptor?.get || !cookieDescriptor.set) {
window.close();
throw new Error('zhihu: JSDOM did not provide document.cookie accessors');
} Defensive patterns
Strategy: fallback
Validate before calling
// Verify JSDOM exposes cookie accessors before relying on the VM challenge
import { JSDOM } from 'jsdom';
function jsdomSupportsCookieAccessor() {
const dom = new JSDOM('<!doctype html><html></html>', { url: 'https://example.com/' });
const d = Object.getOwnPropertyDescriptor(dom.window.Document.prototype, 'cookie');
dom.window.close();
return !!(d?.get && d.set);
} Try / catch
const cookieDescriptor = Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie')
?? Object.getOwnPropertyDescriptor(window.document, 'cookie');
if (!cookieDescriptor?.get || !cookieDescriptor.set) {
window.close();
// fall back to configured credentials instead of failing
if (configuredDc0) return { dc0: configuredDc0 };
throw new Error('zhihu: JSDOM did not provide document.cookie accessors');
} Prevention
- Pin the jsdom version that RSSHub's lockfile certifies; don't float the major.
- Add a unit test asserting JSDOM exposes a functional document.cookie accessor on the prototype.
- When upgrading jsdom, re-run the Zhihu challenge generation path in CI before shipping.
When it happens
Trigger: The installed `jsdom` version changed or removed its `document.cookie` property descriptor (different JSDOM major version, a stricter cookie config, or `Storage`/cookie access disabled), so `Object.getOwnPropertyDescriptor(window.Document.prototype, 'cookie')` returns undefined or an accessor-less descriptor.
Common situations: A dependency upgrade (jsdom) altered how `document.cookie` is defined; running under a runtime/Node version where JSDOM behaves differently; the `JSDOM` constructor options (e.g. `url`, `runScripts`) were changed in a way that disables cookie support.
Related errors
- zhihu: failed to obtain a guest d_c0 cookie
- zhihu: challenge page did not contain an URL to __zse_ck met
- zhihu: WASM VM did not produce a __zse_ck
- Baidu security verification required. The cookie may be expi
- message ?? code
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/5516d38b2a7ab9a0.
Report an issue: GitHub.