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
- Wait and retry later — blocks are usually temporary.
- Switch to a full URL with a valid xsec_token from search results instead of a bare note ID.
- Use a different Chrome session/profile or network to change the fingerprint.
- 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
- Always use full URLs with xsec_token instead of bare note IDs.
- Throttle request rate; avoid rapid successive automation calls.
- Complete any captcha manually in the browser session when it appears.
- Rotate sessions/networks if blocks recur.
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
- SECURITY_BLOCK
- Bilibili view API returned a malformed payload during paid-c
- 获取视频信息失败: ${view?.message ?? 'unknown'} (${view?.code})
- 获取视频播放信息失败: ${payload.message} (${payload.code})
- [风控拦截/未登录] 获取到的 subtitle_url 为空!请确保 CLI 已成功登录且风控未封锁此账号。
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0a83f29a22008855.
Report an issue: GitHub.