# TikTok comments in Python for sentiment analysis (2026)

> Search TikTok by keyword, page through the comments under the top videos and write a clean CSV for sentiment analysis, in Python with requests. Parameters, code and cost.

Canonical page: https://okdata.online/guides/tiktok-comments-python/

Two endpoints: TikTok video search to pick the videos, then TikTok video comments, page by page, for each one. The worked example below is 11 calls and costs $0.022; a failed call is not charged.

Updated 2026-11-12

The job: you want to know how people feel about a product or topic on TikTok, measured on what they write, not on view counts. That means a few hundred real comments from the videos where the discussion happens, in a file a sentiment model or an LLM can read. TikTok's own Research API has comments, but only for researchers TikTok approves through an application; [what a company can use instead](https://okdata.online/answers/tiktok-research-api-alternative/) covers that route. Here each call is an HTTPS GET with an API key, no TikTok account or login, and `requests` is the only library.

You end with `tiktok_comments.csv`: one row per comment with the video it came from, the video's language, the comment text, likes, reply count and time, deduplicated and with empty rows dropped.

## Step by step

Set the key once: `export OKDATA_API_KEY=okd_...`. Every answer has `code` (`"ok"` on success); lists come in `data.items` with a `page` that carries the next cursor.

### Step 1: find the videos where people talk

