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 sharedGET /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 eachtargets[]element are listed under each endpoint's "target fields". One run may hold multiple targets (per-target outcome is reported in thetasks[]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) |
profileandprofile-urlreturn the same output; they differ only in the input entry:profileis username-first,profile-urlis 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}untilsucceeded, then page throughGET /v1/scraper/runs/{id}/records?page=1&pageSize=20, or download the full result viaGET /v1/scraper/runs/{id}/download?format=json|csv|excel(see Quick Start for the end-to-end example).
Next Steps
- Platform guides: X · Instagram · Facebook · LinkedIn · Google · YouTube · Amazon
- Synchronous search: Google SERP
- Auth & Error Handling — Unified envelope, run state machine, billing & error codes
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.
