TikTok API
The TrueScrape TikTok API exposes 32 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
| Endpoint | Returns | Credits | Cacheable | Batchable |
|---|---|---|---|---|
| /v1/tiktok/ad-library/ad | One TikTok ad | 1 | yes | yes |
| /v1/tiktok/ad-library/search | Search the TikTok Ads Library | 1 | yes | no |
| /v1/tiktok/collection/videos | Collection videos | 1 | yes | yes |
| /v1/tiktok/comment-replies | Replies to a comment | 1 | yes | yes |
| /v1/tiktok/comments | Comments on a video | 1 | yes | yes |
| /v1/tiktok/creators/popular | Popular creators | 1 | yes | yes |
| /v1/tiktok/followers | Accounts following a creator | 1 | yes | yes |
| /v1/tiktok/following | Accounts a creator follows | 1 | yes | yes |
| /v1/tiktok/hashtag | Hashtag details | 1 | yes | yes |
| /v1/tiktok/hashtag-videos | Videos using a hashtag | 1 | yes | yes |
| /v1/tiktok/live | Live stream info | 1 | yes | yes |
| /v1/tiktok/playlist-videos | Videos in a playlist | 1 | yes | yes |
| /v1/tiktok/playlists | A creator's playlists | 1 | yes | yes |
| /v1/tiktok/product | Product details | 1 | yes | yes |
| /v1/tiktok/profile | Profile details | 1 | yes | yes |
| /v1/tiktok/profile/region | Creator region | 1 | yes | yes |
| /v1/tiktok/search/keyword | Search videos by keyword | 1 | yes | yes |
| /v1/tiktok/search/suggestions | Search suggestions | 1 | yes | yes |
| /v1/tiktok/search/top | Top (blended) search | 1 | yes | yes |
| /v1/tiktok/search/users | Search creators | 1 | yes | yes |
| /v1/tiktok/shop/product/reviews | Product reviews | 1 | yes | yes |
| /v1/tiktok/shop/products | Seller's product catalogue | 1 | yes | yes |
| /v1/tiktok/shop/search | Search TikTok Shop | 1 | yes | yes |
| /v1/tiktok/song | Sound / song details | 1 | yes | yes |
| /v1/tiktok/song-videos | Videos using a sound | 1 | yes | yes |
| /v1/tiktok/songs/popular | Popular songs | 1 | yes | yes |
| /v1/tiktok/transcript | Video transcript | 1 | yes | yes |
| /v1/tiktok/trending | Trending feed | 1 | yes | yes |
| /v1/tiktok/user-videos | Videos posted by a creator | 1 | yes | yes |
| /v1/tiktok/user/showcase | Creator's product showcase | 1 | yes | yes |
| /v1/tiktok/video | Video or photo-post details | 1 | yes | yes |
| /v1/tiktok/videos/popular | Popular videos | 1 | yes | yes |
Reference
/v1/tiktok/ad-library/ad1 creditcacheablebatchableOne TikTok ad
One TikTok ad by id or URL. Two public surfaces carry ads and an id alone does not say which: Creative Center Top Ads (ads.tiktok.com) is checked first, then the Commercial Content Library (library.tiktok.com). Pass a URL from either and only that source is queried. Both return the same Ad shape; fields a source does not publish are null rather than inferred - Top Ads carries no flight dates or advertiser entity, and the library carries no performance metrics. countries here is the ad's own targeting, unlike a search result's, where it is the market that was searched. An id neither source knows is a 404; an id that only one source could be asked about is not, because a source that did not answer has not said no. Reach bands stay in raw, not in the impressions fields, because reach is not impressions.
| Parameter | Type | Required | Description |
|---|---|---|---|
| ad_id | string | yes | Numeric ad id, a library.tiktok.com /ads/detail?ad_id= URL, or an ads.tiktok.com Top Ads URL |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns one Ad.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| advertiserId | string | null | always | |
| advertiserName | string | null | always | |
| url | string | null | always | Link to the ad's page in the platform's ad library. |
| headline | string | null | always | |
| body | string | null | always | |
| ctaText | string | null | always | Text of the call-to-action button, such as "Shop now". |
| linkUrl | string | null | always | Where the ad links to. Some ad libraries expose only the destination's domain. |
| creativeType | string | null | always | Format of the ad creative, such as `video` or `image`, as the ad library labels it. |
| imageUrls | string[] | always | |
| videoUrls | string[] | always | |
| platforms | string[] | always | Platforms the ad was shown on, in lowercase, such as `facebook` or `instagram`. |
| countries | string[] | always | Countries the ad ran in or targeted, usually as two-letter country codes. |
| languages | string[] | always | |
| startedAt | string | null | always | |
| endedAt | string | null | always | When the ad stopped running. Null while it is still running, or when the ad library reports no end date. |
| isActive | boolean | null | always | |
| impressionsLower | number | null | always | Lower bound of the impressions range the ad library reports. Libraries publish a range, not an exact figure. |
| impressionsUpper | number | null | always | Upper bound of the impressions range the ad library reports. |
| spendLower | number | null | always | Lower bound of the reported spend range, in `currency`. |
| spendUpper | number | null | always | Upper bound of the reported spend range, in `currency`. |
| currency | string | null | always | Currency of the spend range, as a code such as `USD`. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/ad-library/ad?ad_id=%3Cad_id%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
ad_id: '<ad_id>',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/ad-library/ad?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/ad-library/ad",
params={
"ad_id": "<ad_id>",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/ad-library/search1 creditcacheableSearch the TikTok Ads Library
Ads in TikTok's public Commercial Content Library, by keyword (query) or by advertiser (advertiser_name). An advertiser name is resolved through TikTok's own typeahead first, then searched as an entity, so it matches the registered legal name ("NIKE Retail B.V.") rather than a brand. Results are NOT global: TikTok publishes this archive per market and refuses a search without one, so region is required, validated against the market list the library itself publishes rather than a fixed list here, and every result ran in that market, which is what each ad's countries reports. TikTok returns its own relevance ranking; we ask for the most recently shown first, but that is only a tiebreak within it, so results are not ordered by date. Cursor-paginated 12 at a time, each ad carrying its public library.tiktok.com detail URL. Pages are not guaranteed disjoint: the archive re-ranks live, so an ad can repeat across pages. Political and election ads are outside the archive. Reach is published as a band and is not impressions, so it stays in raw.estimated_audience rather than the impressions fields.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | no | Keyword, matched against ad text and advertiser name |
| advertiser_name | string | no | Advertiser name, resolved through TikTok's typeahead to one advertiser entity |
| region | string | yes | Market to search. TikTok publishes this archive per market; one of AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, TR. |
| cursor | string | no | pagination.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 Ad in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| advertiserId | string | null | always | |
| advertiserName | string | null | always | |
| url | string | null | always | Link to the ad's page in the platform's ad library. |
| headline | string | null | always | |
| body | string | null | always | |
| ctaText | string | null | always | Text of the call-to-action button, such as "Shop now". |
| linkUrl | string | null | always | Where the ad links to. Some ad libraries expose only the destination's domain. |
| creativeType | string | null | always | Format of the ad creative, such as `video` or `image`, as the ad library labels it. |
| imageUrls | string[] | always | |
| videoUrls | string[] | always | |
| platforms | string[] | always | Platforms the ad was shown on, in lowercase, such as `facebook` or `instagram`. |
| countries | string[] | always | Countries the ad ran in or targeted, usually as two-letter country codes. |
| languages | string[] | always | |
| startedAt | string | null | always | |
| endedAt | string | null | always | When the ad stopped running. Null while it is still running, or when the ad library reports no end date. |
| isActive | boolean | null | always | |
| impressionsLower | number | null | always | Lower bound of the impressions range the ad library reports. Libraries publish a range, not an exact figure. |
| impressionsUpper | number | null | always | Upper bound of the impressions range the ad library reports. |
| spendLower | number | null | always | Lower bound of the reported spend range, in `currency`. |
| spendUpper | number | null | always | Upper bound of the reported spend range, in `currency`. |
| currency | string | null | always | Currency of the spend range, as a code such as `USD`. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/ad-library/search?region=%3Cregion%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
region: '<region>',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/ad-library/search?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/ad-library/search",
params={
"region": "<region>",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/collection/videos1 creditcacheablebatchableCollection 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | no | Collection URL, e.g. https://www.tiktok.com/@nasa/collection/Artemis-7123… |
| collection_id | string | no | Numeric collection id |
| count | number | no | Items per page (default 20, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/collection/videos?cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/comment-replies1 creditcacheablebatchableReplies 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| comment_id | string | yes | id of the parent comment, from tiktok.comments |
| url | string | yes | The video the comment is on: URL, share link, or numeric id |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| postId | string | null | always | |
| parentId | string | null | always | Id of the comment this one replies to. Null on a top-level comment. |
| text | string | always | |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| authorAvatarUrl | string | null | always | |
| likeCount | number | null | always | |
| replyCount | number | null | always | |
| isPinned | boolean | null | always | |
| isAuthorReply | boolean | null | always | Whether the comment was written by the author of the post. |
| publishedAt | string | null | always | When the comment was posted. Usually an ISO 8601 timestamp; some platforms expose only relative text such as "2 days ago". |
curl "$API/v1/tiktok/comment-replies?comment_id=%3Ccomment_id%3E&url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/comments1 creditcacheablebatchableComments on a video
Top-level comments on a TikTok, with like counts, reply counts, pinned status and a flag for the creator's own replies. Use tiktok.commentReplies to expand a thread.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Video URL (preferred), share link, or numeric video id |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| postId | string | null | always | |
| parentId | string | null | always | Id of the comment this one replies to. Null on a top-level comment. |
| text | string | always | |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| authorAvatarUrl | string | null | always | |
| likeCount | number | null | always | |
| replyCount | number | null | always | |
| isPinned | boolean | null | always | |
| isAuthorReply | boolean | null | always | Whether the comment was written by the author of the post. |
| publishedAt | string | null | always | When the comment was posted. Usually an ISO 8601 timestamp; some platforms expose only relative text such as "2 days ago". |
curl "$API/v1/tiktok/comments?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/comments?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/comments",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/creators/popular1 creditcacheablebatchablePopular creators
Creators trending in a market, from TikTok's own Creative Center leaderboard. Filter by country, follower band and category.
| Parameter | Type | Required | Description |
|---|---|---|---|
| region | string | no | Two-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market. |
| period | 7 | 30 | 120 | no | Trailing window in days: 7, 30 or 120defaults to 7 |
| follower_band | 1k-10k | 10k-100k | 100k-1m | 1m+ | no | Restrict to creators in this follower range |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The platform's own id for the account, such as a channel id or a numeric user id, always as a string. |
| handle | string | null | always | The account handle without the leading @. Null when the platform has no handles. |
| displayName | string | null | always | |
| bio | string | null | always | |
| avatarUrl | string | null | always | |
| bannerUrl | string | null | always | |
| url | string | null | always | |
| verified | boolean | null | always | Whether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it. |
| followerCount | number | null | always | Followers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it. |
| followingCount | number | null | always | |
| postCount | number | null | always | Posts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published. |
| viewCount | number | null | always | Lifetime views across the account, where the platform exposes a total. |
| likeCount | number | null | may be absent | Total likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it. |
| isPrivate | boolean | null | always | |
| isBusiness | boolean | null | always | Whether 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. |
| category | string | null | always | A label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform. |
| location | string | null | always | Location as the platform shows it: a city, a country, a region code or an address, depending on the platform. |
| externalLinks | string[] | always | Links the account lists on its profile, such as a website or other social accounts. |
| createdAt | string | null | always | When the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/creators/popular?cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/followers1 creditcacheablebatchableAccounts 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | yes | Handle (@nike), or a full tiktok.com profile URL |
| count | number | no | Items per page (default 30, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The platform's own id for the account, such as a channel id or a numeric user id, always as a string. |
| handle | string | null | always | The account handle without the leading @. Null when the platform has no handles. |
| displayName | string | null | always | |
| bio | string | null | always | |
| avatarUrl | string | null | always | |
| bannerUrl | string | null | always | |
| url | string | null | always | |
| verified | boolean | null | always | Whether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it. |
| followerCount | number | null | always | Followers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it. |
| followingCount | number | null | always | |
| postCount | number | null | always | Posts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published. |
| viewCount | number | null | always | Lifetime views across the account, where the platform exposes a total. |
| likeCount | number | null | may be absent | Total likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it. |
| isPrivate | boolean | null | always | |
| isBusiness | boolean | null | always | Whether 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. |
| category | string | null | always | A label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform. |
| location | string | null | always | Location as the platform shows it: a city, a country, a region code or an address, depending on the platform. |
| externalLinks | string[] | always | Links the account lists on its profile, such as a website or other social accounts. |
| createdAt | string | null | always | When the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/followers?handle=%40mkbhd&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/following1 creditcacheablebatchableAccounts a creator follows
The accounts a TikTok creator follows, newest first. Hidden entirely when the creator has set their following list to private. Requires a configured TikTok signer.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | yes | Handle (@nike), or a full tiktok.com profile URL |
| count | number | no | Items per page (default 30, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The platform's own id for the account, such as a channel id or a numeric user id, always as a string. |
| handle | string | null | always | The account handle without the leading @. Null when the platform has no handles. |
| displayName | string | null | always | |
| bio | string | null | always | |
| avatarUrl | string | null | always | |
| bannerUrl | string | null | always | |
| url | string | null | always | |
| verified | boolean | null | always | Whether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it. |
| followerCount | number | null | always | Followers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it. |
| followingCount | number | null | always | |
| postCount | number | null | always | Posts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published. |
| viewCount | number | null | always | Lifetime views across the account, where the platform exposes a total. |
| likeCount | number | null | may be absent | Total likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it. |
| isPrivate | boolean | null | always | |
| isBusiness | boolean | null | always | Whether 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. |
| category | string | null | always | A label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform. |
| location | string | null | always | Location as the platform shows it: a city, a country, a region code or an address, depending on the platform. |
| externalLinks | string[] | always | Links the account lists on its profile, such as a website or other social accounts. |
| createdAt | string | null | always | When the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/following?handle=%40mkbhd&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
handle: '@mkbhd',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/following?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/following",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/hashtag1 creditcacheablebatchableHashtag 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| hashtag | string | yes | Tag 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
| Field | Type | Present |
|---|---|---|
| platform | "tiktok" | always |
| id | string | always |
| name | string | always |
| description | string | null | always |
| url | string | always |
| coverUrl | string | null | always |
| videoCount | number | null | always |
| viewCount | number | null | always |
| isCommerce | boolean | null | always |
| fetchedAt | string | always |
curl "$API/v1/tiktok/hashtag?hashtag=%3Chashtag%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/hashtag-videos1 creditcacheablebatchableVideos using a hashtag
TikToks carrying a given hashtag, in TikTok's own feed order, with a cursor for the next page.
| Parameter | Type | Required | Description |
|---|---|---|---|
| hashtag | string | yes | Tag without the # (fyp), or a full /tag/ URL |
| count | number | no | Items per page (default 30, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/hashtag-videos?hashtag=%3Chashtag%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
hashtag: '<hashtag>',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/hashtag-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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/hashtag-videos",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/live1 creditcacheablebatchableLive 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | no | Handle (@nike), or a full tiktok.com profile URL |
| room_id | string | no | TikTok 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
| Field | Type | Present |
|---|---|---|
| platform | "tiktok" | always |
| roomId | string | always |
| handle | string | always |
| title | string | null | always |
| coverUrl | string | null | always |
| viewerCount | number | null | always |
| startedAt | string | null | always |
| url | string | always |
| creator | Creator | always |
| fetchedAt | string | always |
curl "$API/v1/tiktok/live?cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/playlist-videos1 creditcacheablebatchableVideos in a playlist
The videos inside one TikTok playlist, in the creator's chosen order. Requires a configured TikTok signer.
| Parameter | Type | Required | Description |
|---|---|---|---|
| playlist_id | string | yes | id from tiktok.playlists, or a /playlist/ URL |
| count | number | no | Items per page (default 30, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/playlist-videos?playlist_id=%3Cplaylist_id%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
playlist_id: '<playlist_id>',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/playlist-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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/playlist-videos",
params={
"playlist_id": "<playlist_id>",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/playlists1 creditcacheablebatchableA creator's playlists
The playlists (TikTok calls them "mixes") a creator has organised their videos into. Pair with tiktok.playlistVideos to walk one. Requires a configured TikTok signer.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | yes | Handle (@nike), or a full tiktok.com profile URL |
| count | number | no | Items per page (default 20, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present |
|---|---|---|
| platform | "tiktok" | always |
| id | string | always |
| name | string | always |
| url | string | always |
| coverUrl | string | null | always |
| videoCount | number | null | always |
| fetchedAt | string | always |
curl "$API/v1/tiktok/playlists?handle=%40mkbhd&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
handle: '@mkbhd',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/playlists?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/playlists",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/product1 creditcacheablebatchableProduct details
A single TikTok Shop product: title, description, images, price and original price, rating, review and sales counts, stock, category and the seller. price is the lowest-priced variant; it is null when TikTok hides the digits from logged-out visitors. Catalogues are per market: region picks one, default US.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Product id, or a tiktok.com/shop/pdp/… URL |
| region | string | no | Two-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 an object with platform, id, title, url, description, price, originalPrice, imageUrls, rating, reviewCount, soldCount, inStock, sellerId, sellerName, categoryName, fetchedAt.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| title | string | always | |
| url | string | null | always | |
| description | string | null | always | |
| price | object | always | |
| price.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| price.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| price.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| originalPrice | object | always | |
| originalPrice.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| originalPrice.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| originalPrice.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| imageUrls | string[] | always | |
| rating | number | null | always | Star rating out of 5. Null on a product with no reviews yet. |
| reviewCount | number | null | always | |
| soldCount | number | null | always | |
| inStock | boolean | null | always | |
| sellerId | string | null | always | |
| sellerName | string | null | always | |
| categoryName | string | null | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/product?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/product?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/product",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/profile1 creditcacheablebatchableProfile details
Public profile for a TikTok account: followers, following, video count, bio, bio link, verification and account region. Private accounts return their public shell with isPrivate: true rather than an error. That is a real answer, not a failure. Total likes received (TikTok's "hearts") is in raw, since it is a like total rather than the lifetime view count viewCount means elsewhere in the schema.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | yes | Handle (@nike), or a full tiktok.com profile URL |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns one Creator.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The platform's own id for the account, such as a channel id or a numeric user id, always as a string. |
| handle | string | null | always | The account handle without the leading @. Null when the platform has no handles. |
| displayName | string | null | always | |
| bio | string | null | always | |
| avatarUrl | string | null | always | |
| bannerUrl | string | null | always | |
| url | string | null | always | |
| verified | boolean | null | always | Whether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it. |
| followerCount | number | null | always | Followers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it. |
| followingCount | number | null | always | |
| postCount | number | null | always | Posts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published. |
| viewCount | number | null | always | Lifetime views across the account, where the platform exposes a total. |
| likeCount | number | null | may be absent | Total likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it. |
| isPrivate | boolean | null | always | |
| isBusiness | boolean | null | always | Whether 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. |
| category | string | null | always | A label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform. |
| location | string | null | always | Location as the platform shows it: a city, a country, a region code or an address, depending on the platform. |
| externalLinks | string[] | always | Links the account lists on its profile, such as a website or other social accounts. |
| createdAt | string | null | always | When the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/profile?handle=%40mkbhd&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
handle: '@mkbhd',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/profile?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/profile",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/profile/region1 creditcacheablebatchableCreator region
The market TikTok assigns a creator's account. Read from TikTok's own region field: on the profile where TikTok publishes one, otherwise from the region stamped on the creator's recent posts. Never inferred from language, timezone or content. **Required:** Pass either handle or url.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | no | Creator handle, e.g. @nasa |
| url | string | no | Profile URL, e.g. https://www.tiktok.com/@nasa |
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, handle, userId, region, source, agreement, fetchedAt.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| handle | string | always | |
| userId | string | always | |
| region | string | null | always | Two-letter market code as TikTok reports it. Never inferred. |
| source | profile | posts | null | always | Where the value came from, so a caller can weigh it. |
| agreement | object[] | always | From posts: how many sampled posts agreed. A traveller can carry several. |
| agreement[].region | string | always | |
| agreement[].count | number | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/profile/region?cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/profile/region?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/profile/region",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/search/keyword1 creditcacheablebatchableSearch videos by keyword
TikToks matching a search term, with the same normalised engagement fields as every other post endpoint. sort_by and date_posted map onto TikTok's own search filters. Requires a configured TikTok signer.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search term |
| sort_by | relevance | most_liked | no | TikTok's own two search orderingsdefaults to relevance |
| date_posted | all | yesterday | week | month | three_months | six_months | no | Restrict to videos posted within this windowdefaults to all |
| count | number | no | Items per page (default 12, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/search/keyword?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/search/keyword?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/search/keyword",
params={
"query": "ai agents",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/search/suggestions1 creditcacheablebatchableSearch suggestions
TikTok's typeahead completions for a partial query: what the platform thinks people are looking for. Useful for keyword research.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Partial search term |
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
| Field | Type | Present | Description |
|---|---|---|---|
| text | string | always | |
| type | string | null | always | TikTok's own grouping, when it labels one. |
curl "$API/v1/tiktok/search/suggestions?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/search/suggestions?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/search/suggestions",
params={
"query": "ai agents",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/search/top1 creditcacheablebatchableTop (blended) search
TikTok's blended "Top" search tab: the highest-ranked videos AND accounts for a query, returned as two typed lists. Requires a configured TikTok signer.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search terms |
| count | number | no | Items per page (default 12, max 30) |
| cursor | string | no | pagination.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).
curl "$API/v1/tiktok/search/top?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/search/top?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/search/top",
params={
"query": "ai agents",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/search/users1 creditcacheablebatchableSearch creators
TikTok accounts matching a query, with follower counts and verification. Requires a configured TikTok signer.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search term |
| count | number | no | Items per page (default 12, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The platform's own id for the account, such as a channel id or a numeric user id, always as a string. |
| handle | string | null | always | The account handle without the leading @. Null when the platform has no handles. |
| displayName | string | null | always | |
| bio | string | null | always | |
| avatarUrl | string | null | always | |
| bannerUrl | string | null | always | |
| url | string | null | always | |
| verified | boolean | null | always | Whether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it. |
| followerCount | number | null | always | Followers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it. |
| followingCount | number | null | always | |
| postCount | number | null | always | Posts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published. |
| viewCount | number | null | always | Lifetime views across the account, where the platform exposes a total. |
| likeCount | number | null | may be absent | Total likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it. |
| isPrivate | boolean | null | always | |
| isBusiness | boolean | null | always | Whether 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. |
| category | string | null | always | A label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform. |
| location | string | null | always | Location as the platform shows it: a city, a country, a region code or an address, depending on the platform. |
| externalLinks | string[] | always | Links the account lists on its profile, such as a website or other social accounts. |
| createdAt | string | null | always | When the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/search/users?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/search/users?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/search/users",
params={
"query": "ai agents",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/shop/product/reviews1 creditcacheablebatchableProduct reviews
The reviews a TikTok Shop product page shows, with star rating, reviewer, photos and the purchased variant. That is the page's first screen, not every review. region picks the market, default US.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Product id, or a tiktok.com/shop/pdp/… URL |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.cursor from a previous response |
| region | string | no | Two-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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| productId | string | null | always | |
| text | string | always | |
| rating | number | null | always | |
| authorName | string | null | always | |
| authorAvatarUrl | string | null | always | |
| imageUrls | string[] | always | |
| variant | string | null | always | The variant the reviewer actually bought, when TikTok attaches it. |
| publishedAt | string | null | always |
curl "$API/v1/tiktok/shop/product/reviews?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/shop/product/reviews?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/shop/product/reviews",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/shop/products1 creditcacheablebatchableSeller's product catalogue
The products a TikTok Shop store lists, page by page, with price, rating, review and sales counts. Pass the store's URL (tiktok.com/shop/store/<name>/<seller_id>). region picks the market, default US.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | TikTok Shop store URL, e.g. https://www.tiktok.com/shop/store/goli-nutrition/7495794203056835079 |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.cursor from a previous response |
| region | string | no | Two-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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| title | string | always | |
| url | string | null | always | |
| description | string | null | always | |
| price | object | always | |
| price.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| price.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| price.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| originalPrice | object | always | |
| originalPrice.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| originalPrice.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| originalPrice.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| imageUrls | string[] | always | |
| rating | number | null | always | Star rating out of 5. Null on a product with no reviews yet. |
| reviewCount | number | null | always | |
| soldCount | number | null | always | |
| inStock | boolean | null | always | |
| sellerId | string | null | always | |
| sellerName | string | null | always | |
| categoryName | string | null | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/shop/products?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/shop/products?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/shop/products",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/shop/search1 creditcacheablebatchableSearch TikTok Shop
The products TikTok Shop search returns for a query, page by page, with price, rating, review and sales counts. US market.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search terms |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.cursor from a previous response |
| region | string | no | Two-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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| title | string | always | |
| url | string | null | always | |
| description | string | null | always | |
| price | object | always | |
| price.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| price.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| price.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| originalPrice | object | always | |
| originalPrice.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| originalPrice.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| originalPrice.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| imageUrls | string[] | always | |
| rating | number | null | always | Star rating out of 5. Null on a product with no reviews yet. |
| reviewCount | number | null | always | |
| soldCount | number | null | always | |
| inStock | boolean | null | always | |
| sellerId | string | null | always | |
| sellerName | string | null | always | |
| categoryName | string | null | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/shop/search?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/shop/search?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/shop/search",
params={
"query": "ai agents",
"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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/song1 creditcacheablebatchableSound / song details
Details for a TikTok sound: title, artist, album, cover, clip length, and how many videos use it.
| Parameter | Type | Required | Description |
|---|---|---|---|
| song | string | yes | Music 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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| title | string | always | |
| authorName | string | null | always | |
| album | string | null | always | |
| url | string | always | |
| coverUrl | string | null | always | |
| playUrl | string | null | always | |
| durationSeconds | number | null | always | |
| isOriginalSound | boolean | null | always | True when the sound originated on TikTok rather than a licensed track. |
| videoCount | number | null | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/song?song=%3Csong%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/song-videos1 creditcacheablebatchableVideos using a sound
TikToks built on a given sound: the endpoint behind "who is using my track", with a cursor for the next page.
| Parameter | Type | Required | Description |
|---|---|---|---|
| song | string | yes | Music id, or a full tiktok.com/music/… URL |
| count | number | no | Items per page (default 30, max 30) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/song-videos?song=%3Csong%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/songs/popular1 creditcacheablebatchablePopular songs
Sounds trending in a market, the endpoint behind music A&R and sync-licensing research. From TikTok's Creative Center.
| Parameter | Type | Required | Description |
|---|---|---|---|
| region | string | no | Two-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market. |
| period | 7 | 30 | 120 | no | Trailing window in days: 7, 30 or 120defaults to 7 |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| title | string | always | |
| authorName | string | null | always | |
| album | string | null | always | |
| url | string | always | |
| coverUrl | string | null | always | |
| playUrl | string | null | always | |
| durationSeconds | number | null | always | |
| isOriginalSound | boolean | null | always | True when the sound originated on TikTok rather than a licensed track. |
| videoCount | number | null | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/songs/popular?cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/transcript1 creditcacheablebatchableVideo 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Video URL (preferred), share link, or numeric video id |
| language | string | no | BCP-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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| postId | string | always | |
| url | string | null | always | |
| language | string | null | always | The transcript's language as the platform labels it, usually a language code such as `en`. |
| isAutoGenerated | boolean | null | always | Whether the platform generated the captions automatically, by speech recognition or machine translation, rather than a person writing them. |
| text | string | always | The full transcript as a single block of text. |
| cues | object[] | always | Timed segments of the transcript. |
| cues[].start | number | always | Seconds from the start of the media. |
| cues[].end | number | null | always | Seconds from the start of the media. Null when the platform gives no end time. |
| cues[].text | string | always | |
| durationSeconds | number | null | always | |
| source | captions | asr | null | always | Where 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. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/transcript?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/trending1 creditcacheablebatchableTrending feed
TikTok's logged-out For You feed for a region, showing what the platform is pushing to a brand-new visitor right now. Not a ranking anyone can reproduce: TikTok personalises even the anonymous feed, so two calls a second apart return different videos.
| Parameter | Type | Required | Description |
|---|---|---|---|
| region | string | no | Two-letter country code, e.g. US, GB, DEdefaults to US |
| count | number | no | Items per page (default 30, max 30) |
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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/trending?cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/trending?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/trending",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/user-videos1 creditcacheablebatchableVideos posted by a creator
A creator's public posts, newest first, with view/like/comment/share counts. Photo posts are included and typed as image or carousel. Up to 15 per page, with a cursor for older posts.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | yes | Handle (@nike), or a full tiktok.com profile URL |
| count | number | no | Items per page (default 35, max 35) |
| cursor | string | no | pagination.cursor from a previous response |
| max_cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/user-videos?handle=%40mkbhd&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
handle: '@mkbhd',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/user-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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/user-videos",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/user/showcase1 creditcacheablebatchableCreator'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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| handle | string | yes | Creator handle, e.g. @charlidamelio |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.cursor from a previous response |
| region | string | no | Two-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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | "tiktok" | always | |
| id | string | always | |
| title | string | always | |
| url | string | null | always | |
| description | string | null | always | |
| price | object | always | |
| price.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| price.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| price.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| originalPrice | object | always | |
| originalPrice.amount | number | null | always | Numeric amount in major units (12.99, not 1299). Null if unparseable. |
| originalPrice.currency | string | null | always | ISO-4217 where TikTok gives one. Null means we will not guess. |
| originalPrice.formatted | string | null | always | Exactly what TikTok displayed, e.g. "$12.99". |
| imageUrls | string[] | always | |
| rating | number | null | always | Star rating out of 5. Null on a product with no reviews yet. |
| reviewCount | number | null | always | |
| soldCount | number | null | always | |
| inStock | boolean | null | always | |
| sellerId | string | null | always | |
| sellerName | string | null | always | |
| categoryName | string | null | always | |
| fetchedAt | string | always |
curl "$API/v1/tiktok/user/showcase?handle=%40mkbhd&cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/video1 creditcacheablebatchableVideo or photo-post details
Full public metadata for one TikTok: caption, hashtags, mentions, author, sound, duration, and view/like/comment/share counts. Photo posts return every image in mediaUrls. Accepts a full URL, a share link (vm.tiktok.com), or a numeric video id.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Video URL (preferred), share link, or numeric video id |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns one Post.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/video?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/tiktok/video?${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
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/tiktok/video",
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/tiktok/videos/popular1 creditcacheablebatchablePopular 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| region | string | no | Two-letter market code (US, GB, ID…). TikTok feeds and catalogues are per-market. |
| period | 7 | 30 | 120 | no | Trailing window in days: 7, 30 or 120defaults to 7 |
| count | number | no | Items per page (default 20, max 50) |
| cursor | string | no | pagination.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
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What 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. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames 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. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/tiktok/videos/popular?cache_max_age=7d" \
-H "x-api-key: $KEY"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
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
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
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. 31 of 32 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, 20 of 32. A subscription polls on your schedule and fires your webhook only when the content changed; the rest carry x-subscribable: false in the spec.