NanmiCoder/MediaCrawler · error

d_c0 not found in cookies

Error message

d_c0 not found in cookies

What it means

Bare Exception raised by ZhiHuClient._pre_headers when the d_c0 cookie is absent from the session cookie dict. d_c0 is zhihu's device credential; it is a required input to the x-zse-96/x-zst-81 request signing, so without it no signed API call can be built.

Source

Thrown at media_platform/zhihu/client.py:78

        self.timeout = timeout
        self.default_headers = headers
        self.cookie_urls = ["https://www.zhihu.com"]
        self.cookie_dict = cookie_dict
        self._extractor = ZhihuExtractor()
        # Initialize proxy pool (from ProxyRefreshMixin)
        self.init_proxy_pool(proxy_ip_pool)

    async def _pre_headers(self, url: str) -> Dict:
        """
        Sign request headers
        Args:
            url: Request URL with query parameters
        Returns:

        """
        d_c0 = self.cookie_dict.get("d_c0")
        if not d_c0:
            raise Exception("d_c0 not found in cookies")
        sign_res = sign(url, self.default_headers["cookie"])
        headers = self.default_headers.copy()
        headers['x-zst-81'] = sign_res["x-zst-81"]
        headers['x-zse-96'] = sign_res["x-zse-96"]
        return headers

    @retry(stop=stop_after_attempt(3), wait=wait_fixed(1))
    async def request(self, method, url, **kwargs) -> Union[str, Any]:
        """
        Wrapper for httpx common request method with response handling
        Args:
            method: Request method
            url: Request URL
            **kwargs: Other request parameters such as headers, body, etc.

        Returns:

        """

View on GitHub (pinned to d6f7c5bb90)

Solutions

  1. Visit zhihu.com in a browser, confirm d_c0 exists in devtools Application > Cookies, and re-export the full cookie string into config.
  2. If login type is cookie, ensure the exported string includes d_c0=...; if using qrcode login, wait for the session to fully establish before crawling.
  3. Log the cookie_dict keys (names only) before crawling to verify d_c0 was parsed.

Example fix

// before
data = await zhihu_client.get(uri, params=params)
// after
if "d_c0" not in zhihu_client.cookie_dict:
    raise RuntimeError("zhihu cookie missing d_c0 - re-export cookie")
data = await zhihu_client.get(uri, params=params)
Defensive patterns

Strategy: validation

Validate before calling

def cookie_dict_has_d_c0(cookie_dict: dict) -> bool:
    return bool(cookie_dict.get("d_c0"))

Type guard

def has_d_c0(cookie_dict: dict) -> bool:
    return isinstance(cookie_dict, dict) and isinstance(cookie_dict.get("d_c0"), str) and len(cookie_dict["d_c0"]) > 0

Try / catch

try:
    data = await zhihu_client.get(uri, params=params)
except Exception as e:
    if "d_c0" in str(e):
        raise RuntimeError("zhihu cookie lacks d_c0 - re-export full cookie from browser") from e
    raise

Prevention

When it happens

Trigger: Calling any signed zhihu request (get/post wrappers) after login cookies were loaded but no d_c0 value was present - e.g. cookie string exported before visiting zhihu, a cookie from a logged-out session, or a truncated/malformed ZHIHU_COOKIES config value.

Common situations: Cookie string pasted incompletely so the d_c0 entry got cut off; using a fresh browser profile where zhihu never set d_c0; cookie parsed with the wrong key separator so cookie_dict keys are wrong.

Related errors


AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15). Data as JSON: /api/errors/b35342a63a504099. Report an issue: GitHub.