{"record":{"id":"25b6ee3d0564d396","repo":"DIYgod/RSSHub","slug":"empty-post-data-the-request-may-be-filtered-by-wa","errorCode":null,"errorMessage":"Empty post data. The request may be filtered by WAF.","messagePattern":"Empty post data\\. The request may be filtered by WAF\\.","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/douyin/user.ts","lineNumber":74,"sourceCode":"                const request = route.request();\n                request.resourceType() === 'document' || request.resourceType() === 'script' || request.resourceType() === 'xhr' ? route.continue() : route.abort();\n            });\n            page.on('response', async (response) => {\n                const request = response.request();\n                if (request.url().includes('/web/aweme/post') && !postData) {\n                    postData = await response.json();\n                }\n            });\n\n            logger.http(`Requesting ${pageUrl}`);\n            await page.goto(pageUrl, {\n                waitUntil: 'networkidle',\n            });\n\n            await context.close();\n\n            if (!postData) {\n                throw new Error('Empty post data. The request may be filtered by WAF.');\n            }\n\n            return postData;\n        },\n        config.cache.routeExpire,\n        false\n    )) as PostData;\n\n    if (!pageData.aweme_list?.length) {\n        throw new Error('Empty post data. The request may be filtered by WAF.');\n    }\n    const userInfo = pageData.aweme_list[0].author;\n    const userNickName = userInfo.nickname;\n    // const userDescription = userInfo.desc;\n    const userAvatar = getOriginAvatar(userInfo.avatar_thumb.url_list.at(-1));\n\n    const items = pageData.aweme_list.map((post) => {\n        // parse video","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/douyin/user.ts#L56-L92","documentation":"Thrown inside the cache callback of the Douyin user feed route when `postData` is falsy after the Playwright page finishes loading. The route intercepts the `/web/aweme/post` XHR response to capture post data; if that XHR never fires (no response was intercepted), `postData` remains undefined. This is typically caused by Douyin's WAF (Web Application Firewall) blocking or challenging the automated browser before the XHR can complete.","triggerScenarios":"Douyin's WAF detects Playwright/Puppeteer automation and blocks the page load or the XHR request; network timing issues where the XHR fires after `networkidle` is reached; the user account has been deleted or is geo-restricted; Playwright's request interception aborts the critical XHR.","commonSituations":"Running from a datacenter IP that Douyin blocks; Playwright detection via navigator.webdriver or other fingerprinting; the user profile doesn't exist or is region-locked; high-frequency requests trigger WAF escalation.","solutions":["Retry after waiting — WAF challenges are often temporary.","Ensure Playwright stealth measures are in place (the RSSHub playwright utils handle some of this).","Run from a residential IP or proxy if datacenter IPs are blocked.","Verify the uid is valid and the user profile is accessible."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"interface DouyinPostData {\n    aweme_list?: unknown[];\n}\n\nfunction hasPostData(data: unknown): data is DouyinPostData {\n    return typeof data === 'object' && data !== null && typeof (data as any).aweme_list !== 'undefined';\n}","tryCatchPattern":"try {\n    const feed = await fetch(`${rsshubUrl}/douyin/user/${uid}`);\n} catch (e) {\n    if (e.message.includes('filtered by WAF')) {\n        // WAF blocks are often temporary — retry after cache expiry\n        console.error('Douyin WAF blocked the request. Retry later or use a residential IP.');\n    }\n    throw e;\n}","preventionTips":["Run RSSHub from a residential IP if datacenter IPs are WAF-blocked.","Retry after delays — WAF challenges are typically temporary.","Ensure Playwright stealth configurations are current.","Poll infrequently to avoid WAF escalation."],"tags":["douyin","waf","playwright","anti-bot","empty-response"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}