jackwener/OpenCLI · error · CommandExecutionError

Zhihu risk control blocked answer ${target.answerId} (40362)

Error message

Zhihu risk control blocked answer ${target.answerId} (40362): ${data.errorMessage || 'abnormal request'}

What it means

Zhihu's anti-scraping risk control rejected the request to fetch an answer, returning errorCode 40362 ('abnormal request'). The Zhihu CLI's extractAnswer (via the Browser Bridge) detects this code and throws a CommandExecutionError instead of returning partial data. It signals Zhihu flagged the traffic or session as suspicious, not a bug in the CLI.

Source

Thrown at clis/zhihu/download-helpers.js:209

          author: typeof payload.author?.name === 'string' ? payload.author.name : '',
          createdTime: payload.created_time,
          ...normalized
        } };
      })()
    `).catch((error) => {
        throw new CommandExecutionError(
            `Zhihu answer download request failed: ${error instanceof Error ? error.message : String(error)}`,
            'Try again later or rerun with -v for more detail.',
        );
    });

    const data = unwrapEvaluateResult(raw);
    if (!data || typeof data !== 'object' || Array.isArray(data)) {
        throw new CommandExecutionError('Zhihu answer download returned a malformed Browser Bridge payload');
    }
    const status = data.status;
    if (String(data.errorCode) === '40362') {
        throw new CommandExecutionError(
            `Zhihu risk control blocked answer ${target.answerId} (40362): ${data.errorMessage || 'abnormal request'}`,
            'Open the answer in the connected Chrome profile and retry later.',
        );
    }
    if (status === 401 || status === 403 || String(data.errorCode) === '40353' || data.needLogin) {
        throw new AuthRequiredError('www.zhihu.com', 'Failed to download Zhihu answer');
    }
    if (status === 404) {
        throw new EmptyResultError('zhihu download', `No Zhihu answer was found for ${target.answerId}.`);
    }
    if (status || data.fetchError) {
        throw new CommandExecutionError(
            status ? `Zhihu answer download request failed (HTTP ${status})` : 'Zhihu answer download request failed',
            String(data.fetchError || data.errorMessage || 'Try again later or rerun with -v for more detail.'),
        );
    }
    if (data.malformed || data.errorCode || data.errorMessage) {
        throw new CommandExecutionError('Zhihu answer download returned a malformed or error payload');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open the target answer URL in the connected Chrome profile manually to prove the session is human, then retry the download later
  2. Log into www.zhihu.com in the connected Chrome profile so requests carry authenticated cookies
  3. Reduce request rate: add delays between answer downloads and lower batch size
  4. Wait and retry — 40362 blocks are often temporary (minutes to hours)
  5. If it persists, switch IP / network or use a different Chrome profile

Example fix

// before: immediate retry loop on failure
await downloadAnswer(id);
// after: back off and verify session first
if (err instanceof CommandExecutionError && err.message.includes('40362')) {
  console.error('Open the answer in Chrome, log in, wait, then retry.');
  await sleep(60_000);
  await downloadAnswer(id);
}
Defensive patterns

Strategy: retry

Validate before calling

if (!target.answerId || typeof target.answerId !== 'string') throw new Error('Need a valid Zhihu answerId before download');
const answerUrl = `https://www.zhihu.com/question/x/answer/${target.answerId}`;
// verify the URL loads in the connected Chrome profile before batch-downloading

Type guard

function isRiskControlBlock(err) {
  return err instanceof Error && err.message.includes('40362');
}

Try / catch

try {
  const answer = await downloadAnswer(target);
} catch (err) {
  if (isRiskControlBlock(err)) {
    console.error('Blocked by Zhihu risk control. Open the answer in Chrome, log in, wait, then retry.');
    await sleep(60_000);
    return downloadAnswer(target); // bounded retries only
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling the Zhihu answer download flow (extractAnswer, invoked from the download/data command) when the in-page fetch returns { errorCode: '40362' } — i.e. Zhihu's server-side risk control rejected the request for that answerId.

Common situations: Scraping many answers in rapid succession from one account/IP; running headless or in a fresh Chrome profile with no browsing history or login; requesting answers during Zhihu risk-control sweeps; the answer being sensitive/removed and the fetch tripping anomaly detection.

Related errors


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