jackwener/OpenCLI · error · Error
Could not parse profile data
Error message
Could not parse profile data
What it means
After fetching the profile HTML successfully, the script searches for the __UNIVERSAL_DATA_FOR_REHYDRATION__ script tag that carries TikTok's JSON state. If the marker string is absent (indexOf returns -1) it throws 'Could not parse profile data'. This means the page loaded but did not contain the expected embedded data blob.
Source
Thrown at clis/tiktok/profile.js:34
columns: [
'username',
'name',
'followers',
'following',
'likes',
'videos',
'verified',
'bio',
],
pipeline: [
{ navigate: { url: 'https://www.tiktok.com/explore', settleMs: 5000 } },
{ evaluate: `(async () => {
const username = \${{ args.username | json }};
const res = await fetch('https://www.tiktok.com/@' + encodeURIComponent(username), { credentials: 'include' });
if (!res.ok) throw new Error('User not found: ' + username);
const html = await res.text();
const idx = html.indexOf('__UNIVERSAL_DATA_FOR_REHYDRATION__');
if (idx === -1) throw new Error('Could not parse profile data');
const start = html.indexOf('>', idx) + 1;
const end = html.indexOf('</script>', start);
const data = JSON.parse(html.substring(start, end));
const ud = data['__DEFAULT_SCOPE__'] && data['__DEFAULT_SCOPE__']['webapp.user-detail'];
const u = ud && ud.userInfo && ud.userInfo.user;
const s = ud && ud.userInfo && ud.userInfo.stats;
if (!u) throw new Error('User not found: ' + username);
return [{
username: u.uniqueId || username,
name: u.nickname || '',
bio: (u.signature || '').replace(/\\n/g, ' ').substring(0, 120),
followers: s && s.followerCount || 0,
following: s && s.followingCount || 0,
likes: s && s.heartCount || 0,
videos: s && s.videoCount || 0,
verified: u.verified ? 'Yes' : 'No',
}];
})()View on GitHub (pinned to 49907e53dc)
Solutions
- Retry with a logged-in, warmed browser session and residential IP to bypass bot/consent interstitials
- Capture and inspect the returned HTML to see what page TikTok actually served
- Check the library for updates — the marker may have been renamed by TikTok and selectors patched
- Fall back to another data source or the mobile API for profile info
Example fix
// before
const data = await getProfile(username); // throws Could not parse profile data
// after
try {
const data = await getProfile(username);
} catch (e) {
if (/Could not parse profile data/.test(e.message)) {
console.error('TikTok page had no rehydration data (likely bot wall); retry with warm session');
} else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
const html = await (await fetch('https://www.tiktok.com/@' + username, { credentials: 'include' })).text();
if (!html.includes('__UNIVERSAL_DATA_FOR_REHYDRATION__')) {
throw new Error('TikTok served a page without profile data (bot wall or markup change)');
} Type guard
function hasRehydrationData(html) {
return typeof html === 'string' && html.indexOf('__UNIVERSAL_DATA_FOR_REHYDRATION__') !== -1;
} Try / catch
let profile;
for (let attempt = 0; attempt < 3; attempt++) {
try {
profile = await run('tiktok profile', { username });
break;
} catch (e) {
if (!/Could not parse profile data/.test(e.message) || attempt === 2) throw e;
await new Promise(r => setTimeout(r, 5000 * (attempt + 1)));
}
} Prevention
- Use a warmed, logged-in browser session with residential IPs to avoid consent/bot interstitials
- Capture the failing HTML periodically to detect TikTok markup changes early
- Keep the library updated for rehydration-key changes
- Fail fast and alert when the served page is not a profile page (login wall/captcha detection)
When it happens
Trigger: The fetched HTML for tiktok.com/@<username> lacks the __UNIVERSAL_DATA_FOR_REHYDRATION__ script — typically a login wall, captcha/bot-check page, consent/redirect interstitial, or a TikTok markup change removed/renamed the global data key.
Common situations: Datacenter IP or headless browser flagged by TikTok; cookie-consent banner intercepting; TikTok renaming the rehydration global in a frontend deploy; response being an SPA shell without SSR data.
Related errors
- No videos found on /explore + suffix
- PARSE_ERROR
- FETCH_ERROR
- Booking.com served a verification / captcha page; retry late
- Chess.com callback returned malformed JSON for ${url}: ${err
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/33fe805e92162206.
Report an issue: GitHub.