Developer Docs

TikTok Scraper API

Scraping is asynchronous: submit run → poll → fetch data. For the full flow see Quick Start; for the shared envelope / run state machine / billing / error codes see Auth & Error Handling. This page only lists each endpoint's target fields and output fields.


Quick Reference

  • Base URL: https://api.antsdata.com/v1
  • Method & path: submitting a run is always POST /v1/scraper/tiktok/<resource>; polling / fetching / downloading use the shared GET /v1/scraper/runs/{id} (see Quick Start)
  • Auth: header Authorization: Bearer ants_xxx (static API key)
  • Content-Type: application/json
  • Request body: always { "deliveryMode": "async", "recordLimit": 1000, "targets": [ … ] }; the fields of each targets[] element are listed under each endpoint's "target fields". One run may hold multiple targets (per-target outcome is reported in the tasks[] returned by polling).

💡 You can also use deliveryMode: "sync" (small jobs block until terminal, auto fallback to polling on timeout) — see quick-start · Sync mode.


Endpoints at a Glance

Endpoint Path Description
Account profile (by username) POST /v1/scraper/tiktok/profile Extract an account's public profile by username
Account profile (by URL) POST /v1/scraper/tiktok/profile-url Extract an account's public profile by profile URL
Account videos POST /v1/scraper/tiktok/videos Extract videos published by an account
Hashtag videos POST /v1/scraper/tiktok/hashtag Extract videos under a hashtag
Video search POST /v1/scraper/tiktok/search Search videos by keyword
Comments POST /v1/scraper/tiktok/comments Extract video comments (replies optional)

profile and profile-url return the same output; they differ only in the input entry: profile is username-first, profile-url is URL-first (each endpoint also accepts the other field — supply either one).


Profile — Account Data (by Username)

POST /v1/scraper/tiktok/profile

Target fields (each element of targets[]):

Field Type Required Description
username string one of TikTok username (without @; one of username / profileUrl)
profileUrl string one of Profile URL (URL format; one of username / profileUrl)

Output fields (each item in records' items[] when fetching data):

Field Type Description
userId string Internal TikTok user ID
username string Username
nickname string Nickname
signature string Bio / signature
avatarUrl string Avatar URL
followers number Follower count
following number Following count
totalLikes number Total like count across all videos
videosCount number Total number of videos
isVerified boolean Whether the account is verified
isPrivate boolean Whether the account is private
profileUrl string Profile URL

Submit example:

curl -X POST "https://api.antsdata.com/v1/scraper/tiktok/profile" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveryMode": "async",
    "recordLimit": 1000,
    "targets": [
      { "username": "khaby.lame" },
      { "username": "nike" }
    ]
  }'

Returns HTTP 201 + { "id": <run id>, "status": "queued" }; then poll and fetch data as in Quick Start.


Profile URL — Account Data (by Profile URL)

POST /v1/scraper/tiktok/profile-url

Target fields (each element of targets[]):

Field Type Required Description
profileUrl string one of TikTok profile URL (URL format; one of username / profileUrl)
username string one of TikTok username (without @; one of username / profileUrl)

Output fields (each item in records' items[] when fetching data):

Field Type Description
userId string Internal TikTok user ID
username string Username
nickname string Nickname
signature string Bio / signature
avatarUrl string Avatar URL
followers number Follower count
following number Following count
totalLikes number Total like count across all videos
videosCount number Total number of videos
isVerified boolean Whether the account is verified
isPrivate boolean Whether the account is private
profileUrl string Profile URL

Submit example:

curl -X POST "https://api.antsdata.com/v1/scraper/tiktok/profile-url" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveryMode": "async",
    "recordLimit": 1000,
    "targets": [
      { "profileUrl": "https://www.tiktok.com/@khaby.lame" }
    ]
  }'

Returns HTTP 201 + { "id": <run id>, "status": "queued" }; then poll and fetch data as in Quick Start.


Videos — Account Videos

POST /v1/scraper/tiktok/videos

Target fields (each element of targets[]):

