TikTok transcript API: turn TikTok videos into text
A TikTok transcript API returns a video's captions as timed JSON segments and full text. 1 credit per video at any length. cURL, Python and SRT code.
By Scrape Everything team · · 11 min read
A TikTok transcript API takes a public TikTok video URL and returns its captions as timed segments plus the full text. With the Scrape Everything TikTok Transcript API, one POST /v1/tiktok/transcript call costs 1 credit per video, whatever its length. Videos without captions return 404 NO_TRANSCRIPT.
A TikTok transcript is the text of a video's captions, added by the creator or generated by TikTok, with a start time and duration for every line. We don't listen to the audio. We read the caption tracks TikTok already attached to the video and return them as clean JSON, so turning a TikTok video to text is one HTTP request instead of a speech pipeline.
What does the TikTok transcript API return?
Seven fields, straight from the endpoint's response schema:
| Field | Type | What it holds |
|---|---|---|
video_id | string | The numeric TikTok video ID |
language | string | TikTok's language code for the returned captions, for example eng-US |
is_auto_generated | boolean or null | true when the captions came from speech recognition or machine translation |
available_languages | array | Every caption track on the video, each with code and is_auto_generated |
segments | array | Caption lines in order, each with start, duration and text |
text | string | All segments joined into one string |
segment_count | integer | Number of segments |
Times are in seconds, rounded to 2 decimals. TikTok serves its captions as WebVTT files. We parse the cues, skip the header, NOTE and STYLE blocks, strip the styling tags and decode HTML entities, so text is plain prose you can paste into a prompt.
How do I get a TikTok transcript from a video URL?
- Sign up and copy your API key from the dashboard. New accounts get 100 free credits, no payment details needed.
- Put the key in an environment variable called
SCRAPEEVERYTHING_API_KEY. - Send the full video URL (or the numeric ID as a string) to
/v1/tiktok/transcript.
curl -X POST https://api.scrapeeverything.com/v1/tiktok/transcript \
-H "Authorization: Bearer $SCRAPEEVERYTHING_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.tiktok.com/@example_user/video/7400000000000000001"}'Swap in any public video link. The response, trimmed (placeholder values):
{
"success": true,
"data": {
"video_id": "7400000000000000001",
"language": "eng-US",
"is_auto_generated": true,
"available_languages": [
{ "code": "eng-US", "is_auto_generated": true },
{ "code": "spa-ES", "is_auto_generated": true }
],
"segment_count": 14,
"text": "Okay so I tried three cold brew makers this week and only one of them ...",
"segments": [
{ "start": 0.0, "duration": 2.4, "text": "Okay so I tried three cold brew makers this week" },
{ "start": 2.4, "duration": 1.9, "text": "and only one of them" }
]
},
"meta": { "credits_charged": 1, "cached": false }
}A 9-second clip and a 10-minute video cost the same 1 credit. That's the nicest side effect of reading captions instead of transcribing audio.
One gotcha. Short share links like vm.tiktok.com/... or tiktok.com/t/... aren't supported and return 400 VALIDATION_ERROR. Open the link in a browser, copy the full tiktok.com/@user/video/... address, and send that.
Does TikTok have an official transcript API?
Not one most developers can use. TikTok has two developer products worth checking, and neither fits a typical commercial project:
- The Display API returns videos for a user who logged in through your app. Its video object has fields like
title,video_description,durationandview_count, but no captions or transcript field. - The Research API does have a
voice_to_textfield in its video query. Access is limited to eligible academic and not-for-profit researchers in specific regions, by application.
Here's how the realistic options compare, using only what each one documents:
| Option | Who can use it | Returns caption text | Cost model |
|---|---|---|---|
Scrape Everything tiktok.transcript | Anyone with an API key | Yes, timed segments + full text, for videos with captions | 1 credit per video, any length |
| TikTok Display API | Apps where the video owner logs in | No caption field | Free, requires a registered TikTok app |
| TikTok Research API | Approved academic and not-for-profit researchers | Yes, voice_to_text | Free, by application |
| Download audio + your own speech-to-text | Anyone | Yes, also for videos without captions | Your compute or a speech API billed by audio length |
| Free TikTok Transcript Generator | Anyone, no signup | Yes, one video at a time | Free, daily limit per visitor |
If you qualify for the Research API and it covers your study, use it. First-party access is the better foundation for published research. Everyone else is choosing between reading existing captions and running speech recognition themselves.
What happens when a TikTok video has no captions?
You get 404 with code NO_TRANSCRIPT. No captions means no transcript, and we don't paper over that.
That's a deliberate trade. We don't run speech-to-text on the audio, so the price stays at 1 credit regardless of length, and you never receive text a model guessed at while presenting it as the video's captions. The cost is coverage: if a creator didn't add captions and TikTok didn't generate any, there's nothing for us to return.
NO_TRANSCRIPT also comes back for a language the video doesn't offer, and for videos that aren't in the creator's public feed. It's a final answer, billed like NOT_FOUND and the other final 404s on the errors page. Retrying returns the same result and is charged again. The cache only stores successful responses, so keep your own list of caption-less videos.
If you need text from those videos anyway, route them to a speech model you pick. The fallback is a few lines:
def get_text(url: str) -> dict:
t = call("/v1/tiktok/transcript", {"url": url, "cache_days": 14})
if t.get("success"):
return {"source": "captions", "text": t["data"]["text"]}
if t.get("code") == "NO_TRANSCRIPT":
# Your own pipeline: download audio, run a speech model, store the result.
return {"source": "speech_model", "text": transcribe_audio_yourself(url)}
raise RuntimeError(t.get("code"))call is the small helper defined in the brand-mention script further down, and transcribe_audio_yourself is whatever speech setup you already trust. Tag the source, because captions and model output deserve different levels of trust downstream.
How do I get a TikTok transcript in another language?
Leave lang out and you get the track TikTok marks as the video's original language (or the first track, if none is marked). Pass lang to ask for a specific one. Two kinds of codes work:
- A short ISO 639-1 code such as
en,es,deorpt. We map it to TikTok's codes, soenmatcheseng-US. - TikTok's code exactly as it appears in
available_languages, such aseng-USorspa-ES.
An exact match wins. With a regional code like pt-BR, a track from the same region beats other Portuguese tracks. Anything not shaped like a language code returns 400 VALIDATION_ERROR.
curl -X POST https://api.scrapeeverything.com/v1/tiktok/transcript \
-H "Authorization: Bearer $SCRAPEEVERYTHING_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.tiktok.com/@example_user/video/7400000000000000001", "lang": "es"}'If the language isn't there, the NO_TRANSCRIPT message lists the codes that are. Cheapest fallback: request without lang, read available_languages, pick one.
TikTok sometimes attaches machine-translated tracks. They come back with is_auto_generated: true, same as speech-recognition captions. If you need the words the creator actually said, take the original track (the default without lang) and translate it yourself with a model you trust.
How do I check if a creator mentioned my brand on TikTok?
Sponsored deals often require the creator to say the product name on camera, not just tag it in the description. Checking that by watching every video gets old fast. Transcripts make it a search problem.
- Call
tiktok.postswith the creator's username. It returns the profile plus up to 12 of their newest videos, each with alink. - Call
tiktok.transcriptfor each link. - Search
segmentsfor your brand terms and keep the timestamps, so a person can jump straight to the moment.
import os
import re
import requests
API = "https://api.scrapeeverything.com"
HEADERS = {
"Authorization": f"Bearer {os.environ['SCRAPEEVERYTHING_API_KEY']}",
"Content-Type": "application/json",
}
# Swap in your own brand terms.
BRAND = re.compile(r"\b(acme|acme coffee)\b", re.IGNORECASE)
def call(path: str, body: dict) -> dict:
r = requests.post(f"{API}{path}", json=body, headers=HEADERS, timeout=90)
return r.json()
feed = call("/v1/tiktok/posts", {"username": "example_user", "limit": 12})
if not feed.get("success"):
raise SystemExit(f"posts failed: {feed.get('code')}")
for post in feed["data"]["posts"]:
t = call("/v1/tiktok/transcript", {"url": post["link"], "cache_days": 14})
if not t.get("success"):
# NO_TRANSCRIPT just means the video has no captions; skip it
print(f"{post['id']}: {t.get('code')}")
continue
hits = [s for s in t["data"]["segments"] if BRAND.search(s["text"])]
for s in hits:
print(f"{post['link']} @{s['start']:.1f}s {s['text']}")Cost for one creator: 1 credit for the feed plus up to 12 for transcripts, so 13 credits. The Builder pack ($39 for 25,000 credits) covers about 1,900 creators. On Scale ($449 for 500,000 credits) it's roughly a cent per creator.
Re-runs are cheaper still.
With cache_days: 14, checking the same creator again within two weeks returns stored transcripts for 0 credits (the caching docs explain the 1 to 14 day window). Failed requests on our side, like timeouts and platform blocks, are refunded automatically. If you also want likes, shares, saves and duration for the videos that matched, add a tiktok.video call for those only. The rest of the TikTok endpoints are covered in our TikTok scraper API guide.
How do I download TikTok subtitles as an SRT file?
We return JSON, not files, but segments has everything an SRT needs. This turns one response into a file most video editors accept:
def to_srt(segments: list[dict]) -> str:
def ts(sec: float) -> str:
ms = int(round(sec * 1000))
h, ms = divmod(ms, 3_600_000)
m, ms = divmod(ms, 60_000)
s, ms = divmod(ms, 1000)
return f"{h:02}:{m:02}:{s:02},{ms:03}"
blocks = []
for i, seg in enumerate(segments, 1):
end = seg["start"] + (seg["duration"] or 0)
blocks.append(f"{i}\n{ts(seg['start'])} --> {ts(end)}\n{seg['text']}\n")
return "\n".join(blocks)
# t is a successful /v1/tiktok/transcript response
with open("captions.srt", "w", encoding="utf-8") as f:
f.write(to_srt(t["data"]["segments"]))Want WebVTT instead? Add a WEBVTT header line, drop the index numbers and use a period instead of a comma before the milliseconds.
How do I feed a TikTok transcript to an LLM?
Send text for summaries. Send segments when you need citations.
TikTok videos are short, so a TikTok transcript for LLM work usually fits in one prompt with no chunking, unlike an hour-long YouTube talk. Length is rarely the problem. Auto captions mishear product names, slang and anything said over music. Pass is_auto_generated to the model and tell it the captions may contain errors.
A prompt pattern that keeps the model honest:
Transcript of a TikTok video (captions, auto_generated=true, language=eng-US).
Each line is [start_seconds] text.
[0.0] Okay so I tried three cold brew makers this week
[2.4] and only one of them
...
Task: summarize in 2 sentences, list every product named, and give the
timestamp where each product is first mentioned. Captions may contain
recognition errors; flag uncertain product names.Formatting segments as [start] text lines keeps timestamps in context, so the answer can point to the exact second.
For agents rather than scripts, our MCP server (@scrapeeverything/mcp, listed in the official MCP Registry) exposes the API as tools, so Claude, Cursor or any Model Context Protocol client can fetch a transcript mid-conversation. The AI agents use case walks through setup. Prefer building flows visually? There's an n8n node (n8n-nodes-scrapeeverything).
Can one pipeline handle TikTok and YouTube transcripts?
Yes, and we built it that way on purpose. The TikTok endpoint uses the same core response shape as our YouTube Transcript API: video_id, language, is_auto_generated, available_languages, segments with start / duration / text, a joined text and segment_count. Same inputs too: url or id, plus optional lang.
The differences that matter:
| TikTok transcript | YouTube transcript | |
|---|---|---|
| Input | Full video URL or numeric ID (as a string) | Watch, youtu.be, Shorts, live or embed URL, or 11-character ID |
| Language codes | TikTok codes such as eng-US | Codes such as en, de, pt-BR |
language_name | Not returned | Returned, e.g. English (auto-generated) |
| Machine-translated tracks | Can appear, flagged as auto-generated | Not returned by our endpoint |
| No captions | 404 NO_TRANSCRIPT | 404 NO_TRANSCRIPT |
| Cost | 1 credit | 1 credit |
Because the shapes match, the only platform-specific bit is the path. In Node 18+:
// transcripts.mjs
async function transcript(platform, url) {
const res = await fetch(`https://api.scrapeeverything.com/v1/${platform}/transcript`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SCRAPEEVERYTHING_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ url, cache_days: 14 }),
});
const body = await res.json();
return body.success ? { platform, ...body.data } : { platform, error: body.code };
}
console.log(await transcript("tiktok", "https://www.tiktok.com/@example_user/video/7400000000000000001"));To compare languages across platforms, normalize the code to its first part (eng-US to eng, en stays en) and keep a small lookup table. We chose not to rewrite TikTok's codes in the response, because then lang values copied from available_languages would stop round-tripping.
Is there a free TikTok transcript tool?
Yes. For one-off jobs, like saving a recipe or quoting a creator correctly, use the free TikTok Transcript Generator. Paste the full video link and you get every caption line with its start time, plus the whole transcript to copy. No signup.
It runs on the same endpoint, with a daily limit per visitor. Once you're past a handful of videos, or want JSON you can store, switch to the API.
What are the limits of a TikTok transcript API?
The main one is covered above: captions only, no speech-to-text. The rest:
- Public videos only. No logins, no private accounts. Scrape Everything is not affiliated with TikTok.
- Full URLs or numeric IDs only. Send
idas a string, because TikTok IDs are larger than JavaScript's safe integer range and get silently rounded as numbers. - Auto captions contain recognition errors. Treat brand-mention hits on them as leads for a person to confirm, not as proof.
tiktok.postsreturns at most the 12 newest videos per creator. It's a recent-activity check, not a back catalog. For ongoing monitoring, run it on a schedule and keep the links you collect.- Rate limits apply per account. At the time of writing, free accounts get 60 requests per minute and 5 concurrent, paid accounts 300 per minute and 20 concurrent. The rate limits page has the current numbers.
Public doesn't mean free of obligations. Transcripts are someone's spoken words, and a creator is often an identifiable person, so data protection rules and copyright can apply to what you store and republish. Our post on whether scraping public social media data is legal covers the questions to ask, and TikTok's own terms are worth reading before you build on its content.
FAQ
Is a TikTok transcript API the same as speech-to-text?
No. A TikTok transcript is the text of a video's captions, added by the creator or generated by TikTok, with a start time and duration for every line. The API returns those captions and doesn't process the audio. That's why it costs 1 credit regardless of length, and why videos without captions have no transcript.
How much does it cost to transcribe a TikTok video?
1 credit per video. Credits come in one-time packs that never expire: Builder $39 for 25,000 credits, Growth $119 for 100,000, Scale $449 for 500,000. New accounts get 100 free credits once, not monthly. Cached repeats are free, and the pricing calculator estimates a workload.
Does TikTok have an official transcript API?
Only for researchers. The Research API has a voice_to_text field, but access is limited to approved academic and not-for-profit researchers. The Display API's video object has no captions field.
Can I download TikTok subtitles in another language?
When the video has a track in that language, yes. Pass lang with a short code like es or a TikTok code from available_languages like spa-ES. If the track doesn't exist, you get 404 NO_TRANSCRIPT and the message lists the languages that do. To save it as a file, convert segments to SRT with the snippet above.
Why does my vm.tiktok.com link fail?
Short share links aren't supported and return 400 VALIDATION_ERROR. Open the link in a browser and use the full tiktok.com/@user/video/... URL, or send the numeric video ID as a string.
Do TikTok and YouTube transcripts use the same format?
The core fields match: video_id, language, is_auto_generated, available_languages, segments and text. YouTube adds language_name, and the language codes differ (eng-US on TikTok, en on YouTube). One parser handles both.
Try it on your own videos
Pick a creator you already track, run the brand-mention script, and see what they actually said on camera this month. It'll cost you about 13 credits.
Get 100 free credits, then try the TikTok Transcript API or browse every TikTok endpoint. Working mostly with long-form video? Our comparison of the best YouTube transcript APIs covers that side.