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

  1. Wait (minutes to hours) before retrying so the rate-limit window resets.
  2. Use a different logged-in browser session or account.
  3. Add delays/jitter between search calls and reduce crawl concurrency.
  4. Run from a residential IP instead of a datacenter/VPN address.
  5. 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

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


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