> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-fetch.io/llms.txt
> Use this file to discover all available pages before exploring further.

# TikTok comments

> Comments and full reply threads from TikTok videos. scraper_type tiktok_comments.

`tiktok_comments` collects the comments on TikTok videos, and their replies if you ask. One result is one comment or
one reply. Rows have the same fields as [Instagram comments](https://docs.go-fetch.io/scrapers/instagram-comments.md), so one parser reads both.

## Run it

```python Python theme={null}
import os

from gofetch import GoFetchClient

client = GoFetchClient(api_key=os.environ["GOFETCH_API_KEY"])

run = client.actor("tiktok_comments").call(run_input={
    "handles": ["duolingo"],
    "maxPosts": 3,
    "maxComments": 300,
})

for comment in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(comment["postUrl"], comment["likesCount"], comment["text"])
```

```bash cURL theme={null}
curl https://go-fetch.io/api/v1/jobs/create/ \
  -H "X-API-Key: $GOFETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scraper_type": "tiktok_comments", "config": {"handles": ["duolingo"], "maxPosts": 3, "maxComments": 300}}'
```

## Inputs

Send `directUrls`, `handles`, or both, in `config`. A video found through both is collected once.

| Field | Type | Default | What it does |
| - | - | - | - |
| `directUrls` | list of URLs | | Video links containing `/video/<id>` or `/photo/<id>`. Short links (`vm.tiktok.com/...`) are skipped. |
| `handles` | list of text | | Accounts, with or without `@`. Their most recent videos are found for you. |
| `maxPosts` | integer | `10` | Videos per handle, up to 1,000. Not used for `directUrls`. |
| `maxComments` | integer | no cap | The budget for the whole job, comments and replies together, up to 1,000,000. The job stops cleanly when it is reached. |
| `maxCommentsPerPost` | integer | `500` | Top-level comments per video, up to 100,000. |
| `includeReplies` | true / false | `false` | Also collect reply threads, for comments that have replies. Each reply is a billed result. JSON `true` or `false` only: anything else, such as the string `"false"`, is refused with `400`. |
| `maxRepliesPerComment` | integer | `50` | Replies per comment, up to 10,000. |
| `onlyCommentsNewerThan` | date or date-time | | Only comments and replies posted on or after this time, each judged by its own time. Not in the future. |
| `maxTotalChargeUsd` | number | | A spending cap. If you leave out `maxComments`, it becomes what the cap buys. See [Billing](https://docs.go-fetch.io/billing.md#cap-a-job-with-maxtotalchargeusd). |

> [!TIP]
>
> Always set `maxComments`. It is your cost ceiling. Without it, credit is reserved for `maxPosts` ×
> `maxCommentsPerPost` comments (twice that with replies) when the job is created, also for `directUrls`.

`enrichCommenterProfiles` is accepted (as JSON `true` or `false` only) but does nothing on TikTok. With `true`, the
job reports `scraper_metadata.enrichment: {"enabled": false, "reason": "disabled_for_tiktok"}` and adds a
warning to its log.

## Output

One row per comment or reply. Every field is always present. A real row from a job on @duolingo's videos; the
commenter's handle, name, ids and picture are replaced with placeholders here:

```json theme={null}
[
  {
    "type": "comment",
    "platform": "tiktok",
    "postUrl": "https://www.tiktok.com/@duolingo/video/7696579447217982750",
    "commentUrl": "https://www.tiktok.com/@duolingo/video/7696579447217982750?comment_id=7696582275705930518",
    "parentCommentUrl": null,
    "id": "7696582275705930518",
    "text": "great video...",
    "ownerUsername": "example_commenter_1",
    "ownerProfilePicUrl": "https://example.com/placeholder-avatar.jpg",
    "timestamp": "2026-10-14T17:50:26.000Z",
    "likesCount": 5,
    "repliesCount": 1,
    "replies": null,
    "parentCommentId": null,
    "isReply": false,
    "owner": {
      "username": "example_commenter_1",
      "id": "0000000000000000000",
      "profile_pic_url": "https://example.com/placeholder-avatar.jpg",
      "is_verified": false,
      "fbid_v2": null,
      "full_name": "Example Commenter 1",
      "is_private": null,
      "is_mentionable": null,
      "profile_pic_id": null,
      "latest_reel_media": null,
      "sec_uid": "MS4wLjABAAAA-example-placeholder"
    }
  },
  {
    "type": "comment",
    "platform": "tiktok",
    "postUrl": "https://www.tiktok.com/@duolingo/video/7696579447217982750",
    "commentUrl": "https://www.tiktok.com/@duolingo/video/7696579447217982750?comment_id=7696658536915698445",
    "parentCommentUrl": null,
    "id": "7696658536915698445",
    "text": "Duolingo u proud..",
    "ownerUsername": "example_commenter_2",
    "ownerProfilePicUrl": "https://example.com/placeholder-avatar.jpg",
    "timestamp": "2026-10-14T22:46:43.000Z",
    "likesCount": 1,
    "repliesCount": 0,
    "replies": null,
    "parentCommentId": null,
    "isReply": false,
    "owner": {
      "username": "example_commenter_2",
      "id": "0000000000000000000",
      "profile_pic_url": "https://example.com/placeholder-avatar.jpg",
      "is_verified": false,
      "fbid_v2": null,
      "full_name": "Example Commenter 2",
      "is_private": null,
      "is_mentionable": null,
      "profile_pic_id": null,
      "latest_reel_media": null,
      "sec_uid": "MS4wLjABAAAA-example-placeholder"
    }
  }
]
```

| Field | Type | What it holds |
| - | - | - |
| `type`, `platform` | text | `comment` (replies too) and `tiktok`. |
| `postUrl` | URL | The video, as you sent it, or as found from a handle. |
| `commentUrl` | URL | A link that opens the video at the comment. |
| `parentCommentUrl` | URL or null | The parent comment's link, on a reply. |
| `id` | text | The comment's id. It is text because it is too long for a JavaScript number. |
| `text` | text or null | The comment. |
| `ownerUsername`, `ownerProfilePicUrl` | text or null | The commenter's handle and picture. |
| `timestamp` | date-time or null | When it was posted (ISO 8601, UTC). |
| `likesCount` | integer or null | Likes. |
| `repliesCount` | integer or null | TikTok's reply count on a top-level comment; it can differ from the replies collected. Always `null` on a reply. |
| `replies` | null | Always `null`: replies are rows of their own. |
| `parentCommentId`, `isReply` | text or null, true / false | The parent's id, on a reply. |
| `owner` | object | The commenter: `username`, `id`, `profile_pic_url`, `is_verified`, `full_name`, `sec_uid`. `is_private` and the other keys are always `null` on TikTok. |
| `raw` | object | TikTok's original comment object, unchanged. Its shape can change without notice. |

## What logged-out means here

**You get:** comments and replies on public videos, with the commenter's handle, name, picture and verified badge.

**Not available:**

* Comments on deleted, private or region-blocked videos, or videos with comments turned off. These count in
  `posts_unavailable` and return no rows.
* Whether a commenter's account is private.
* Videos of private, deleted, banned or blocked accounts given as `handles`. They are skipped without a per-handle
  report; if no video is found at all, the job fails.

## Completeness

`scraper_metadata.completeness`:

| Key | What it says |
| - | - |
| `posts_processed`, `posts_complete` | Videos attempted, and videos whose comments were collected to the end. |
| `posts_truncated` | Videos stopped by one of your caps. |
| `posts_throttled` | Videos TikTok stopped serving partway; the rows collected are kept. |
| `posts_unavailable`, `posts_failed` | Videos with nothing to read, and videos that failed. |
| `comments_collected`, `replies_collected` | Rows of each kind. |
| `all_posts_failed` | Every video ended in an error. With some rows collected the job still completes. |
| `posts` | Per video: `aweme_id`, `post_url`, `comments_collected`, `status` (`complete`, `truncated`, `throttled`, `unavailable`, `error` or `aborted`), `truncated`, `has_more`. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.