jackwener/OpenCLI · error · CliError

SECURITY_BLOCK

SECURITY_BLOCK

Error message

Xiaohongshu security block: the note detail page was blocked by risk control.

What it means

The in-page extraction script flagged data.securityBlock, meaning Xiaohongshu risk control blocked the note detail page (captcha or verification wall). The command throws CliError with code SECURITY_BLOCK and a hint that differs depending on whether the input was a URL or a bare ID.

Source

Thrown at clis/xiaohongshu/note.js:87

    domain: 'www.xiaohongshu.com',
    strategy: Strategy.COOKIE,
    navigateBefore: false,
    args: [
        { name: 'note-id', required: true, positional: true, help: 'Full Xiaohongshu note URL with xsec_token' },
    ],
    columns: ['field', 'value'],
    func: async (page, kwargs) => {
        const raw = String(kwargs['note-id']);
        const noteId = parseNoteId(raw);
        const url = buildNoteUrl(raw, { commandName: 'xiaohongshu note' });
        await page.goto(url);
        await page.wait({ time: 2 + Math.random() * 3 });
        const data = await page.evaluate(NOTE_EXTRACT_JS);
        if (!data || typeof data !== 'object') {
            throw new EmptyResultError('xiaohongshu/note', 'Unexpected evaluate response');
        }
        if (data.securityBlock) {
            throw new CliError('SECURITY_BLOCK', 'Xiaohongshu security block: the note detail page was blocked by risk control.', /^https?:\/\//.test(raw)
                ? 'The page may be temporarily restricted. Try again later or from a different session.'
                : 'Try using a full URL from search results (with xsec_token) instead of a bare note ID.');
        }
        if (data.loginWall) {
            throw new AuthRequiredError('www.xiaohongshu.com', 'Note content requires login');
        }
        if (data.notFound) {
            throw new EmptyResultError('xiaohongshu/note', `Note ${noteId} not found or unavailable — it may have been deleted or restricted`);
        }
        const d = data;
        // XHS renders placeholder text like "赞"/"收藏"/"评论" when count is 0;
        // normalize to '0' unless the value looks numeric.
        const numOrZero = (v) => /^\d+/.test(v) ? v : '0';
        // A note may legitimately have no title, but a real note page always
        // renders an author. If both are missing, the page failed to load.
        if (!d.title && !d.author) {
            throw new EmptyResultError('xiaohongshu/note', 'The note page loaded without visible content. The note may be deleted or restricted.');
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Wait and retry later — blocks are usually temporary.
  2. Switch to a full URL with a valid xsec_token from search results instead of a bare note ID.
  3. Use a different Chrome session/profile or network to change the fingerprint.
  4. Reduce request frequency and complete any captcha manually in the browser.

Example fix

// before
await note('65a1b2c3'); // bare ID, high risk-control score
// after
await note('https://www.xiaohongshu.com/explore/65a1b2c3?xsec_token=<fresh-token>');
Defensive patterns

Strategy: try-catch

Validate before calling

// Prefer full signed URLs over bare IDs to lower risk-control score
if (!/^https?:\/\//.test(raw)) console.warn('bare note ID increases security-block risk');

Type guard

function isSecurityBlockError(err) {
  return err instanceof CliError && err.code === 'SECURITY_BLOCK';
}

Try / catch

try {
  await note(raw);
} catch (err) {
  if (isSecurityBlockError(err)) {
    await sleep(60_000); // back off, then retry with a fresh signed URL
    return note(freshSignedUrl);
  } else throw err;
}

Prevention

When it happens

Trigger: page.evaluate(NOTE_EXTRACT_JS) returns { securityBlock: true } — XHS served a risk-control/verification page instead of note content.

Common situations: Too many automated requests from one session/IP; using bare note IDs which look suspicious to risk control; datacenter IP or unfamiliar browser fingerprint; expired xsec_token triggering verification.

Related errors


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