Skip to content
truescrape

TikTok API

The TrueScrape TikTok API exposes 28 public endpoints covering One TikTok ad, Search the TikTok Ads Library and Collection videos. Every call is a GET against public, logged-out pages and returns the same unified schema as every other platform here. Calls cost 1 credit each. A cache hit is free, and a failed or empty response is never charged.

Endpoints

EndpointReturnsCreditsCacheableBatchable
/v1/tiktok/ad-library/adOne TikTok ad1yesyes
/v1/tiktok/ad-library/searchSearch the TikTok Ads Library1yesno
/v1/tiktok/collection/videosCollection videos1yesyes
/v1/tiktok/comment-repliesReplies to a comment1yesyes
/v1/tiktok/commentsComments on a video1yesyes
/v1/tiktok/creators/popularPopular creators1yesyes
/v1/tiktok/followersAccounts following a creator1yesyes
/v1/tiktok/hashtagHashtag details1yesyes
/v1/tiktok/hashtag-videosVideos using a hashtag1yesyes
/v1/tiktok/liveLive stream info1yesyes
/v1/tiktok/playlist-videosVideos in a playlist1yesyes
/v1/tiktok/playlistsA creator's playlists1yesyes
/v1/tiktok/productProduct details1yesyes
/v1/tiktok/profileProfile details1yesyes
/v1/tiktok/profile/regionCreator region1yesyes
/v1/tiktok/search/suggestionsSearch suggestions1yesyes
/v1/tiktok/shop/product/reviewsProduct reviews1yesyes
/v1/tiktok/shop/productsSeller's product catalogue1yesyes
/v1/tiktok/shop/searchSearch TikTok Shop1yesyes
/v1/tiktok/songSound / song details1yesyes
/v1/tiktok/song-videosVideos using a sound1yesyes
/v1/tiktok/songs/popularPopular songs1yesyes
/v1/tiktok/transcriptVideo transcript1yesyes
/v1/tiktok/user-videosVideos posted by a creator1yesyes
/v1/tiktok/user/showcaseCreator's product showcase1yesyes
/v1/tiktok/videoVideo or photo-post details1yesyes
/v1/tiktok/videos/popularPopular videos1yesyes

Reference

GET/v1/tiktok/collection/videos1 creditcacheablebatchable

Collection videos

Videos in a public TikTok collection, a creator-curated playlist of other people's posts as well as their own. **Required:** Pass either url or collection_id.

