Skip to content
ScrapeField

Blog · Guides ·

Every comment on a TikTok video

Up to 50 comments a call, with a cursor for the rest, replies marked as replies. A short loop reads all of them, and a sort finds the questions people most want answered.

ScrapeField

The comments under a video are where people say what they think of it: what they ask, what they would buy, what went wrong. This guide reads every comment on one TikTok video, then sorts out the questions. You need a key from us, and no TikTok account.

One page

GET /v1/tiktok/comments takes the video’s url, as it is in the address bar, or its numeric id. It answers with up to 50 comments and a cursor for the next ones:

curl -H "Authorization: Bearer $SCRAPEFIELD_KEY" \
  "https://api.scrapefield.com/v1/tiktok/comments?id=7643923087913651479"

Each comment has id, text, the username who wrote it, create_time, like_count and reply_count. A reply has the comment it answers in parent_comment_id; a comment on the video itself has null there. Every field is in the comments reference.

A call costs 3 credits, from our cache or not, and a call that fails costs nothing. At 50 comments a call, 1,000 comments cost about $0.05 on the smallest pack and $0.03 on the largest. A page can hold fewer than 50 while the cursor is still set, so read until it is null.

All of them

Pass meta.next_cursor back as cursor until it is null. In TypeScript:

const base = 'https://api.scrapefield.com/v1/tiktok/comments';
const headers = { Authorization: `Bearer ${process.env.SCRAPEFIELD_KEY}` };
const comments = [];
let cursor: string | null = null;
do {
  const q = new URLSearchParams({ id: '7643923087913651479' });
  if (cursor) q.set('cursor', cursor);
  const res = await fetch(`${base}?${q}`, { headers });
  const body = await res.json();
  if (!res.ok) throw new Error(body.error.message);
  comments.push(...body.data);
  cursor = body.meta.next_cursor;
} while (cursor);

And in Python:

import os, requests

base = "https://api.scrapefield.com/v1/tiktok/comments"
headers = {"Authorization": f"Bearer {os.environ['SCRAPEFIELD_KEY']}"}
comments, cursor = [], None
while True:
    params = {"id": "7643923087913651479"}
    if cursor:
        params["cursor"] = cursor
    body = requests.get(base, params=params, headers=headers).json()
    if "error" in body:
        raise RuntimeError(body["error"]["message"])
    comments += body["data"]
    cursor = body["meta"]["next_cursor"]
    if cursor is None:
        break

A cursor lasts as long as the answer it belongs to is cached, an hour for comments. Run the loop in one go.

The questions people most want answered

Keep the comments on the video itself, keep the ones that ask something, and sort them by likes: a like on a question is someone else who wants the answer. After the loop:

const questions = comments
  .filter((c) => c.parent_comment_id === null && (c.text ?? '').includes('?'))
  .sort((a, b) => (b.like_count ?? 0) - (a.like_count ?? 0));
for (const c of questions.slice(0, 10)) console.log(c.like_count ?? 0, c.text);

A question with many replies has been answered by someone already; one with many likes and no replies is the gap. The same idea across a brand’s videos is a worked example on the TikTok page.

Every video of an account

An account’s videos come back with their comment_count, so you can pick the ones worth reading. For many videos at once, run the calls side by side, up to your limit of calls at once. Every list pages the same way (how lists work).

More articles