{"record":{"id":"793467e588dacf0a","repo":"jackwener/OpenCLI","slug":"security-block-793467","errorCode":"SECURITY_BLOCK","errorMessage":"Xiaohongshu search was blocked by request-frequency or security controls.","messagePattern":"Xiaohongshu search was blocked by request-frequency or security controls\\.","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/search.js","lineNumber":792,"sourceCode":"            feedClientHeight: feedContainer ? feedContainer.clientHeight : null,\n            distinctCardTops: distinctCardTops.size,\n            rounds: round,\n            stopReason,\n            elapsedMs,\n            securityBlock,\n          },\n        };\n      })()\n    `;\n}\n\nasync function collectSearchHarvest(page, limit, requestedFilters) {\n    const waitResult = unwrapEvaluateResult(await page.evaluate(WAIT_FOR_CONTENT_JS));\n    if (waitResult === 'login_wall') {\n        throw new AuthRequiredError('www.xiaohongshu.com', 'Xiaohongshu search results are blocked behind a login wall');\n    }\n    if (waitResult === 'security_block') {\n        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.');\n    }\n    if (waitResult === 'timeout') {\n        throw new TimeoutError('xiaohongshu search content', CONTENT_WAIT_SECONDS);\n    }\n    if (waitResult !== 'content') {\n        throw new CommandExecutionError('Unexpected Xiaohongshu search wait payload shape.');\n    }\n    requireFilterApplication(await page.evaluate(buildApplySearchFiltersJs(requestedFilters)));\n    const harvestOptions = harvestOptionsForLimit(limit);\n    const harvest = requireHarvestPayload(await page.evaluate(buildScrollHarvestJs('www.xiaohongshu.com', limit, harvestOptions)), 'www.xiaohongshu.com');\n    if (harvest.diag.securityBlock) {\n        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.');\n    }\n    return harvest;\n}\n\nasync function replaceCollapsedTab(page, url) {\n    if (typeof page.getActivePage !== 'function' || typeof page.newTab !== 'function' ||","sourceCodeStart":774,"sourceCodeEnd":810,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/search.js#L774-L810","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nfor (const q of queries) await xhs.search(q);\n// after\ntry {\n  for (const q of queries) {\n    await xhs.search(q);\n    await sleep(5000 + Math.random() * 5000);\n  }\n} catch (e) {\n  if (e.code === 'SECURITY_BLOCK') {\n    await sleep(15 * 60 * 1000); // back off before resuming\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":"// pre-flight: check the page isn't already showing a block screen\nconst blocked = await page.evaluate(() =>\n  /验证码|captcha|blocked|访问过于频繁/i.test(document.body.innerText.slice(0, 2000)));\nif (blocked) throw new Error('xiaohongshu risk-control already active; wait before retrying');","typeGuard":"function isSecurityBlock(e) {\n  return e instanceof Error && (e.code === 'SECURITY_BLOCK' || /security controls/i.test(e.message));\n}","tryCatchPattern":"try {\n  const notes = await xhs.search(query);\n} catch (e) {\n  if (isSecurityBlock(e)) {\n    await sleep(15 * 60 * 1000);      // exponential backoff\n    return withBackoff(() => xhs.search(query), 3);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["rate-limit","anti-bot","security-block","scraping"],"backgroundTag":"security-block","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}