ParameterTypeRequiredDescription
urlstringnoCollection URL, e.g. https://www.tiktok.com/@nasa/collection/Artemis-7123…
collection_idstringnoNumeric collection id
countnumbernoItems per page (default 20, max 30)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of Post in data.items.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
idstringalways
typevideo | short | image | carousel | text | live | story | reel | audio | album | episode | unknownalwaysWhat kind of post this is. `short` and `reel` are short-form video formats, `live` is a live stream or a recording of one, `carousel` holds several images or videos, `audio` is a music track, `album` is an album, `episode` is a podcast episode, and `unknown` covers anything else.
urlstring | nullalways
titlestring | nullalways
textstring | nullalwaysThe post's text: a caption, a description or the message body.
authorIdstring | nullalways
authorHandlestring | nullalways
authorNamestring | nullalways
thumbnailUrlstring | nullalways
mediaUrlsstring[]always
durationSecondsnumber | nullalways
viewCountnumber | nullalwaysViews. Null means the platform did not expose a count, which is not the same as zero.
likeCountnumber | nullalwaysLikes, or the platform's nearest equivalent. Null means not exposed, not zero.
commentCountnumber | nullalwaysComments. Null means not exposed, not zero.
shareCountnumber | nullalwaysShares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero.
hashtagsstring[]alwaysHashtags or the platform's own topic tags, without the leading #.
mentionsstring[]alwaysHandles mentioned in the post text, without the leading @.
taggedUsersstring[]may be absentUsernames tagged in the media itself, as distinct from `mentions`, which come from the caption text. Absent when the platform does not report tags; an empty array means it reports none.
isSponsoredboolean | nullalwaysWhether the platform labels the post as an ad, promoted content or a paid partnership.
publishedAtstring | nullalwaysWhen the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago".
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/tiktok/collection/videos?cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/collection/videos?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/collection/videos",
    params={
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/collection/videos
Open the full playground
GET/v1/tiktok/comment-replies1 creditcacheablebatchable

Replies to a comment

The reply thread under one TikTok comment. parentId on each reply points back at the comment it answers, so nested threads reconstruct cleanly.

ParameterTypeRequiredDescription
comment_idstringyesid of the parent comment, from tiktok.comments
urlstringyesThe video the comment is on: URL, share link, or numeric id
countnumbernoItems per page (default 20, max 50)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of Comment in data.items.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
idstringalways
postIdstring | nullalways
parentIdstring | nullalwaysId of the comment this one replies to. Null on a top-level comment.
textstringalways
authorIdstring | nullalways
authorHandlestring | nullalways
authorNamestring | nullalways
authorAvatarUrlstring | nullalways
likeCountnumber | nullalways
replyCountnumber | nullalways
isPinnedboolean | nullalways
isAuthorReplyboolean | nullalwaysWhether the comment was written by the author of the post.
publishedAtstring | nullalwaysWhen the comment was posted. Usually an ISO 8601 timestamp; some platforms expose only relative text such as "2 days ago".
curl
curl "$API/v1/tiktok/comment-replies?comment_id=%3Ccomment_id%3E&url=8XkPqR2nLvE&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  comment_id: '<comment_id>',
  url: '8XkPqR2nLvE',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/comment-replies?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/comment-replies",
    params={
        "comment_id": "<comment_id>",
        "url": "8XkPqR2nLvE",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/comment-replies
Open the full playground
GET/v1/tiktok/creators/popular1 creditcacheablebatchable

Popular creators

Creators trending in a market, from TikTok's own Creative Center leaderboard. Filter by country, follower band and category.

ParameterTypeRequiredDescription
regionstringnoTwo-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market.
period7 | 30 | 120noTrailing window in days: 7, 30 or 120defaults to 7
follower_band1k-10k | 10k-100k | 100k-1m | 1m+noRestrict to creators in this follower range
countnumbernoItems per page (default 20, max 50)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of Creator in data.items.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
idstringalwaysThe platform's own id for the account, such as a channel id or a numeric user id, always as a string.
handlestring | nullalwaysThe account handle without the leading @. Null when the platform has no handles.
displayNamestring | nullalways
biostring | nullalways
avatarUrlstring | nullalways
bannerUrlstring | nullalways
urlstring | nullalways
verifiedboolean | nullalwaysWhether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it.
followerCountnumber | nullalwaysFollowers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it.
followingCountnumber | nullalways
postCountnumber | nullalwaysPosts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published.
viewCountnumber | nullalwaysLifetime views across the account, where the platform exposes a total.
likeCountnumber | nullmay be absentTotal likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it.
isPrivateboolean | nullalways
isBusinessboolean | nullalwaysWhether the platform classifies the account as a business or organisation rather than a person or creator. Null where the platform draws no such line or does not expose it. On Facebook every Page counts, including Pages for public figures.
categorystring | nullalwaysA label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform.
locationstring | nullalwaysLocation as the platform shows it: a city, a country, a region code or an address, depending on the platform.
externalLinksstring[]alwaysLinks the account lists on its profile, such as a website or other social accounts.
createdAtstring | nullalwaysWhen the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile.
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/tiktok/creators/popular?cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/creators/popular?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/creators/popular",
    params={
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/creators/popular
Open the full playground
GET/v1/tiktok/followers1 creditcacheablebatchable

Accounts following a creator

The public follower list for a TikTok account, newest first. TikTok caps how deep this list can be walked regardless of paging. Requires a configured TikTok signer.

ParameterTypeRequiredDescription
handlestringyesHandle (@nike), or a full tiktok.com profile URL
countnumbernoItems per page (default 30, max 50)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of Creator in data.items.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
idstringalwaysThe platform's own id for the account, such as a channel id or a numeric user id, always as a string.
handlestring | nullalwaysThe account handle without the leading @. Null when the platform has no handles.
displayNamestring | nullalways
biostring | nullalways
avatarUrlstring | nullalways
bannerUrlstring | nullalways
urlstring | nullalways
verifiedboolean | nullalwaysWhether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it.
followerCountnumber | nullalwaysFollowers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it.
followingCountnumber | nullalways
postCountnumber | nullalwaysPosts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published.
viewCountnumber | nullalwaysLifetime views across the account, where the platform exposes a total.
likeCountnumber | nullmay be absentTotal likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it.
isPrivateboolean | nullalways
isBusinessboolean | nullalwaysWhether the platform classifies the account as a business or organisation rather than a person or creator. Null where the platform draws no such line or does not expose it. On Facebook every Page counts, including Pages for public figures.
categorystring | nullalwaysA label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform.
locationstring | nullalwaysLocation as the platform shows it: a city, a country, a region code or an address, depending on the platform.
externalLinksstring[]alwaysLinks the account lists on its profile, such as a website or other social accounts.
createdAtstring | nullalwaysWhen the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile.
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/tiktok/followers?handle=%40mkbhd&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  handle: '@mkbhd',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/followers?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/followers",
    params={
        "handle": "@mkbhd",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/followers
Open the full playground
GET/v1/tiktok/hashtag1 creditcacheablebatchable

Hashtag details

Stats for a TikTok hashtag: total videos and total views, plus its description and cover. Read straight off the tag page, so it needs no signer.

ParameterTypeRequiredDescription
hashtagstringyesTag without the # (fyp), or a full /tag/ URL

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns an object with platform, id, name, description, url, coverUrl, videoCount, viewCount, isCommerce, fetchedAt.

Fields
FieldTypePresent
platform"tiktok"always
idstringalways
namestringalways
descriptionstring | nullalways
urlstringalways
coverUrlstring | nullalways
videoCountnumber | nullalways
viewCountnumber | nullalways
isCommerceboolean | nullalways
fetchedAtstringalways
curl
curl "$API/v1/tiktok/hashtag?hashtag=%3Chashtag%3E&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  hashtag: '<hashtag>',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/hashtag?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/hashtag",
    params={
        "hashtag": "<hashtag>",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/hashtag
Open the full playground
GET/v1/tiktok/live1 creditcacheablebatchable

Live stream info

Details of a creator's stream while they are live: room id, title, cover, current viewers and start time. A creator who is not live returns empty_result, a real answer that costs nothing, so this works as a cheap "are they live?" poll. Pass room_id (from a previous response's roomId) to look the room up directly on TikTok's own webcast surface. No third-party provider is involved. On the room_id path handle may come back empty if the webcast payload omits the room owner. **Required:** Pass either handle or room_id.

ParameterTypeRequiredDescription
handlestringnoHandle (@nike), or a full tiktok.com profile URL
room_idstringnoTikTok LIVE room id, e.g. from a previous tiktok.live response's roomId

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns an object with platform, roomId, handle, title, coverUrl, viewerCount, startedAt, url, creator, fetchedAt.

Fields
FieldTypePresent
platform"tiktok"always
roomIdstringalways
handlestringalways
titlestring | nullalways
coverUrlstring | nullalways
viewerCountnumber | nullalways
startedAtstring | nullalways
urlstringalways
creatorCreatoralways
fetchedAtstringalways
curl
curl "$API/v1/tiktok/live?cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/live?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/live",
    params={
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
GET/v1/tiktok/song1 creditcacheablebatchable

Sound / song details

Details for a TikTok sound: title, artist, album, cover, clip length, and how many videos use it.

ParameterTypeRequiredDescription
songstringyesMusic id, or a full tiktok.com/music/… URL

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns an object with platform, id, title, authorName, album, url, coverUrl, playUrl, durationSeconds, isOriginalSound, videoCount, fetchedAt.

Fields
FieldTypePresentDescription
platform"tiktok"always
idstringalways
titlestringalways
authorNamestring | nullalways
albumstring | nullalways
urlstringalways
coverUrlstring | nullalways
playUrlstring | nullalways
durationSecondsnumber | nullalways
isOriginalSoundboolean | nullalwaysTrue when the sound originated on TikTok rather than a licensed track.
videoCountnumber | nullalways
fetchedAtstringalways
curl
curl "$API/v1/tiktok/song?song=%3Csong%3E&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  song: '<song>',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/song?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/song",
    params={
        "song": "<song>",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
GET/v1/tiktok/song-videos1 creditcacheablebatchable

Videos using a sound

TikToks built on a given sound: the endpoint behind "who is using my track", with a cursor for the next page.

ParameterTypeRequiredDescription
songstringyesMusic id, or a full tiktok.com/music/… URL
countnumbernoItems per page (default 30, max 30)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of Post in data.items.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
idstringalways
typevideo | short | image | carousel | text | live | story | reel | audio | album | episode | unknownalwaysWhat kind of post this is. `short` and `reel` are short-form video formats, `live` is a live stream or a recording of one, `carousel` holds several images or videos, `audio` is a music track, `album` is an album, `episode` is a podcast episode, and `unknown` covers anything else.
urlstring | nullalways
titlestring | nullalways
textstring | nullalwaysThe post's text: a caption, a description or the message body.
authorIdstring | nullalways
authorHandlestring | nullalways
authorNamestring | nullalways
thumbnailUrlstring | nullalways
mediaUrlsstring[]always
durationSecondsnumber | nullalways
viewCountnumber | nullalwaysViews. Null means the platform did not expose a count, which is not the same as zero.
likeCountnumber | nullalwaysLikes, or the platform's nearest equivalent. Null means not exposed, not zero.
commentCountnumber | nullalwaysComments. Null means not exposed, not zero.
shareCountnumber | nullalwaysShares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero.
hashtagsstring[]alwaysHashtags or the platform's own topic tags, without the leading #.
mentionsstring[]alwaysHandles mentioned in the post text, without the leading @.
taggedUsersstring[]may be absentUsernames tagged in the media itself, as distinct from `mentions`, which come from the caption text. Absent when the platform does not report tags; an empty array means it reports none.
isSponsoredboolean | nullalwaysWhether the platform labels the post as an ad, promoted content or a paid partnership.
publishedAtstring | nullalwaysWhen the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago".
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/tiktok/song-videos?song=%3Csong%3E&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  song: '<song>',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/song-videos?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/song-videos",
    params={
        "song": "<song>",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/song-videos
Open the full playground
GET/v1/tiktok/songs/popular1 creditcacheablebatchable

Popular songs

Sounds trending in a market, the endpoint behind music A&R and sync-licensing research. From TikTok's Creative Center.

ParameterTypeRequiredDescription
regionstringnoTwo-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market.
period7 | 30 | 120noTrailing window in days: 7, 30 or 120defaults to 7
countnumbernoItems per page (default 20, max 50)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of object in data.items.

Fields
FieldTypePresentDescription
platform"tiktok"always
idstringalways
titlestringalways
authorNamestring | nullalways
albumstring | nullalways
urlstringalways
coverUrlstring | nullalways
playUrlstring | nullalways
durationSecondsnumber | nullalways
isOriginalSoundboolean | nullalwaysTrue when the sound originated on TikTok rather than a licensed track.
videoCountnumber | nullalways
fetchedAtstringalways
curl
curl "$API/v1/tiktok/songs/popular?cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/songs/popular?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/songs/popular",
    params={
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/songs/popular
Open the full playground
GET/v1/tiktok/transcript1 creditcacheablebatchable

Video transcript

The spoken transcript of a TikTok, as one text block plus timed cues. Returns the ORIGINAL spoken-language track by default rather than whichever track TikTok lists first, so the text reflects what was actually said. Pass language for a specific track. A miss is an error listing what is available, never a silent substitution into another language.

Or see what it returns without a key, in the free TikTok transcript.

ParameterTypeRequiredDescription
urlstringyesVideo URL (preferred), share link, or numeric video id
languagestringnoBCP-47 or ISO-639 code, e.g. "en", "es", "pt-BR". Omit for the original spoken track.

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns one Transcript.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
postIdstringalways
urlstring | nullalways
languagestring | nullalwaysThe transcript's language as the platform labels it, usually a language code such as `en`.
isAutoGeneratedboolean | nullalwaysWhether the platform generated the captions automatically, by speech recognition or machine translation, rather than a person writing them.
textstringalwaysThe full transcript as a single block of text.
cuesobject[]alwaysTimed segments of the transcript.
cues[].startnumberalwaysSeconds from the start of the media.
cues[].endnumber | nullalwaysSeconds from the start of the media. Null when the platform gives no end time.
cues[].textstringalways
durationSecondsnumber | nullalways
sourcecaptions | asr | nullalwaysWhere the transcript came from. `captions`: the platform's own caption track, whether a person wrote it or the platform generated it (see `isAutoGenerated`). `asr`: produced by speech recognition on the audio. Null when this cannot be told.
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/tiktok/transcript?url=8XkPqR2nLvE&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  url: '8XkPqR2nLvE',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/transcript?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/transcript",
    params={
        "url": "8XkPqR2nLvE",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/transcript
Open the full playground
GET/v1/tiktok/user/showcase1 creditcacheablebatchable

Creator's product showcase

Products a creator has pinned to their profile showcase. This is what they are actually promoting, as opposed to what they sell. Requires a configured TikTok signer.

ParameterTypeRequiredDescription
handlestringyesCreator handle, e.g. @charlidamelio
countnumbernoItems per page (default 20, max 50)
cursorstringnopagination.cursor from a previous response
regionstringnoTwo-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market.

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of object in data.items.

Fields
FieldTypePresentDescription
platform"tiktok"always
idstringalways
titlestringalways
urlstring | nullalways
descriptionstring | nullalways
priceobjectalways
price.amountnumber | nullalwaysNumeric amount in major units (12.99, not 1299). Null if unparseable.
price.currencystring | nullalwaysISO-4217 where TikTok gives one. Null means we will not guess.
price.formattedstring | nullalwaysExactly what TikTok displayed, e.g. "$12.99".
originalPriceobjectalways
originalPrice.amountnumber | nullalwaysNumeric amount in major units (12.99, not 1299). Null if unparseable.
originalPrice.currencystring | nullalwaysISO-4217 where TikTok gives one. Null means we will not guess.
originalPrice.formattedstring | nullalwaysExactly what TikTok displayed, e.g. "$12.99".
imageUrlsstring[]always
ratingnumber | nullalwaysStar rating out of 5. Null on a product with no reviews yet.
reviewCountnumber | nullalways
soldCountnumber | nullalways
inStockboolean | nullalways
sellerIdstring | nullalways
sellerNamestring | nullalways
categoryNamestring | nullalways
fetchedAtstringalways
curl
curl "$API/v1/tiktok/user/showcase?handle=%40mkbhd&cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  handle: '@mkbhd',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/user/showcase?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/user/showcase",
    params={
        "handle": "@mkbhd",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/user/showcase
Open the full playground
GET/v1/tiktok/videos/popular1 creditcacheablebatchable

Popular videos

Videos trending in a market over a trailing window, from TikTok's Creative Center. Distinct from /v1/tiktok/trending, which is the personalised For You feed.

ParameterTypeRequiredDescription
regionstringnoTwo-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market.
period7 | 30 | 120noTrailing window in days: 7, 30 or 120defaults to 7
countnumbernoItems per page (default 20, max 50)
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

Returns a list of Post in data.items.

Fields
FieldTypePresentDescription
platformone of 47 stringsalways
idstringalways
typevideo | short | image | carousel | text | live | story | reel | audio | album | episode | unknownalwaysWhat kind of post this is. `short` and `reel` are short-form video formats, `live` is a live stream or a recording of one, `carousel` holds several images or videos, `audio` is a music track, `album` is an album, `episode` is a podcast episode, and `unknown` covers anything else.
urlstring | nullalways
titlestring | nullalways
textstring | nullalwaysThe post's text: a caption, a description or the message body.
authorIdstring | nullalways
authorHandlestring | nullalways
authorNamestring | nullalways
thumbnailUrlstring | nullalways
mediaUrlsstring[]always
durationSecondsnumber | nullalways
viewCountnumber | nullalwaysViews. Null means the platform did not expose a count, which is not the same as zero.
likeCountnumber | nullalwaysLikes, or the platform's nearest equivalent. Null means not exposed, not zero.
commentCountnumber | nullalwaysComments. Null means not exposed, not zero.
shareCountnumber | nullalwaysShares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero.
hashtagsstring[]alwaysHashtags or the platform's own topic tags, without the leading #.
mentionsstring[]alwaysHandles mentioned in the post text, without the leading @.
taggedUsersstring[]may be absentUsernames tagged in the media itself, as distinct from `mentions`, which come from the caption text. Absent when the platform does not report tags; an empty array means it reports none.
isSponsoredboolean | nullalwaysWhether the platform labels the post as an ad, promoted content or a paid partnership.
publishedAtstring | nullalwaysWhen the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago".
fetchedAtstringalwaysWhen this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch.
curl
curl "$API/v1/tiktok/videos/popular?cache_max_age=7d" \
  -H "x-api-key: $KEY"
TypeScript
const query = new URLSearchParams({
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/videos/popular?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/videos/popular",
    params={
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])
Response codes
200Success
400invalid_request. Not charged
401missing_api_key / invalid_api_key / revoked_api_key. Never a billing error
402insufficient_credits. The key is valid, the balance is not
429daily_cap_exceeded or rate_limited (hourly calls to servers you named outside our known list). Not charged
501not_configured. This deployment is not set up to serve this endpoint. Not charged.
502upstream_schema_drift. Not charged
503upstream_unavailable. We could not get this from the platform. Not charged
504upstream_timeout. Not charged
Try it here
GET/v1/tiktok/videos/popular
Open the full playground

Questions

How much does the TikTok API cost?
Calls cost 1 credit each. Every endpoint is cacheable, and a cache hit costs nothing. A failed request and an empty result are both free, on every endpoint.
Does the TikTok API need a login or cookies?
No. Every endpoint reads public, logged-out pages only — no account, no cookies, no session. An API key identifies your own TrueScrape account and nothing else.
Can I fetch many TikTok targets in one request?
Yes. 27 of 28 are batchable: one POST to /v1/jobs/batch takes many targets and returns a job id to poll.
Can I watch TikTok endpoints for changes?
Yes, 19 of 28. A subscription polls on your schedule and fires your webhook only when the content changed; the rest carry x-subscribable: false in the spec.