Field Type Required Description
username string TikTok username (without @)
sortBy string Sort: recent (newest) / popular (most popular); default recent
newestPostDate string Latest post date YYYY-MM-DD (only when sortBy=recent)

Output fields (each item in records' items[] when fetching data):

Field Type Description
id string Video ID
webUrl string Video page URL
caption string Video caption
createdAt string Publish time (ISO 8601)
author object Author info
author.username string Username
author.nickname string Nickname
author.userId string User ID
metrics object Engagement metrics
metrics.playCount number View count
metrics.diggCount number Like count
metrics.shareCount number Share count
metrics.commentCount number Comment count
video object Video media details
video.downloadUrl string Watermark-free video URL (empty for image posts)
video.coverUrl string Cover image URL
video.duration number Duration in seconds (0 for image posts)
video.width number Width in px
video.height number Height in px
images array Image-post URLs (set only for image posts, empty for regular videos)
music object Music info
music.id string Music ID
music.title string Track title
music.artist string Artist name
music.coverUrl string Music cover URL
music.playUrl string Music preview URL
hashtags array List of hashtags
mentions array @ mentions

Submit example:

curl -X POST "https://api.antsdata.com/v1/scraper/tiktok/videos" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveryMode": "async",
    "recordLimit": 1000,
    "targets": [
      { "username": "khaby.lame", "sortBy": "popular" }
    ]
  }'

Returns HTTP 201 + { "id": <run id>, "status": "queued" }; then poll and fetch data as in Quick Start.


Hashtag — Hashtag Videos

POST /v1/scraper/tiktok/hashtag

Target fields (each element of targets[]):

