Douyin Comments API

POST

API health

24h health
Normal
24h average time
—
  • Healthy / normal
  • Available
  • Limited
  • Mostly down
Normal

Pull viewer comments on a Douyin video, with likes, reply count, IP region, hot-comment and author-liked flags, mentions and any images. Pass back next_page_token as page_token to page through the top-level comments.

Douyin Comments reads the comments under one video, given the video's url. Each row carries the text, likes, reply count, the commenter's nickname and ID, the IP region and the publish time. Use it to hear what viewers say about a video: sentiment and reputation analysis, product feedback, or finding the most engaged viewers.

A call without page_token reads only the first batch of comments, with some replies; to read every top-level comment, start with an empty page_token and page through. liked_by_author marks comments the video's author liked, and is_reply with reply_to_id lets you put each reply back under the comment it answers. ip_location is the region Douyin displays, not an address the commenter entered.

Price $0.56 per 1,000 requests ($0.000556 per call). Failed calls and empty results are not charged. Every 20 rows you ask for count as one call: limit sets the charge, and blocks that come back with no rows are not charged. Synchronous. For slow jobs add "mode": "async" to the body, take the job_id and poll.

AI prompt

Paste this into your AI assistant. It already holds this endpoint's parameters, response fields and an example request, so the assistant can ask what you need and then write the scraper.

Please help me write a data collection script with the EveryInfra Douyin Comments endpoint (douyin/comments).

Endpoint contract:
- Request: POST https://api.everyinfra.com/api/v1/social with the header Authorization: Bearer <API key>. Read the key from the EVERYINFRA_API_KEY environment variable and never hard-code it.
- In the request body, set platform to douyin and action to comments, and put the parameters inside params.
- Required parameters:
  - url: Full URL of the target Douyin video, formatted as https://www.douyin.com/video/<video_id>. Fetches video details in video, comments in comments, or audio transcripts in transcript.
- Optional parameters:
  - page_token: Page token for user_posts and comments. To start paging, send an empty string page_token="".
  - limit: The most rows to return in this call, an integer from 1 to 150. The default applies when you leave it out, and a call can return fewer rows. Larger values return 422 before any charge. (default: 20)
