The Cheapest TikTok API for Developers

Profile, video, hashtag, search and music as structured JSON, with the true author and an honest list shape.

Join the List See the Rate Card
Try for Free Read the Build Guide
Prelaunch — not served yet 5 endpoints 180 items per sync call 10 Free API Calls No monthly plan

Not live yet. /api/tiktok/* does not answer today. The rates on this page are target rates, unverified until launch — they are not served yet. Join the list and we’ll mail you the day they start answering.

One enriched call returns a whole list for one charge, up to the 180-item synchronous cap. The limit you pass sets both the depth and the price — deeper costs more in total and less per item.

Run a live TikTok profile request

No signup and no key. The box sends a real profile request and prints exactly what the endpoint returns.

TikTok is in prelaunch, so the box answers the standard unavailable message rather than a profile. That is the correct behaviour for an endpoint that is not served yet, not a fault in the box.

Five TikTok Endpoints, One API Key

Profile and video are the flat basic rate. Hashtag, search and music are list calls, and a list call is priced by the depth you ask for.

Video

Video record

from $0.35
/1K calls (Scale tier, basic)
  • GET /api/tiktok/video by id or URL
  • The true author, not a re-post handle
  • Caption, music, hashtags, mentions, labels, stats
  • Optional comments and related groups; include_media is priced separately and is not a group
Default$0.50/1K calls
Growth$0.45/1K calls
Scale$0.35/1K calls
Build guide →
Hashtag

Hashtag

from $2.10
/1K calls at limit=30 (Scale)
  • GET /api/tiktok/hashtag by tag or id
  • Accepts football, #football or a tag URL
  • Up to 180 items in one synchronous call
  • Priced by depth — see the ladder below
Default$3.00/1K calls
Growth$2.70/1K calls
Scale$2.10/1K calls
How depth is priced →
Search

Search

from $2.10
/1K calls at limit=30 (Scale)
  • GET /api/tiktok/search by keyword
  • The same items[] envelope as every other list
  • Up to 180 items in one synchronous call
  • Priced by depth — see the ladder below
Default$3.00/1K calls
Growth$2.70/1K calls
Scale$2.10/1K calls
How depth is priced →
Music

Music

from $2.10
/1K calls at limit=30 (Scale)
  • GET /api/tiktok/music by id or sound URL
  • Every item that used the sound, in one list
  • Up to 180 items in one synchronous call
  • Priced by depth — see the ladder below
Default$3.00/1K calls
Growth$2.70/1K calls
Scale$2.10/1K calls
How depth is priced →

The depth price, in full — $3.00 is the limit=30 price, not a flat rate

An enriched call is any call carrying an include_* group, plus every hashtag, search and music call. It is charged as a fixed part plus a per-item part, and the limit you pass is what moves it. At Default the charge is $3.00/1K × (0.7 + 0.01 × limit).

limit=30 (default)
$3.00
$0.100 per 1,000 items
limit=60
$3.90
$0.065 per 1,000 items
limit=100
$5.10
$0.051 per 1,000 items
limit=180 (sync cap)
$7.50
$0.042 per 1,000 items

Read that both ways. A limit=180 call bills $7.50 per 1,000 calls — two and a half times the advertised $3.00. Per item it goes the other way: $0.100 falls to $0.042 per 1,000 items, and to $0.029 on Scale. Both statements are true and the second is the one we win on, so the first is printed first. Two groups are billed to less depth than you ask for: include_following is billed to a depth of 50 and include_related to the default depth of 30, so at limit=180 they bill $3.60 and $3.00 rather than $7.50. You are never billed for depth a list cannot return. Every other group follows the ladder above. Growth and Scale scale the whole ladder by the same 10% and 30%. Deeper than 180 items is the async form, which holds no client socket and is not bound by the synchronous cap.

include_media is a surcharge, charged on top of the call. Media is $10.00 per 1,000 on Default, $9.00 on Growth and $7.00 on Scale, so a basic video call with media is $0.50 + $10.00 = $10.50 per 1,000 at Default — not $10.00. It is opt-in and never free-eligible, because it is the one part of this API whose cost is bytes rather than requests. When a hosted copy exists the media block carries a link that needs no headers plus an expires_at; when one cannot be produced the block says unavailable.

Prelaunch rate card. The rates above are target rates, unverified until launch, and are what you will pay when the endpoints ship — they are not served yet. Growth and Scale are earned by a single deposit of $100 and $500; both are one-time, and a tier once earned never downgrades. A list that genuinely comes back empty, or a profile or video that does not exist, is an answer and is charged; a failure on our side is refunded.

One call, one charge, whole list. An enriched call returns a list up to the 180-item synchronous cap for a single charge, where per-row vendors bill every item in it. Growth and Scale are earned by a single $100 and $500 deposit; both are one-time and never downgrade. A list that genuinely comes back empty, or a profile or video that does not exist, is an answer and is charged; a failure on our side is refunded.

TikTok Data in One Request

One header, one GET. Every list — a profile’s posts, a hashtag, a keyword search, a song — comes back in the same envelope, so your parser is written once.

cURL — profile, video, hashtag
# A basic profile — one record, the flat basic rate, no depth to set
curl "https://apiserpent.com/api/tiktok/profile?username=zachking&country=us" \
  -H "X-API-Key: YOUR_API_KEY"

# A video with its true author, music, hashtags and stats
curl "https://apiserpent.com/api/tiktok/video?url=https://www.tiktok.com/@zachking/video/7231" \
  -H "X-API-Key: YOUR_API_KEY"

# A hashtag list. limit sets BOTH the depth and the price — 180 is the sync cap
curl "https://apiserpent.com/api/tiktok/hashtag?tag=cottagecore&limit=180&country=us" \
  -H "X-API-Key: YOUR_API_KEY"
Python — one hashtag list into rows
import os, requests

h = {"X-API-Key": os.environ["SERPENT_API_KEY"]}
p = {"tag": "cottagecore", "limit": 180, "country": "us"}

data = requests.get("https://apiserpent.com/api/tiktok/hashtag",
                    params=p, headers=h, timeout=120).json()

# Check the envelope BEFORE the items. total_count is None when TikTok
# never stated one — it is not the same fact as result_count.
print(data["result_count"], data["total_count"], data["complete"])

for it in data["items"]:
    print(it["video_id"], it["author"]["username"], it["stats"]["play_count"])
Node — one profile record
const qs = new URLSearchParams({ username: "zachking", country: "us" });

const res = await fetch(`https://apiserpent.com/api/tiktok/profile?${qs}`, {
  headers: { "X-API-Key": process.env.SERPENT_API_KEY }
});

const profile = await res.json();
// A basic profile is a single record spread at the top level — no include_* set,
// so this is the flat basic rate and there is no depth to pay for.
console.log(profile.username, profile.verified, profile.stats.follower_count);
JSON Response — /api/tiktok/hashtag (partial)
{
  "success": true,
  "items": [
    {
      "video_id": "7301234567890123456",
      "video_url": "https://www.tiktok.com/@example/video/7301234567890123456",
      "description": "three weeks of sourdough in 40 seconds #cottagecore",
      "created_at": "2026-08-19T09:14:02.000Z",
      "author": {
        "username": "example",
        "nickname": "Example Creator",
        "verified": false
      },
      "music": {
        "music_id": "6987654321098765432",
        "title": "original sound",
        "original": true
      },
      "stats": {
        "play_count": 418200,
        "digg_count": 61400,
        "comment_count": 812,
        "share_count": 2140
      },
      "hashtags": [ { "name": "cottagecore" } ],
      "mentions": []
    }
  ],
  "result_count": 180,
  "total_count": null,
  "has_more": true,
  "next_cursor": "180",
  "truncated": false,
  "restricted": false,
  "complete": false,
  "meta": {
    "elapsed": "41830ms",
    "timestamp": "2026-09-08T11:04:31.522Z"
  }
}

Read the envelope before the items. total_count is null here because TikTok did not state a total for this tag — it is never back-filled from result_count, because “180 arrived” and “there are 180” are different facts. truncated (TikTok cut the list short), restricted (the list is not public) and complete (we reached the natural end) are three separate flags for three separate situations, and a collection that treats them as one will quietly record a private account as an empty one.

Every Field a TikTok Call Returns

Named JSON fields, not HTML you have to select against. Every key is always present, so an absent value arrives as null and never as a missing key.

Profile record

  • username, user_id, sec_uid
  • nickname, biography, bio_link
  • profile_url, avatar.thumb/medium/large
  • verified, private_account, is_organization
  • commerce_user, tt_seller, is_ad_virtual
  • region, language, created_at
  • stats (followers, likes, videos)
  • settings.comment/duet/stitch/download
  • settings.liked_videos_public
  • tabs.music, tabs.question, tabs.playlist

Video record

  • video_id, video_url, description
  • created_at, created_region, language
  • author (the true author, not a re-post)
  • music.music_id, title, author_name
  • music.original, music.duration
  • stats.play_count, digg_count
  • stats.comment_count, share_count
  • hashtags[], mentions[], labels[]
  • image_post, is_ad
  • duet_enabled, stitch_enabled, share_enabled
  • media.play_url, media.download_url (every video call)
  • media.video_link_headers, media.link_expires_at
  • media.hosted (only with include_media)

The list envelope

  • items[]
  • result_count
  • total_count (null when unstated)
  • has_more
  • next_cursor
  • truncated
  • restricted
  • complete
  • partialResults.requested
  • partialResults.returned
  • partialResults.reason, .note

Request parameters

  • username — profile
  • video_id or url — video
  • tag, q, music_id — the list calls
  • limit (1–180 sync; sets the price)
  • country (two-letter code)
  • include_posts, include_followers
  • include_following, include_liked
  • include_comments, include_related
  • include_media (surcharge, never free)

The playback links ship on every video call — and one field has to travel with them. media.play_url and media.download_url come back on every /video call at no extra charge, with no flag to set. They are time-limited, and a request for one has to carry the exact header set returned beside it in media.video_link_headerssend it as returned, unchanged. Without it the request does not get the file. media.link_expires_at is that link’s own expiry, so read it off the response rather than assuming a window. When we cannot produce a link that will actually serve, all four come back null instead of a link that would fail on you later. media.hosted is the separate, paid part: our own copy of the file, on a link that needs no headers, and the only piece include_media adds.

What is TikTok data, and why teams use it

It is the record behind a profile, video, hashtag or song: author, bio, stats, caption, music and the list itself. Four things decide whether it is usable.

The author has to be the real one

A TikTok video can surface under a handle that did not make it. author on a video record is the creator of that video, carrying username, user_id, sec_uid, nickname and verified.

If you are building a creator database, an attribution report or an outreach list, this is the field the whole dataset rests on. Getting it wrong does not throw an error — it quietly credits the wrong person for a year.

A list has to say what kind of list it is

An empty list is three different situations. TikTok cut it short (truncated). It is not public (restricted). Or you reached the end and there is genuinely nothing more (complete).

All three are on the envelope, and total_count stays null when TikTok never stated a total rather than being back-filled from what arrived. A collector that cannot tell those apart records a private account as an empty one.

Depth is a price, and it should be visible

One enriched call returns a whole list — up to 180 items — for one charge, where per-row vendors bill every item. That is the structural saving, and it is also why the depth cannot be free.

So the formula is printed on this page rather than discovered on an invoice: $3.00/1K × (0.7 + 0.01 × limit). limit=180 bills $7.50, which is 2.5× the headline — and $0.042 per 1,000 items, which is the number that matters. Two groups are billed to less depth than you ask for: include_following is billed to a depth of 50 and include_related to the default depth of 30, so at limit=180 they bill $3.60 and $3.00. You are never billed for depth a list cannot return.

Media costs bytes, so it is priced apart

include_media is the one option here whose cost is the file rather than the request, and it is billed as a surcharge on top of the call rather than folded into a band that hides it. The playback links are not what it buys — those come back on every video call at no extra charge.

It is opt-in and never free-eligible. When a hosted copy exists, the media block carries a link that needs no headers plus an expires_at; when one cannot be produced it says unavailable rather than returning a link that will fail later.

TikTok API Pricing, Side by Side

Every figure is the vendor’s own published rate. Units differ wildly here, so the table names each one and normalises to a comparable figure below.

Provider What one unit is Cost per 1,000 — entry Cost per 1,000 — lowest published What the lowest rate requires Free tier
Serpent API Per call. A profile or a video flat; a list call returns up to 180 items for one charge. $0.50 basic
$3.00 list call at limit=30
$0.35 basic
$2.10 list call at limit=30
A single $500 deposit, spendable as balance. No monthly plan and no daily bucket; the tier never expires or downgrades. 10 free API calls
Apify — clockworks/tiktok-scraper Per result (one post) $3.70 $0.50 Diamond plan, contact sales. Bronze $19/month is $3.00; Silver $199 is $2.30; Gold $999 is $1.70. $5 platform credit
Apify — xmolodtsov/tiktok-search-scraper Per post $0.30 $0.15 Diamond plan, contact sales. Gold and Business at $999/month are $0.20. $5 platform credit
Apify — pro100chok/tiktok-profile-pro Per profile $4.00 $3.00 Gold or above; Business is $999 per month $5 platform credit
Apify — get-leads/all-in-one-tiktok-scraper Per profile $2.40 $1.50 Gold or above; Business is $999 per month $5 platform credit
ScrapingDog Per request (5 credits) $1.00 (LITE, $40/month) $0.136 $30,000 per month 200 credits
Bright Data Per record $1.50 (pay as you go) $1.30 Scale plan, $499 per month 5,000 records/month
EnsembleData Per unit, drawn from a daily bucket that does not roll over about $2.22 per 1,000 units (Wood, $100/month, 1,500 units/day) about $0.93 per 1,000 units Platinum, $1,400 per month — and only if you spend the full daily allowance every day. The bucket resets at 00:00 UTC. 50 units/day

Normalised per item, which is the only fair way to read the rows above. Rates checked against each vendor’s own live pricing page on 2026-09-08. An enriched list call here returns 30 items at the default depth and 180 at the cap, so per item it is $0.100 per 1,000 items at limit=30 and $0.042 at limit=180 on Default, or $0.029 at limit=180 on Scale. Against the cheapest Apify TikTok actor that is 3× below its $0.30 free-tier rate and 1.5× below its $0.15 enterprise floor at the default depth, widening to 3.6× at limit=180. Two rows genuinely beat us and they are in the table above. ScrapingDog’s floor of $0.136 per 1,000 requests is below our $0.35 basic call — it needs $30,000 a month. EnsembleData’s Platinum plan normalises to roughly $0.047 per 1,000 posts on Search Hashtag, where one unit returns 20 posts: about twice as cheap as our default-depth $0.100, and slightly dearer than our $0.042 at limit=180. It costs $1,400 a month and holds that rate only if you spend the full daily allowance every single day.

What Teams Actually Pull TikTok Data For

Four jobs that account for most TikTok data traffic, and the endpoint, depth and parameters each one needs.

Creator research and outreach lists

A basic /api/tiktok/profile call is the flat rate and carries bio, bio_link, region, verified, private_account, commerce_user and the follower and like counts — enough to qualify a creator without paying for depth.

Add include_posts only for the handles that survive the first filter. That keeps the expensive band on the shortlist rather than on the whole scan.

Trend and hashtag tracking

Poll /api/tiktok/hashtag on a tag list and diff the item set day over day. One call returns the whole page for one charge, and has_more plus next_cursor tell you whether there was more behind it.

Set limit deliberately: it is the parameter that moves the invoice. A daily limit=30 sweep and a weekly limit=180 deep pull is usually cheaper than either alone.

Sound and campaign monitoring

/api/tiktok/music takes a music id or a sound URL and returns the items that used it, in the same envelope. That is how you measure whether a brand sound is actually being picked up rather than just posted.

Each item carries the true author, so a spike resolves to the creators who caused it instead of to whoever reposted it hardest.

Audit-safe bulk collection

truncated, restricted and complete, plus a partialResults block naming requested and returned, keep a bulk run honest: a short list is labelled short rather than filed as a finding.

That matters most when the output is a report someone else will act on. A silently truncated feed and a genuinely quiet week look identical in a chart, and only one of them is real.

Bash — daily hashtag sweep with an honest short-list check
# One line per tag: date, tag, items returned, and whether the list was complete.
# limit=30 is the default depth and the cheapest per call — deepen only when it pays.
while IFS= read -r tag; do
  curl -s -G "https://apiserpent.com/api/tiktok/hashtag" \
      --data-urlencode "tag=$tag" -d "limit=30" -d "country=us" \
      -H "X-API-Key: $SERPENT_API_KEY" \
    | jq -r --arg t "$tag" \
        '[$t, (.result_count|tostring), (.complete|tostring), (.restricted|tostring)] | @csv' \
    | sed "s|^|$(date -u +%F),|" >> tiktok-tags.csv
done < tags.txt

TikTok API Questions

Not yet. /api/tiktok/profile, /video, /hashtag, /search and /music are in prelaunch and are not served. Everything on this page — the field lists, the parameters, the list envelope and the rates — describes the contract they ship with. The rates are target rates and are unverified until launch. Join the list and we will mail you the day the endpoints start answering; there is no card and no commitment.
Five: profile, video, hashtag, search and music. Profile and video return a single record and accept optional include_* groups; hashtag, search and music are list calls. Every list on every endpoint — a profile’s posts, a hashtag feed, a keyword search, the videos using one song — comes back in the same items[] envelope, so a parser written for one reads all of them.
Two bands. Basic is a profile or video call with no include_* groups: $0.50 per 1,000 calls on Default, $0.45 on Growth, $0.35 on Scale. Enriched is any call with an include_* group, plus every hashtag, search and music call: $3.00 per 1,000 calls on Default, $2.70 on Growth and $2.10 on Scale at the default limit=30. Enriched is priced by depth, so those figures are the limit=30 price and not a flat rate — see the depth question below. Growth unlocks at a single $100 deposit and Scale at $500; both are one-time and neither ever downgrades.
Because an enriched call is charged as a fixed part plus a per-item part. The exact charge is $3.00/1K × (0.7 + 0.01 × limit) at Default. So limit=30, the default, is exactly the published $3.00; limit=100 is $5.10; and limit=180, the synchronous cap, is $7.50 — two and a half times the advertised rate. Per item it falls the other way: $0.100 per 1,000 items at limit=30, $0.051 at limit=100 and $0.042 at limit=180 ($0.029 on Scale). Two groups are billed to less depth than you ask for: include_following is billed to a depth of 50 and include_related to the default depth of 30, so at limit=180 they bill $3.60 and $3.00 rather than $7.50 — you are never billed for depth a list cannot return. Set limit deliberately. It is the one parameter on this API that changes your invoice.
It is a surcharge charged on top of the call, not a band that replaces it. Media is $10.00 per 1,000 on Default, $9.00 on Growth and $7.00 on Scale, so a basic video call with include_media is $0.50 + $10.00 = $10.50 per 1,000 at Default — not $10.00. It is opt-in and never free-eligible, because it is the only part of this API whose cost is the bytes rather than the request. When a hosted copy exists the media block carries a link that needs no headers plus an expires_at; when one cannot be produced the block says unavailable.
items[] and result_count are what arrived. total_count is TikTok’s own stated total and is null when TikTok did not state one — it is never back-filled from result_count, because that would turn “we do not know” into a number. has_more and next_cursor are what TikTok said about the page after this one. truncated means TikTok cut the list short, restricted means the list is not public, and complete means we reached the natural end and there is genuinely nothing more. Those three are different facts and the envelope keeps them apart.
You get what we hold, and the response says so. A short list carries a top-level partialResults block with requested and returned, plus a reason only when it is short by more than 40%, and a note. A list that genuinely comes back empty, or a profile or video that does not exist, is an answer and is charged; a failure on our side is refunded. Nothing is silently truncated to make a response look complete.
On some units, yes, and the comparison table on this page shows every one of them. ScrapingDog’s floor is $0.136 per 1,000 requests, below our $0.35 basic call — it needs $30,000 a month. Apify’s xmolodtsov/tiktok-search-scraper is $0.30 per 1,000 posts on the free tier and $0.15 at enterprise. EnsembleData’s Platinum plan normalises to roughly $0.047 per 1,000 posts at $1,400 a month, and only if you spend the full daily allowance every day. Where we win is the enriched list per item: $0.100 per 1,000 items at the default depth and $0.042 at limit=180, against that $0.15 enterprise floor. And there is no monthly plan and no daily bucket here at all.
Neither. There is no monthly plan anywhere in Serpent’s pricing and no per-day allowance. Growth and Scale are earned by a single deposit of $100 and $500, that deposit is spendable balance rather than a fee, and the tier is permanent — it never downgrades if your usage drops. A vendor whose allowance resets at 00:00 UTC and does not roll over cannot let a busy week borrow from a quiet one; a balance can.
Yes. The box at the top of this page sends a real profile request with no signup and no key, and prints exactly what the endpoint returns — which, while TikTok is in prelaunch, is the standard unavailable message. A signed-up account gets 10 free API calls, shared across every free-eligible endpoint, with no card required. Media is the one thing the free calls never cover.

Join the TikTok API list

Start using the TikTok API

The endpoints are not served yet. Join and we’ll mail you the day they start answering. No card, no commitment, and the 10 free API calls are waiting on every other endpoint in the meantime.

10 free API calls, shared across every free-eligible endpoint. No card, no subscription, no monthly plan and no daily bucket. TikTok profile and video data from $0.35/1K calls.

Get your free API key

Related guides

More on working with social and creator data in code.

Best TikTok Scraping APIsEvery vendor compared on price, unit and list honesty. Build a TikTok Scraper in PythonA runnable route to profile, video and hashtag records. Instagram APIProfiles and recent posts in the same call, at the same price. YouTube APIChannel, video and search data without a quota unit. Social Media APIEvery social surface in the catalog, on one key. The Cheapest SERP API in 2026A full cost comparison across every major provider. Amazon Scraper APIProduct, search and bestseller data across 22 marketplaces. PricingEvery published rate, and the two one-time deposit tiers.