Docs · Video comments
Video comments
A video's top-level comments, most relevant first, with like and reply counts.
https://api.lurkapi.com/v1/tiktok/video/commentsWhen to use this
Use it to read what viewers say: objections, questions, praise and the words your audience uses. Each comment has its likes, reply count and author; pass a comment's cid as comment_id to comment replies for its thread.
Pagination. 50 comments per page. Pass the response's cursor back as cursor (with the same url) for more; it's null at the end.
Deleted or private videos return 404 not_found; videos with comments turned off return an empty list.
Parameters
All parameters go in the query string.
| Parameter | Description |
|---|---|
urlstringrequired | The video's URL, e.g. https://www.tiktok.com/@hubspot/video/7671325437229845774. Photo post URLs and bare video ids work too.
|
cursorstringoptional | The cursor from the previous response, to get the next page. |
Example request
Replace YOUR_API_KEY with your key, or set LURKAPI_KEY for the code. Get a free key.
curl "https://api.lurkapi.com/v1/tiktok/video/comments?url=https%3A%2F%2Fwww.tiktok.com%2F%40scout2015%2Fvideo%2F6718335390845095173" \
-H "x-api-key: YOUR_API_KEY"const params = new URLSearchParams({
url: "https://www.tiktok.com/@scout2015/video/6718335390845095173",
});
const res = await fetch(`https://api.lurkapi.com/v1/tiktok/video/comments?${params}`, {
headers: { "x-api-key": process.env.LURKAPI_KEY },
});
const data = await res.json();
if (!data.success) throw new Error(`${data.code}: ${data.error}`);
console.log(data.comments);import os
import requests
res = requests.get(
"https://api.lurkapi.com/v1/tiktok/video/comments",
params={
"url": "https://www.tiktok.com/@scout2015/video/6718335390845095173",
},
headers={"x-api-key": os.environ["LURKAPI_KEY"]},
timeout=60,
)
data = res.json()
if not data["success"]:
raise RuntimeError(f"{data['code']}: {data['error']}")
print(data["comments"])Example response
A real response from this endpoint, captured from the live API and trimmed to a couple of items. Strings over 96 characters (mostly signed media URLs) are cut short and end in ….
Show the example response (2 KB)Hide
{
"success": true,
"credits_remaining": 99981,
"credits_charged": 1,
"comments": [
{
"cid": "6718335906996502534",
"text": "ok ;)\nodoreta\nhave fun~\n(it's a Serbian name)",
"create_time": 1564234475,
"digg_count": 166,
"reply_comment_total": 49,
"comment_language": "un",
"author_pin": false,
"is_author_digged": false,
"reply_id": "0",
"reply_to_reply_id": "0",
"aweme_id": "6718335390845095173",
"user": {
"uid": "6650133637952618502",
"unique_id": "flamigo_kisses",
"nickname": "flamigoo",
"sec_uid": "MS4wLjABAAAA2MsvjMy0b24-FHIEBfHzeBhZelr6GpESRqTxE-LAA5ByJY5rSolRWE3rXB4Mfqt6",
"avatar_thumb": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/73363709566…"
}
},
{
"cid": "6722043930156417030",
"text": "srii good luck",
"create_time": 1565097817,
"digg_count": 53,
"reply_comment_total": 44,
"comment_language": "un",
"author_pin": false,
"is_author_digged": false,
"reply_id": "0",
"reply_to_reply_id": "0",
"aweme_id": "6718335390845095173",
"user": {
"uid": "6718326650415203333",
"unique_id": "vsco_room_xx",
"nickname": "vsco_room_xx",
"sec_uid": "MS4wLjABAAAArG6B4beBhFRzOVGzxvDgAKuz2yK0AHG9jfU6PiSjFoIPrtYEASAPir_quhWWPs-4",
"avatar_thumb": "https://p16-common-sign.tiktokcdn-us.com/tos-maliva-avt-0068/73314074326…"
}
}
],
"total": 5844,
"has_more": true,
"cursor": "50"
}Response fields
Every field of a successful response. [] marks a list: a[].b is the b of each item in a. nullable fields can be null; optional fields can be missing.
Show all 24 fieldsHide
| Field | Type | Description |
|---|---|---|
| success | true | Always true here; errors have success: false. |
| credits_remaining | number | Your balance after this call. On anonymous playground calls: free tries left today. |
| credits_charged | number | Credits this call cost; 0 on free endpoints. On anonymous playground calls: tries used (1). |
| comments | object[] | Comments, in TikTok's order. |
| comments[].cid | string | Comment id; pass it as comment_id to comment replies. |
| comments[].text | string | Comment text. |
| comments[].create_time | number | Posted at, Unix seconds. |
| comments[].digg_count | number | Likes. |
| comments[].reply_comment_total | number | Replies to this comment. Always 0 on replies. |
| comments[].comment_language | stringnullable | Language as TikTok detects it, e.g. en; un = undetermined. |
| comments[].author_pin | boolean | Pinned by the video's creator. |
| comments[].is_author_digged | boolean | Liked by the video's creator. |
| comments[].reply_id | string | On replies: the comment it belongs to. 0 on top-level comments. |
| comments[].reply_to_reply_id | string | On replies: the reply it answers, if any. 0 otherwise. |
| comments[].aweme_id | string | The video's id. |
| comments[].user | object | Who wrote it. |
| comments[].user.uid | string | Numeric user id. |
| comments[].user.unique_id | string | Username (handle), without @. |
| comments[].user.nickname | string | Display name. |
| comments[].user.sec_uid | string | TikTok's long, stable user id. |
| comments[].user.avatar_thumb | stringnullable | Small avatar URL (expires after a few days); null if TikTok has none. |
| total | number | Comments TikTok counts in this thread (may include some it no longer shows). |
| has_more | boolean | More comments after this page. |
| cursor | stringnullable | Pass as cursor for the next page. null on the last page. |
Pagination
Pass the response's cursor back as cursor, with the other parameters unchanged, for the next page. It's null on the last page. Each page costs 1 credit.
let cursor = null;
for (let page = 1; page <= 5; page++) {
const params = new URLSearchParams({ url: "https://www.tiktok.com/@scout2015/video/6718335390845095173" });
if (cursor) params.set("cursor", cursor);
const res = await fetch(`https://api.lurkapi.com/v1/tiktok/video/comments?${params}`, {
headers: { "x-api-key": process.env.LURKAPI_KEY },
});
const data = await res.json();
if (!data.success) throw new Error(`${data.code}: ${data.error}`);
console.log(data.comments);
cursor = data.cursor;
if (!cursor) break; // last page
}Caching and freshness
Responses are cached for up to 5 minutes, so a repeat call within that window can return the same data. It still costs 1 credit.
Errors
Errors return { success: false, error, code, docs } with the HTTP status below. Validation errors, 401/402/429 rejections and 5xx failures are free; not_found is charged (how charging works). All error codes.
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_api_key | No API key. Send it in the x-api-key header. |
| 401 | invalid_api_key | The key is unknown or was revoked. |
| 402 | insufficient_credits | Not enough credits for this call. Buy a pack or wait for tomorrow's top-up. |
| 404 | not_found | The endpoint, or the thing you asked for (ad, post, subreddit), doesn't exist. Charged when the platform was checked. |
| 405 | method_not_allowed | Endpoints take GET with query params. |
| 429 | rate_limited | Too many calls at once. Wait for the retry-after seconds, then retry. |
| 500 | internal_error | Something broke on our side. Retry; 5xx errors are free. |
| 502 | upstream_error | The platform didn't give a usable answer. Retry; 5xx errors are free. |
| 503 | upstream_busy | All our connections to the platform are busy. Retry in a few seconds; 5xx errors are free. |
| 504 | upstream_timeout | The platform took over 30 seconds to answer. Retry; timeouts are free. |
Use it in Claude
Once LurkAPI is connected to Claude, this endpoint is the tiktok_comments tool. Ask in plain English, for example:
Use LurkAPI's tiktok_comments with url "https://www.tiktok.com/@scout2015/video/6718335390845095173" and summarize what you find.Claude calls tiktok_comments with arguments like these, and each call costs 1 credit:
{
"url": "https://www.tiktok.com/@scout2015/video/6718335390845095173"
}Tool results skip nulls and empty lists to save tokens.