[TikTok video search](https://okdata.online/apis/tiktok/videos/search/) takes `query` and `sort`: `relevance` (the default), `most_liked` or `latest`. TikTok's search leans on relevance, so `latest` is not a strict date order; filter on `published_at` yourself if dates matter. One call returns about 30 videos for $0.002, each with `id`, the caption in `text`, `lang`, `published_at`, `author.username`, and `metrics.views`, `metrics.likes`, `metrics.comments` and `metrics.shares`. Pick by `metrics.comments`: a video with 4 million views and 80 comments is no use for this.

```bash
curl -G "https://api.okdata.online/v1/tiktok/videos/search" -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'query=air fryer' --data-urlencode 'sort=most_liked' \
  --data-urlencode 'fields=id,text,lang,author.username,metrics.comments,published_at'
```

### Step 2: page through the comments

[TikTok video comments](https://okdata.online/apis/tiktok/videos/comments/list/) takes the video's numeric ID as `id` (such as `7429815063927400734`). One call returns about 50 top-level comments for $0.002, each with `id`, `text`, `likes`, `replies` (the reply count), `published_at`, `author.username` and, where TikTok shows one, `ip_location`. For the next page, send `page.next_cursor` back as `cursor`, unchanged; stop when `page.has_more` is `false`.

```bash
curl -G "https://api.okdata.online/v1/tiktok/videos/comments/list" -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'id=7429815063927400734'
```

### Step 3: the full script

The script searches once, keeps the `VIDEOS` videos with the most comments, reads up to `PAGES_PER_VIDEO` pages under each, cleans the text and writes the CSV. The same number of pages per video keeps one viral video from drowning out the rest. The helper retries rate limits and busy upstreams with the same `Idempotency-Key`, so a retry is never charged twice, and skips videos deleted since the search.

```python
import csv
import os
import re
import time
import uuid

import requests

API = "https://api.okdata.online"
KEY = os.environ["OKDATA_API_KEY"]
QUERY = "air fryer"
VIDEOS = 5            # videos to read
PAGES_PER_VIDEO = 2   # comment pages per video; each page is one call


def call(path, **params):
    headers = {"Authorization": f"Bearer {KEY}", "Idempotency-Key": str(uuid.uuid4())}
    for attempt in range(4):
        body = requests.get(API + path, headers=headers, params=params, timeout=60).json()
        if body["code"] == "ok":
            return body
        if body["code"] == "not_found":
            return None  # deleted or private: not charged
        if body.get("retry") in ("yes", "same_key"):
            time.sleep(body.get("retry_after_seconds") or 2 ** attempt)
            continue
        raise RuntimeError(f"{body['code']}: {body['message']} (request {body['request_id']})")
    raise RuntimeError(f"{path}: still failing after 4 tries")


def comments(video_id, max_pages):
    cursor = None
    for _ in range(max_pages):
        body = call("/v1/tiktok/videos/comments/list", id=video_id, **({"cursor": cursor} if cursor else {}))
        if body is None:
            return
        yield from body["data"]["items"]
        if not body["page"]["has_more"]:
            return
        cursor = body["page"]["next_cursor"]


def clean(text):
    return re.sub(r"\s+", " ", text or "").strip()


videos = call("/v1/tiktok/videos/search", query=QUERY, sort="most_liked")["data"]["items"]
videos = sorted(videos, key=lambda v: v["metrics"]["comments"] or 0, reverse=True)[:VIDEOS]

seen = set()
with open("tiktok_comments.csv", "w", newline="", encoding="utf-8-sig") as f:
    out = csv.writer(f)
    out.writerow(["video_id", "video_lang", "video_caption", "comment_id", "text", "likes", "replies", "published_at", "author"])
    for v in videos:
        for c in comments(v["id"], PAGES_PER_VIDEO):
            text = clean(c["text"])
            if not text or c["id"] in seen:
                continue
            seen.add(c["id"])
            out.writerow([v["id"], v["lang"], clean(v["text"])[:120], c["id"], text,
                          c["likes"], c["replies"], c["published_at"], c["author"]["username"]])

print(f"{len(seen)} comments from {len(videos)} videos")
```

That is the worked example: 1 search and 10 comment pages, about 500 comments. For a bigger sample, 20 videos at 4 pages each is 80 comment calls, $0.16 plus the search.

### Step 4: score it

The CSV is ready for whatever does the scoring. Three habits make the result more honest:

- **Weight by likes.** A complaint with 900 likes speaks for more people than one with none. Keep `likes` next to the score and report both the share of comments and the share of likes.
- **Handle language.** Comments carry no language field. `video_lang` is a fair hint for the thread; mixed threads need a multilingual model or a language detector.
- **Read a sample.** Sarcasm and slang fool every model. Read 30 rows of each label before you trust the split.

An LLM works well on batches of 50 to 100 comments with the video caption as context: ask for a label per comment plus the three most common praises and complaints. [TikTok comments for sentiment analysis](https://okdata.online/answers/tiktok-comments-api-sentiment-analysis/) shows that end of the pipeline.

## Good to know

- **Top-level comments only.** Each comment carries its reply count, not the reply text, so your row count will be lower than the video's `metrics.comments`, which includes replies.
- **Order.** Comments come in TikTok's own order; there is no sort parameter. Two pages per video is a sample of what TikTok puts first, not a random sample.
- **Locations.** `ip_location` is filled only where TikTok shows one; treat it as optional.
- **Trimming.** `fields=id,text,likes,replies,published_at` keeps the answer short when a model reads it directly. It does not change the price.
- **Free cases.** A video deleted between search and comments answers `not_found`, which is free, like rate limits and every other error. The same request with the same `Idempotency-Key` within 24 hours comes back with `meta.replayed: true` and no new charge.

For a single video exported to Excel, [exporting TikTok comments to CSV](https://okdata.online/answers/export-tiktok-comments-csv/) is the shorter path.

## What the example costs

One search for air fryer, then 2 pages of comments (about 100) under each of the 5 videos with the most comments

| Endpoint | Calls | Price | Subtotal |
|---|---|---|---|
| [TikTok video search](https://okdata.online/apis/tiktok/videos/search/) | 1 | $0.002 | $0.002 |
| [TikTok video comments](https://okdata.online/apis/tiktok/videos/comments/list/) | 10 | $0.002 | $0.02 |
| Total | 11 |  | $0.022 |

Prices in force when this page was built. A failed call costs nothing.

## In your AI (MCP)

Connect the MCP server once, then say what you want. The agent finds these endpoints, reads their prices and calls them on your balance.

Say: Search TikTok for air fryer, take the 5 videos with the most comments, get about 100 comments under each and tell me what people like and complain about, with a rough positive/negative split.

```json
{
  "endpoint": "tiktok.videos.search",
  "params": {
    "query": "ai agents"
  },
  "idempotency_key": "<a new UUID>"
}
```

MCP: `https://api.okdata.online/mcp`

## Endpoints in this guide

- [TikTok video search](https://okdata.online/apis/tiktok/videos/search/) `tiktok.videos.search`: $0.002 per call · about 30 videos per page
- [TikTok video comments](https://okdata.online/apis/tiktok/videos/comments/list/) `tiktok.videos.comments.list`: $0.002 per call · about 50 comments per page

## More about TikTok

- [TikTok API](https://okdata.online/apis/tiktok/)
- [How to get TikTok Creative Center top ads by API](https://okdata.online/guides/tiktok-creative-center-top-ads/)
- [How to collect TikTok Shop product reviews by keyword](https://okdata.online/guides/tiktok-shop-product-reviews/)
- [Do I need residential proxies to scrape Douyin or TikTok, and what do they cost?](https://okdata.online/answers/do-i-need-proxies-for-social-media-scraping/)
- [TikTok's Research API is only for academics. What can a company use instead?](https://okdata.online/answers/tiktok-research-api-alternative/)
- [Is there an MCP server that gives Claude TikTok, YouTube and X data?](https://okdata.online/answers/tiktok-youtube-x-mcp-server/)
- [TikTokApi keeps throwing EmptyResponseException. Is there a more reliable way to get TikTok data?](https://okdata.online/answers/tiktokapi-emptyresponseexception/)
- [Which TikTok comments API can I use for sentiment analysis?](https://okdata.online/answers/tiktok-comments-api-sentiment-analysis/)
- [How long should I cache social media API results to avoid paying twice?](https://okdata.online/answers/cache-social-media-api-results/)
- [Official platform APIs vs third-party data APIs (2026)](https://okdata.online/compare/official-apis-vs-data-apis/)
- [How to choose a social media data API (2026)](https://okdata.online/compare/social-media-data-apis/)
- [Comments API](https://okdata.online/roles/posts-comments-list/)
- [Post search API](https://okdata.online/roles/posts-search/)
