{"record":{"id":"7094ffb25cd2be37","repo":"DIYgod/RSSHub","slug":"error-7094ff","errorCode":null,"errorMessage":"小红书风控校验，请稍后再试","messagePattern":"小红书风控校验，请稍后再试","errorType":"exception","errorClass":"CaptchaError","httpStatus":503,"severity":"error","filePath":"lib/routes/xiaohongshu/util.ts","lineNumber":88,"sourceCode":"                        const request = route.request();\n                        request.resourceType() === 'document' || request.resourceType() === 'script' || request.resourceType() === 'xhr' || request.resourceType() === 'other' ? route.continue() : route.abort();\n                    });\n                },\n            });\n            try {\n                let collect = '';\n                logger.http(`Requesting ${url}`);\n                await page.goto(url, {\n                    waitUntil: 'domcontentloaded',\n                });\n                try {\n                    await page.waitForSelector('div.reds-tab-item:nth-child(2), .fe-verify-box', { timeout: 3000 });\n                } catch {\n                    //\n                }\n\n                if (await page.$('.fe-verify-box')) {\n                    throw new CaptchaError('小红书风控校验，请稍后再试');\n                }\n\n                const content = await page.content();\n                const initialState = JSON.parse(extractInitialState(load(content)));\n\n                if (!(await page.$('.lock-icon'))) {\n                    try {\n                        await page.click('div.reds-tab-item:nth-child(2)', { timeout: 3000 });\n                        const response = await page.waitForResponse(\n                            (res) => {\n                                const req = res.request();\n                                return req.url().includes('/api/sns/web/v2/note/collect/page') && req.method() === 'GET' && req.resourceType() === 'xhr';\n                            },\n                            { timeout: 5000 }\n                        );\n                        collect = await response.json();\n                    } catch {\n                        //","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/xiaohongshu/util.ts#L70-L106","documentation":"CaptchaError raised during the Playwright user-profile fetch when the page contains a .fe-verify-box element — Xiaohongshu's anti-bot verification widget. RSSHub classifies this as a distinct CaptchaError so upstream mapping can treat it as retryable rather than a hard failure.","triggerScenarios":"After page.goto(url) and waitForSelector for the tab or the verify box, page.$('.fe-verify-box') resolves truthy at util.ts:87-89, meaning Xiaohongshu challenged the headless browser.","commonSituations":"High request volume from the RSSHub host IP, datacenter IP reputation, missing/warm XIAOHONGSHU_COOKIE, or running Playwright without enough human-like signals.","solutions":["Provide a valid XIAOHONGSHU_COOKIE (config.xiaohongshu.cookie) so the session is already trusted and the verify box is not triggered.","Slow down polling of xiaohongshu routes and let config.cache.routeExpire absorb repeats.","Route egress through a residential/proxy IP (config.xiaohongshu.proxy) less likely to be challenged, and retry after a backoff."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Skip the Playwright path entirely if a trusted cookie is available\nif (!config.xiaohongshu.cookie) {\n    console.warn('No XIAOHONGSHU_COOKIE set — xiaohongshu will likely trigger captcha (.fe-verify-box).');\n}","typeGuard":"function isXiaohongshuCaptchaError(e: unknown): boolean {\n    return e instanceof Error && e.name === 'CaptchaError';\n}","tryCatchPattern":"for (const backoff of [0, 30_000, 120_000]) {\n    try {\n        return await getUser(url, cache);\n    } catch (e) {\n        if (!isXiaohongshuCaptchaError(e) || backoff === 120_000) throw e;\n        await new Promise((r) => setTimeout(r, backoff));\n    }\n}","preventionTips":["Configure XIAOHONGSHU_COOKIE so requests are authenticated and not challenged.","Space out xiaohongshu polling; let config.cache.routeExpire absorb repeats.","Use a residential egress/proxy (config.xiaohongshu.proxy) to reduce datacenter-IP challenges."],"tags":["xiaohongshu","captcha","anti-bot","playwright","rate-limit"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}