jackwener/OpenCLI · error · Error

HTTP ${res.status} from ${requestUrl}: ${text.slice(0, 160)}

Error message

HTTP ${res.status} from ${requestUrl}: ${text.slice(0, 160)}

What it means

The TikTok API fetch helper treats any non-2xx response as fatal and throws an Error containing the status code, the requested URL, and the first 160 characters of the response body. This surfaces server-side rejections (403, 4xx/5xx) with enough of the body to diagnose them.

Source

Thrown at clis/tiktok/utils.js:238

}

function getCookie(name) {
  const prefix = name + '=';
  for (const part of (document.cookie || '').split('; ')) {
    if (part.startsWith(prefix)) return decodeURIComponent(part.slice(prefix.length));
  }
  return '';
}

async function fetchJson(url) {
  const requestUrl = new URL(url, ${JSON.stringify(TIKTOK_HOST)}).toString();
  const res = await fetch(requestUrl, {
    credentials: 'include',
    headers: { accept: 'application/json,text/plain,*/*' },
  });
  const text = await res.text();
  if (!res.ok) {
    throw new Error('HTTP ' + res.status + ' from ' + requestUrl + ': ' + text.slice(0, 160));
  }
  if (!text.trim()) return {};
  try {
    return JSON.parse(text);
  } catch (error) {
    throw new Error('invalid JSON from ' + requestUrl + ': ' + (error instanceof Error ? error.message : String(error)));
  }
}

function assertTikTokApiSuccess(data, label) {
  if (!data || typeof data !== 'object') return;
  const code = data.status_code ?? data.statusCode;
  if (code === undefined || code === null || Number(code) === 0) return;
  const message = cleanText(data.status_msg ?? data.statusMsg ?? data.message ?? data.msg ?? code, 240);
  if (Number(code) === 8 || /auth|captcha|login|permission|unauthori[sz]ed|forbidden/i.test(message)) {
    throw new Error('AUTH_REQUIRED: ' + label + ' API failed: ' + message);
  }
  throw new Error(label + ' API failed: ' + message);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the 160-char body snippet: an HTML challenge means cookies/IP are blocked — refresh session cookies
  2. Retry with backoff for 5xx/429 statuses
  3. Route requests through a residential proxy or different IP
  4. Confirm the API URL is still valid (404 suggests a TikTok endpoint change)

Example fix

// before
const res = await fetch(requestUrl, { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' ...');
// after
if (res.status === 429 || res.status >= 500) {
  await sleep(2000); return fetchJson(requestUrl); // retry once
}
if (!res.ok) throw new Error('HTTP ' + res.status + ' ...');
Defensive patterns

Strategy: retry

Validate before calling

// pre-check session validity before API calls
const ok = await page.evaluate(() => document.cookie.includes('sessionid'));
if (!ok) throw new Error('TikTok session cookies missing — login first');

Type guard

function isHttpError(e) { return /^HTTP \d{3} from /.test(e?.message || ''); }
function statusCodeOf(e) { const m = e?.message.match(/^HTTP (\d{3})/); return m ? Number(m[1]) : null; }

Try / catch

try { const data = await fetchJson(url); } catch (e) {
  const status = statusCodeOf(e);
  if (status === 429 || (status && status >= 500)) { await backoff(); return fetchJson(url); }
  throw e;
}

Prevention

When it happens

Trigger: fetchJson to a tiktok.com API endpoint returned res.ok === false — e.g. expired cookies causing 403, rate limiting returning 429, or a 500 from TikTok's backend.

Common situations: Session cookies expired or missing (403 with an HTML challenge page), datacenter IP blocked by TikTok WAF, transient 5xx, or the endpoint URL changed and now 404s.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/2804b6f8c2af04a7. Report an issue: GitHub.