jackwener/OpenCLI · error · CliError
SECURITY_BLOCK
SECURITY_BLOCK
Error message
Xiaohongshu search was blocked by request-frequency or security controls.
What it means
collectSearchHarvest throws this CliError with code 'SECURITY_BLOCK' when the wait script returns 'security_block': xiaohongshu.com served an anti-bot / risk-control page instead of search results. The library classifies it as request-frequency or security throttling rather than auth, and includes a remediation hint to wait or use a different logged-in session.
Source
Thrown at clis/xiaohongshu/search.js:792
feedClientHeight: feedContainer ? feedContainer.clientHeight : null,
distinctCardTops: distinctCardTops.size,
rounds: round,
stopReason,
elapsedMs,
securityBlock,
},
};
})()
`;
}
async function collectSearchHarvest(page, limit, requestedFilters) {
const waitResult = unwrapEvaluateResult(await page.evaluate(WAIT_FOR_CONTENT_JS));
if (waitResult === 'login_wall') {
throw new AuthRequiredError('www.xiaohongshu.com', 'Xiaohongshu search results are blocked behind a login wall');
}
if (waitResult === 'security_block') {
throw new CliError('SECURITY_BLOCK', 'Xiaohongshu search was blocked by request-frequency or security controls.', 'Wait before retrying or use a different logged-in browser session.');
}
if (waitResult === 'timeout') {
throw new TimeoutError('xiaohongshu search content', CONTENT_WAIT_SECONDS);
}
if (waitResult !== 'content') {
throw new CommandExecutionError('Unexpected Xiaohongshu search wait payload shape.');
}
requireFilterApplication(await page.evaluate(buildApplySearchFiltersJs(requestedFilters)));
const harvestOptions = harvestOptionsForLimit(limit);
const harvest = requireHarvestPayload(await page.evaluate(buildScrollHarvestJs('www.xiaohongshu.com', limit, harvestOptions)), 'www.xiaohongshu.com');
if (harvest.diag.securityBlock) {
throw new CliError('SECURITY_BLOCK', 'Xiaohongshu search was blocked by request-frequency or security controls.', 'Wait before retrying or use a different logged-in browser session.');
}
return harvest;
}
async function replaceCollapsedTab(page, url) {
if (typeof page.getActivePage !== 'function' || typeof page.newTab !== 'function' ||View on GitHub (pinned to 49907e53dc)
Solutions
- Wait (minutes to hours) before retrying so the rate-limit window resets.
- Use a different logged-in browser session or account.
- Add delays/jitter between search calls and reduce crawl concurrency.
- Run from a residential IP instead of a datacenter/VPN address.
- Check for a CLI option to slow down request pacing and enable it.
Example fix
// before
for (const q of queries) await xhs.search(q);
// after
try {
for (const q of queries) {
await xhs.search(q);
await sleep(5000 + Math.random() * 5000);
}
} catch (e) {
if (e.code === 'SECURITY_BLOCK') {
await sleep(15 * 60 * 1000); // back off before resuming
} else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: check the page isn't already showing a block screen
const blocked = await page.evaluate(() =>
/验证码|captcha|blocked|访问过于频繁/i.test(document.body.innerText.slice(0, 2000)));
if (blocked) throw new Error('xiaohongshu risk-control already active; wait before retrying'); Type guard
function isSecurityBlock(e) {
return e instanceof Error && (e.code === 'SECURITY_BLOCK' || /security controls/i.test(e.message));
} Try / catch
try {
const notes = await xhs.search(query);
} catch (e) {
if (isSecurityBlock(e)) {
await sleep(15 * 60 * 1000); // exponential backoff
return withBackoff(() => xhs.search(query), 3);
}
throw e;
} Prevention
- Throttle searches with randomized delays (e.g. 5-15s jitter).
- Limit concurrency to one search at a time per session.
- Use residential IPs; datacenter IPs get flagged faster.
- Rotate accounts/sessions for bulk workloads.
- Back off exponentially on SECURITY_BLOCK instead of hammering retries.
When it happens
Trigger: Hitting the search flow too frequently from the same session/IP; running many parallel searches; the site's risk control detecting automation (headless fingerprints, rapid scrolling) and blocking results.
Common situations: Bulk crawling loops with no delay; shared IP (VPN/datacenter) already flagged; re-using a hot session after a long burst; running multiple CLI instances concurrently against the same account.
Related errors
- SECURITY_BLOCK
- Sogou Weixin blocked this search request
- BOSS search page did not expose its job-list response
- Ctrip is asking for a captcha; complete it in your browser s
- hotels.ctrip.com
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/793467e588dacf0a.
Report an issue: GitHub.