- Returns a list of records. Main fields of each record: next_page_token (Page token (user_posts / comments): pas…), id, text, like_count, reply_count, author_name, author_id, ip_location (IP region Douyin displays (set by the p…), is_hot (Whether the comment carries Douyin's ho…), is_reply (Whether the row is a reply), reply_to_id (ID of the comment this reply answers), posted_at; 18 fields in total, full list at https://api.everyinfra.com/api/v1/social/catalog?platform=douyin.
- Example request body:
{
  "platform": "douyin",
  "action": "comments",
  "params": {
    "url": "https://www.douyin.com/video/7633646113853104116"
  }
}
- Price: $0.56 per 1,000 requests; failed and empty results are not charged.
- For dozens or hundreds of targets, add "mode": "async" to the body: you get a job_id at once and poll GET https://api.everyinfra.com/api/v1/jobs/{job_id} for the result.
- On 422, fix the request using the suggested parameter names and allowed values in the error; on 429 or 503, wait for Retry-After and try again.

Before writing code, ask me which targets I need, how many, which fields, and what output format I want; then confirm the plan and the rough cost with me.

Request parameters

NameInTypeRequiredDefaultDescription
AuthorizationheaderstringYes-Bearer followed by your API key. Create it in the console; never put it in a URL or a code repository.
platformbodystringYesdouyinPlatform identifier, fixed value.
actionbodystringYescommentsCapability identifier, fixed value.
urlbody.paramsNot declaredYes-Full URL of the target Douyin video, formatted as https://www.douyin.com/video/<video_id>. Fetches video details in video, comments in comments, or audio transcripts in transcript. Do not pass user profile or search page URLs.
page_tokenbody.paramsNot declaredNo-Page token for user_posts and comments. To start paging, send an empty string page_token=""; then pass back the previous response's next_page_token exactly as received to get the next page, keeping every other parameter unchanged. Tokens last 24 hours and only work for the same account and the same parameters; an expired or mismatched token returns 422, so start again from the first page. On the last page the response has no next_page_token (pagination.has_more is false). Each user_posts page is one call and holds up to 100 rows, newest first, and is not filtered by since (filter by posted_at on your side if you need a date window). comments pages hold up to 50 top-level comments and are priced per block of rows: every 20 rows count as one call, so a page counts as 3 calls for its 50 rows (a smaller limit counts that many rows), and blocks that come back with no rows are not charged. Without page_token the call is a single fetch: user_posts returns the newest batch (since applies) and comments returns only the head of the list, replies included, also at one call per 20 rows: 20 rows by default and at most about 50-60 however high limit is, usually with no next_page_token.
limitbody.paramsinteger (1–150)No20The most rows to return in this call, an integer from 1 to 150. The default applies when you leave it out, and a call can return fewer rows. Larger values return 422 before any charge.

Code samples

bash
curl -X POST 'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer $EVERYINFRA_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "platform": "douyin",
  "action": "comments",
  "params": {
    "url": "https://www.douyin.com/video/7633646113853104116"
  }
}'

[OpenAPI definition (JSON)]Samples read the key from the EVERYINFRA_API_KEY environment variable; copied code never contains your key.

Response example

Real response

Captured September 26, 2026 at 08:56 (UTC) by calling this API with the parameters in the code sample above. results and count are that call's real response with personal information (names, handles, avatars, profile links, contact details) removed; the list keeps the first 2. id, billing and quota differ on every call, so only their shape is shown.

json
{
  "id": "req_…",
  "platform": "douyin",
  "action": "comments",
  "results": [
    {
      "id": "(已隐去)",
      "text": "也夸夸我好吗?毕竟辛苦了大半天",
      "like_count": 36358,
      "reply_count": 3916,
      "author_name": "(已隐去)",
      "author_id": "(已隐去)",
      "ip_location": "(已隐去)",
      "liked_by_author": false,
      "is_reply": false,
      "posted_at": "2026-05-16T07:44:26+00:00",
      "platform": "douyin"
    },
    {
      "id": "(已隐去)",
      "text": "女人也可以做漂亮饭[抠鼻][抠鼻][抠鼻][抠鼻]",
      "like_count": 7615,
      "reply_count": 645,
      "author_name": "(已隐去)",
      "author_id": "(已隐去)",
      "ip_location": "(已隐去)",
      "liked_by_author": false,
      "is_reply": false,
      "posted_at": "2026-05-12T15:26:16+00:00",
      "platform": "douyin"
    }
  ],
  "next_page_token": …,
  "pagination": { … },
  "count": 42,
  "billing": {
    "charged": …,
    "charged_usd": …,
    "balance_after_usd": …,
    …
  },
  "quota": { … }
}

Response fields

Business data is in results. The table lists the fields a record can contain; values the platform does not show are never made up.

FieldMeaning
next_page_tokenPage token (user_posts / comments): pass it back unchanged as page_token to fetch the next page, keeping the other parameters the same; valid for 24 hours. Every row of a page carries the same value, which also appears at the top level of the response. Absent on the last page. Comment pages walk all top-level comments page by page.
idThe record's unique ID on the platform. Unique only within one platform; IDs can repeat across platforms.
textBody text with HTML removed, returned in full and never cut short (on a few platforms the list results themselves carry only an excerpt; the platform's field notes say so).
like_countLikes. null means the platform or this capability does not disclose it; it is not 0.
reply_countReplies, usually replies to a comment. null means not disclosed.
author_nameAuthor's display name.
author_idAuthor's unique ID on the platform.
ip_locationIP region Douyin displays (set by the platform, not entered by the user).
is_hotWhether the comment carries Douyin's hot-comment badge (comments).
is_replyWhether the row is a reply.
reply_to_idID of the comment this reply answers.
posted_atPublish time in ISO 8601, UTC (for example 2026-08-07T12:34:56+00:00). Non-standard strings from the platform are passed through as is, so parse defensively. null means the platform does not disclose it.
video_idID of the video the comment belongs to (comments).
platformSource platform identifier, the same as platform in the request (for example xiaohongshu, tiktok).
liked_by_authorWhether the video's author liked the comment; comments the author liked tend to carry more weight.
author_avatar_urlAuthor avatar image URL: the creator on search, user_posts and video rows, the commenter on comments rows.
author_uidNumeric user ID of the author (on comments, of the commenter). author_id is the secUid; both identify the same person.
imagesArray of image links in the platform's display order; absent when there are no images.
mentioned_usersPeople @-mentioned in the comment, each with user_id (secUid), uid (numeric ID) and nickname. Absent when nobody is mentioned.

FAQ

How do I read all the comments on a video?

Send page_token as an empty string for the first page, then pass each page's next_page_token back unchanged with the other parameters the same. Pages hold up to 50 top-level comments, the last page has no next_page_token, and tokens last 24 hours. A call without page_token returns only the first 50 to 60 or so comments, replies included, and usually no next_page_token.

How do I tell replies from top-level comments?

Check is_reply: when it is true the row is a reply, and reply_to_id is the ID of the comment it answers. With those two fields you can rebuild the thread, while reply_count tells you how many replies each comment has.

Which comments should I read first?

Start with rows where liked_by_author is true: the video's author liked them personally, so they tend to carry the most weight. Then sort by like_count to see which views other viewers agree with most.

Errors and billing

401
Missing or invalid key. Authentication runs before parameter checks, so unauthenticated requests never see the parameter schema.
422
Wrong parameter name or value. The error lists the parameters and allowed values this capability accepts and the closest match; it happens before any charge.
402
Insufficient balance. Top up first.
429
The account's per-minute request limit was reached (all of its API keys count together; a key's own lower limit applies first). Wait for Retry-After and try again; a rate package in the console raises the limit.
503
Could not complete right now. Any charge for the call goes back to your balance automatically, and the billing receipt in the response states the actual outcome, including when it is not yet known. Do not resend blindly.
200 empty
The request completed without data and is not charged (billing.reason = empty_result_refunded).