TikTok-Api returns empty results or a captcha. What now?
TikTok has flagged the browser session your script controls. An empty list and a captcha page are the same signal at different strengths. Fresh tokens, a new user agent, or a different proxy clear it for a while, then it comes back. The library is not broken. TikTok changed the rules for scripted traffic.
If you only need public profiles, videos, comments, and search, call an API that does the reading. Openhandle returns the same fields from the web and the app, absorbs TikTok changes, and never asks you for a TikTok session.
Checked September 2026 · request and response run against the API · no affiliate links
curl "https://api.openhandle.dev/v1/tiktok/profiles/@pixel_orchard_tt_test/posts" \
-H "Authorization: Bearer $OPENHANDLE_API_KEY"import { OpenHandle } from '@openhandle/sdk';
const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_API_KEY! });
const page = await openhandle.tiktok.profile('pixel_orchard_tt_test').posts.list();
for (const video of page.data) console.log(video.id, video.metrics.views);{
"platform": "tiktok",
"resource": "post",
"capturedAt": "2026-09-18T10:40:09Z",
"source": "live",
"data": [
{
"id": "920100000000000001",
"caption": "A synthetic orchard loop. #pixelorchard",
"createdAt": "2026-08-09T15:30:00Z",
"metrics": { "views": 23000, "likes": 1200, "comments": 24, "shares": 73, "saves": 88 }
}
],
"meta": { "cursors": { "next": "b3BhcXVlLWN1cnNvcg" } }
}Trimmed to one video and the fields a TikTok-Api `video.info()` call gives you. The example is a Test account, so you can run it on a free Test key.
What people try, and what happens
- —Pass a fresh ms_token. Works for a session. TikTok ties the token to the browser fingerprint that made it, so it dies with the next detection pass.
- —Switch headless mode off. Fewer captchas at first. Then the same result, slower, with a visible browser you have to host somewhere.
- —Rotate residential proxies. Costs money and upkeep. Region changes what TikTok shows, so results drift between runs.
- —Pin an older library version. Does nothing. The detection is on TikTok’s side, not in the library.
Map TikTok-Api to the API
| TikTok-Api | Openhandle |
|---|---|
api.user(username).info() | GET /v1/tiktok/profiles/@username |
api.user(username).videos() | GET /v1/tiktok/profiles/@username/posts, one page per request |
api.video(id).info() | GET /v1/tiktok/posts/{id} |
api.video(id).comments() | GET /v1/tiktok/posts/{id}/comments |
api.hashtag(name).videos() | GET /v1/tiktok/hashtags/{id}/posts |
api.search.videos(q) | GET /v1/tiktok/search/posts?q=… |
| A video URL or short link | POST /v1/urls/fetch. Short links are expanded for you. |
What stays the same
Public accounts only. A private account returns PROFILE_PRIVATE. A region-locked video answers as TikTok shows it to a logged-out visitor. A metric TikTok has not published is null, never 0.
When this does not work
The answers you will see instead of an empty list.
| Situation | Status | Code |
|---|---|---|
| The account is private | 403 | PROFILE_PRIVATE |
| The account or video is gone | 404 | PROFILE_NOT_FOUND or POST_NOT_FOUND |
| You passed your own per-second limit | 429 | RATE_LIMITED |
{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the Retry-After header.",
"requestId": "req_01j8…",
"retryable": true
}
}Rate limits are per key, 10 requests per second, and never billed. Higher on request. Every new workspace starts with 100 free live requests, no card needed.
Read next
More TikTok questions
Send your agent ahead.
Paste the prompt into your agent and it sets everything up. Or come yourself, it takes five minutes.