{"record":{"id":"5deea1f17bfc66e4","repo":"jackwener/OpenCLI","slug":"xiaohongshu-search-results-are-blocked-behind-a-lo","errorCode":null,"errorMessage":"Xiaohongshu search results are blocked behind a login wall","messagePattern":"Xiaohongshu search results are blocked behind a login wall","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/search.js","lineNumber":789,"sourceCode":"            scrollHeight: metrics.scrollHeight,\n            clientHeight: metrics.clientHeight,\n            cardCount,\n            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}","sourceCodeStart":771,"sourceCodeEnd":807,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/search.js#L771-L807","documentation":"collectSearchHarvest throws this AuthRequiredError when the page-wait script returns 'login_wall', meaning www.xiaohongshu.com redirected or rendered its login gate instead of search results. The library surfaces this as an authentication requirement rather than a generic failure so callers can re-authenticate. It is the library's structured signal that anonymous search is no longer permitted for this session.","triggerScenarios":"Running the search command in a browser context without a logged-in xiaohongshu.com session when the site enforces login for search; a session cookie expiring mid-crawl; the site deciding this client must log in before showing results.","commonSituations":"Fresh automation profile with no cookies; cookies cleared or expired after inactivity; xiaohongshu tightening anonymous-access policy; datacenter IP ranges triggering forced login; a previously working session hitting a 401/login redirect.","solutions":["Log into www.xiaohongshu.com in the automation browser profile and rerun the command.","Connect the CLI to an existing browser profile that already has an authenticated session (e.g. launch with your regular user data dir).","Refresh/restore session cookies and retry.","Catch AuthRequiredError and pause the crawl until manual login is done.","Switch to a residential IP or different network if datacenter IPs trigger forced login."],"exampleFix":"// before\nconst notes = await xhs.search('coffee');\n// after\ntry {\n  const notes = await xhs.search('coffee');\n} catch (e) {\n  if (e.name === 'AuthRequiredError' && /login wall/.test(e.message)) {\n    await xhs.openLoginPage(); // prompt user to log in, then retry\n    const notes = await xhs.search('coffee');\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"const loggedIn = await page.evaluate(() =>\n  Boolean(document.cookie.includes('web_session') || window.__INITIAL_STATE__?.user?.loggedIn));\nif (!loggedIn) throw new Error('xiaohongshu login required before search');","typeGuard":"function isAuthRequiredError(e) {\n  return e instanceof Error && (e.name === 'AuthRequiredError' || /login wall/i.test(e.message));\n}","tryCatchPattern":"try {\n  const notes = await xhs.search(query);\n} catch (e) {\n  if (isAuthRequiredError(e)) {\n    await promptUserLogin('www.xiaohongshu.com');\n    return xhs.search(query);\n  }\n  throw e;\n}","preventionTips":["Use a persistent browser profile that stays logged in.","Check session validity before starting long crawls.","Handle AuthRequiredError explicitly and pause instead of retrying blindly.","Avoid fresh headless profiles for anonymous search — login walls are common.","Refresh cookies proactively during long-running jobs."],"tags":["authentication","login-wall","scraping"],"backgroundTag":"auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}