jackwener/OpenCLI · error · Error
Search failed: HTTP ${res.status}
Error message
Search failed: HTTP ${res.status} What it means
The search script fetches TikTok's internal /api/search/general/full/ endpoint from the explore page and throws 'Search failed: HTTP <status>' when res.ok is false. This surfaces the raw HTTP status of TikTok's search API, most commonly 403 from bot detection or an unauthenticated request.
Source
Thrown at clis/tiktok/search.js:19
import { cli } from '@jackwener/opencli/registry';
cli({
site: 'tiktok',
name: 'search',
access: 'read',
description: 'Search TikTok videos',
domain: 'www.tiktok.com',
args: [
{ name: 'query', required: true, positional: true, help: 'Search query' },
{ name: 'limit', type: 'int', default: 10, help: 'Number of results' },
],
columns: ['rank', 'desc', 'author', 'url', 'plays', 'likes', 'comments', 'shares'],
pipeline: [
{ navigate: { url: 'https://www.tiktok.com/explore', settleMs: 5000 } },
{ evaluate: `(async () => {
const query = \${{ args.query | json }};
const limit = \${{ args.limit }};
const res = await fetch('/api/search/general/full/?keyword=' + encodeURIComponent(query) + '&offset=0&count=' + limit + '&aid=1988', { credentials: 'include' });
if (!res.ok) throw new Error('Search failed: HTTP ' + res.status);
const data = await res.json();
const items = (data.data || []).filter(function(i) { return i.type === 1 && i.item; });
return items.slice(0, limit).map(function(i, idx) {
var v = i.item;
var a = v.author || {};
var s = v.stats || {};
return {
rank: idx + 1,
desc: (v.desc || '').replace(/\\n/g, ' ').substring(0, 100),
author: a.uniqueId || '',
url: (a.uniqueId && v.id) ? 'https://www.tiktok.com/@' + a.uniqueId + '/video/' + v.id : '',
plays: s.playCount || 0,
likes: s.diggCount || 0,
comments: s.commentCount || 0,
shares: s.shareCount || 0,
};
});
})()View on GitHub (pinned to 49907e53dc)
Solutions
- Retry after a delay with backoff — 429/403 are often transient rate-limit responses
- Ensure the automation browser has a logged-in TikTok session with valid cookies
- Slow down request rate and randomize queries/offsets to avoid bot detection
- Check the status code in the message: 4xx (auth/query problem) vs 5xx (TikTok outage) and act accordingly
Example fix
// before
for (const q of queries) await run('tiktok search', { query: q, limit: 50 });
// after
for (const q of queries) {
try {
await run('tiktok search', { query: q, limit: 50 });
} catch (e) {
if (/Search failed: HTTP (403|429)/.test(e.message)) await sleep(30000); // backoff
else throw e;
}
} Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch('/api/search/general/full/?keyword=test&offset=0&count=1&aid=1988', { credentials: 'include' });
if (!probe.ok) throw new Error(`TikTok search API unavailable (HTTP ${probe.status}) — check session/rate limits`); Type guard
function isSearchOk(res) {
return res && typeof res.status === 'number' && res.status >= 200 && res.status < 300;
} Try / catch
async function searchWithBackoff(query, limit, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await run('tiktok search', { query, limit });
} catch (e) {
const m = e.message.match(/HTTP (\d+)/);
if (!m || ![403, 429, 500, 502, 503].includes(+m[1]) || i === attempts - 1) throw e;
await new Promise(r => setTimeout(r, 15000 * 2 ** i));
}
}
} Prevention
- Throttle search frequency and add jittered delays between queries
- Keep an authenticated session so the internal API does not 403
- Read the HTTP status in the message to distinguish rate limits (429) from auth (403) vs outage (5xx)
- Cache query results to reduce repeated API hits
When it happens
Trigger: fetch to /api/search/general/full/?keyword=... returns non-2xx: 403 (bot detection/missing cookies), 429 (rate limited), 400 (bad query encoding), or 5xx (TikTok-side failure).
Common situations: Too many searches in a row triggering rate limits; no valid session cookie in the automation browser; special characters or very long queries; TikTok changing/protecting the internal search endpoint.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- HTTP ${code}
- Suno feed lookup failed (HTTP ${result?.status || '?'}).
- BUTTON_NOT_FOUND: Follow button not on profile page (logged
- TikTok returned no notifications
- Favorites button not found - make sure you are logged in
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/456c8c6fc48cb270.
Report an issue: GitHub.