jackwener/OpenCLI · error · AuthRequiredError

Zhihu /api/v4/me returned HTTP ${status} — anonymous

Error message

Zhihu /api/v4/me returned HTTP ${status} — anonymous

What it means

After the whoami script runs, if the response carries __httpError with status 401 or 403, the library concludes the session is anonymous and throws AuthRequiredError. Zhihu's /api/v4/me rejects unauthenticated requests with these statuses, so this is an authentication failure, not a code bug.

Source

Thrown at clis/zhihu/auth.js:32

  await page.wait(2);
  const data = await page.evaluate(`
    (async () => {
      try {
        const r = await fetch('https://www.zhihu.com/api/v4/me?include=url_token', { credentials: 'include' });
        if (!r.ok) return { __httpError: r.status };
        return await r.json();
      } catch (e) {
        return { __exception: String(e && e.message || e) };
      }
    })()
  `);
  if (data?.__exception) {
    throw new CommandExecutionError(`Zhihu whoami failed: ${data.__exception}`);
  }
  if (!data || data.__httpError) {
    const status = data?.__httpError;
    if (status === 401 || status === 403) {
      throw new AuthRequiredError('www.zhihu.com', `Zhihu /api/v4/me returned HTTP ${status} — anonymous`);
    }
    throw new CommandExecutionError(`Zhihu identity probe failed (HTTP ${status ?? 'unknown'})`);
  }
  if (!data.url_token) {
    throw new AuthRequiredError('www.zhihu.com', 'Zhihu /api/v4/me returned no url_token — anonymous session');
  }
  return {
    url_token: String(data.url_token),
    name: String(data.name ?? ''),
    uid: String(data.uid ?? data.id ?? ''),
  };
}

registerSiteAuthCommands({
  site: 'zhihu',
  domain: 'www.zhihu.com',
  loginUrl: 'https://www.zhihu.com/signin',
  columns: ['url_token', 'name', 'uid'],

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-login: run `opencli zhihu login` and complete sign-in to obtain a fresh z_c0 cookie.
  2. Clear old cookies in the automation profile before re-login to avoid reusing the stale token.
  3. If sessions keep dying, check whether something logs you out (shared profile used concurrently by multiple automation runs).
  4. Catch AuthRequiredError and route the user to the login flow.

Example fix

// before
await runZhihuCommand(); // AuthRequiredError: /api/v4/me returned HTTP 401 — anonymous
// after
if (!(await isZhihuLoggedIn(page))) {
  await zhihuLogin(); // refresh z_c0
}
await runZhihuCommand();
Defensive patterns

Strategy: try-catch

Validate before calling

const cookies = await page.getCookies({ url: 'https://www.zhihu.com' });
if (!cookies.some(c => c.name === 'z_c0' && c.value)) await runZhihuLogin(); // refresh possibly-stale cookie proactively

Type guard

function isAuthError(e) { return /HTTP (401|403)/.test(String(e.message)); }

Try / catch

try { const me = await verifyZhihuIdentity(page); } catch (e) { if (/HTTP (401|403)/.test(e.message)) { await zhihuLogin(); return verifyZhihuIdentity(page); } throw e; }

Prevention

When it happens

Trigger: A z_c0 cookie exists (so the earlier cookie check passed) but it is expired/invalid, so /api/v4/me returns HTTP 401 or 403 during verifyZhihuIdentity.

Common situations: Stale z_c0 cookie after Zhihu invalidated the session (password change, session revocation, long inactivity); copying a cookie from another browser that has since expired; logged out on another device invalidating the token.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/7cd817fe0fd2080c. Report an issue: GitHub.