Field Type Required Description
hashtag string Hashtag name (without #)

Output fields (each item in records' items[] when fetching data):

Field Type Description
id string Video ID
webUrl string Video page URL
caption string Video caption
createdAt string Publish time (ISO 8601)
author object Author info
author.username string Username
author.nickname string Nickname
author.userId string User ID
metrics object Engagement metrics
metrics.playCount number View count
metrics.diggCount number Like count
metrics.shareCount number Share count
metrics.commentCount number Comment count
video object Video media details
video.downloadUrl string Watermark-free video URL (empty for image posts)
video.coverUrl string Cover image URL
video.duration number Duration in seconds (0 for image posts)
video.width number Width in px
video.height number Height in px
images array Image-post URLs (set only for image posts, empty for regular videos)
music object Music info
music.id string Music ID
music.title string Track title
music.artist string Artist name
music.coverUrl string Music cover URL
music.playUrl string Music preview URL
hashtags array List of hashtags
mentions array @ mentions

Submit example:

curl -X POST "https://api.antsdata.com/v1/scraper/tiktok/hashtag" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveryMode": "async",
    "recordLimit": 1000,
    "targets": [
      { "hashtag": "comedy" }
    ]
  }'

Returns HTTP 201 + { "id": <run id>, "status": "queued" }; then poll and fetch data as in Quick Start.


Search — Keyword Search

POST /v1/scraper/tiktok/search

Target fields (each element of targets[]):

Field Type Required Description
keyword string Search keyword (operators / regex not supported)

Output fields (each item in records' items[] when fetching data):

Field Type Description
id string Video ID
webUrl string Video page URL
caption string Video caption
createdAt string Publish time (ISO 8601)
author object Author info
author.username string Username
author.nickname string Nickname
author.userId string User ID
metrics object Engagement metrics
metrics.playCount number View count
metrics.diggCount number Like count
metrics.shareCount number Share count
metrics.commentCount number Comment count
video object Video media details
video.downloadUrl string Watermark-free video URL (empty for image posts)
video.coverUrl string Cover image URL
video.duration number Duration in seconds (0 for image posts)
video.width number Width in px
video.height number Height in px
images array Image-post URLs (set only for image posts, empty for regular videos)
music object Music info
music.id string Music ID
music.title string Track title
music.artist string Artist name
music.coverUrl string Music cover URL
music.playUrl string Music preview URL
hashtags array List of hashtags
mentions array @ mentions

Submit example:

curl -X POST "https://api.antsdata.com/v1/scraper/tiktok/search" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveryMode": "async",
    "recordLimit": 1000,
    "targets": [
      { "keyword": "web scraping" }
    ]
  }'

Returns HTTP 201 + { "id": <run id>, "status": "queued" }; then poll and fetch data as in Quick Start.


Comments — Video Comments

POST /v1/scraper/tiktok/comments

Target fields (each element of targets[]):

Field Type Required Description
videoUrl string one of Video / photo-post URL (one of videoUrl / videoId)
videoId string one of Numeric aweme_id (one of videoUrl / videoId)
commentsLimit number Max top-level comments (default 20, max 1000)
includeReplies boolean Whether to expand second-level replies (default false)
repliesLimit number Max replies per comment (default 3, max 20; ignored when includeReplies=false)

Output fields (each item in records' items[] when fetching data):

Field Type Description
cid string Comment ID
aweme_id string ID of the video the comment belongs to
text string Comment text
create_time number Publish timestamp (Unix seconds)
digg_count number Like count
reply_comment_total number Total number of replies (top-level comments only)
comment_language string Comment language code
author_pin boolean Whether pinned by the author
is_author_digged boolean Whether the video author liked the comment
status number Comment status (1 means normal)
user object Comment author
user.uid string User ID
user.unique_id string Username
user.nickname string Nickname
user.sec_uid string secUid
user.avatar_thumb object Avatar (direct URLs in url_list)
image_list array Comment images (only for image comments; original URLs in origin_url.url_list)
text_extra array @ mentions / hashtag structure
reply_comment array Inline second-level replies (returned when includeReplies=true)
reply_comment.cid string Reply ID
reply_comment.text string Reply content
reply_comment.create_time number Reply timestamp (Unix seconds)
reply_comment.digg_count number Reply like count
reply_comment.reply_id string Parent comment ID
reply_comment.reply_to_username string Username the reply is directed to
reply_comment.user object Reply author (same structure as the top-level user)

Submit example:

curl -X POST "https://api.antsdata.com/v1/scraper/tiktok/comments" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveryMode": "async",
    "recordLimit": 1000,
    "targets": [
      {
        "videoUrl": "https://www.tiktok.com/@khaby.lame/video/7641693768831225101",
        "commentsLimit": 100,
        "includeReplies": true
      }
    ]
  }'

Returns HTTP 201 + { "id": <run id>, "status": "queued" }; then poll and fetch data as in Quick Start.


Fetching Data

After submitting, poll GET /v1/scraper/runs/{id} until succeeded, then page through GET /v1/scraper/runs/{id}/records?page=1&pageSize=20, or download the full result via GET /v1/scraper/runs/{id}/download?format=json|csv|excel (see Quick Start for the end-to-end example).


Next Steps


FAQ

Q: Can one run scrape multiple accounts / hashtags / keywords?

Yes. targets is an array — a single run can hold multiple targets, and each target's outcome is reported in the tasks[] returned by polling (see Auth & Error Handling).

Q: What is the difference between profile and profile-url?

Both return exactly the same output; they differ only in the input entry: profile scrapes by username, profile-url scrapes by profile URL. Each endpoint also accepts the other field (username / profileUrl, supply either one) — pick the endpoint that matches the identifier you already have.

Q: How are private or nonexistent accounts handled?

That target is marked failed in tasks[] with an errorMessage while the other targets still produce data; failed targets are not billed (partial success is still settled by the number of successful records).

Q: Why does the videos endpoint no longer take searchMode?

The capability once merged under searchMode (user/hashtag/keyword) is now split into three dedicated endpoints: /videos for an account's videos, /hashtag for a hashtag, and /search for keyword search. Choose the endpoint directly — searchMode is no longer accepted.

Q: What format is the comments timestamp?

create_time is a Unix second-level timestamp (e.g. 1781827200); convert it to ISO 8601 yourself if you need a human-readable time.

Q: Is the data real-time?

Yes. Every run scrapes in real time and returns the target platform's current data.