DIYgod/RSSHub · error · NotFoundError
LSD token not found
Error message
LSD token not found
What it means
Thrown by Threads (Meta) profile scraping when the regex cannot extract the LSD (Login Session Data) CSRF token from the profile HTML. The token is required for authenticated GraphQL calls to Threads' internal API. A NotFoundError indicates the page markup no longer contains the expected `"LSD",[],{"token":"..."}` pattern.
Source
Thrown at lib/routes/threads/utils.ts:37
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
},
});
const $ = load(response);
const data = $('script:contains("LSD"):first').text();
const lsd = data.match(/"LSD",\[\],\{"token":"([\w@-]+)"\},/)?.[1];
if (!lsd) {
throw new NotFoundError('LSD token not found');
}
return { lsd };
};
const getUserId = async (user: string): Promise<string> => {
const result = await cache.tryGet(`threads:userId:${user}`, async () => {
const response = await ofetch(profileUrl(user), {
headers: {
'User-Agent': USER_AGENT,
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',View on GitHub (pinned to bed535e087)
Solutions
- Verify the profile URL still returns the expected HTML by reproducing the ofetch with the same headers in isolation.
- Update the regex on line 34 to match Threads' current LSD token serialization (open the page, search the bundle for `LSD`).
- If Threads now gates the page behind login, switch the route to an authenticated flow or a different API surface.
- Add a retry with a different User-Agent / locale to dodge interstitials.
Example fix
// before
const lsd = data.match(/"LSD",\[\],\{"token":"([\w@-]+)"\},/)?.[1];
// after (loosen the matcher to current bundle shape)
const lsd = data.match(/"LSD"[^}]*"token":"([\w@-]+)"/)?.[1]; Defensive patterns
Strategy: try-catch
Validate before calling
const hasLsdShape = (html: string) => /"LSD"[^}]*"token":"[\w@-]+"/.test(html);
const html = await ofetch(profileUrl(user), { headers });
if (!hasLsdShape(html)) throw new Error('Threads page lacks LSD token — bundle changed or interstitial served'); Type guard
const isLsdToken = (v: unknown): v is string => typeof v === 'string' && /^[\w@-]+$/.test(v);
Try / catch
try { const { lsd } = await extractTokens(user); /* use lsd */ }
catch (e) { if (e instanceof NotFoundError) { /* fall back to alt API or surface 503 */ } else throw e; } Prevention
- Monitor the Threads bundle for LSD token shape changes
- Pin a User-Agent known to return the full HTML
- Detect login-wall HTML before parsing
When it happens
Trigger: The ofetch to https://www.threads.com/@{user} returns HTML whose inline scripts do not contain the LSD token string, so the regex match on line 34 yields undefined and line 36-37 throws. This happens when Threads changes its bundler output, serves a login-wall/consent page, or rate-limits the request.
Common situations: Threads rotates its client bundle and the LSD token key/shape changes; an unsupported region gets redirected to an interstitial; the mobile User-Agent is fingerprinted and served a different page; ofetch follows a redirect to a login page.
Related errors
- Failed to fetch thread data
- User ID not found
- 无法从页面中获取到帖子ID,可能网站结构已变更
- 请填入合法的用户 id,参见用户排名 https://www.jisilu.cn/users/
- missing next data
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/c49bd98c6eb39041.
Report an issue: GitHub.