TikTok Transcript Scraper - $0.40 per 1,000
Pricing
from $0.40 / 1,000 transcript scrapeds
TikTok Transcript Scraper - $0.40 per 1,000
No caption track, no charge - a TikTok without one has nothing to transcribe. The rest come back as full transcript, timed segments, SRT and WebVTT, detected language, plus video id, author, caption and view count. $0.40 per 1,000 transcripts.
Pricing
from $0.40 / 1,000 transcript scrapeds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
TikTok Transcript Scraper
Paste TikTok video links, bare video ids or vm.tiktok.com share links, and get the spoken words back as text. Every row carries the full transcript, the timed segments behind it, the detected language, and the video it came from: id, author, caption, duration, upload date and view count.
No account to set up, no cookies to paste, no browser, no API key.
- It reads the caption track TikTok itself generates for the video, so the words match what the app shows on screen. Nothing is re-transcribed and nothing is guessed.
- Every row ships four shapes of the same transcript: flat
text, timedsegments, ready-madesrt, and the originalvtt. - A video with no speech is never charged. It comes back as a free diagnostic row naming the video, so you can see what was skipped.
- Ask for a specific language and you get the translated caption track when TikTok has one, with
isTranslatedmarking those rows. - Up to 1,000 links per run, fetched in parallel, deduplicated before anything is billed.
- Empty input returns one labelled sample row, free.
Price
$0.40 per 1,000 transcripts. Plus $0.0005 per run as the platform start fee, billed per gigabyte of run memory, so exactly that on the default 1 GB.
No volume tiers, no minimum spend, no subscription.
| Transcripts | Total |
|---|---|
| 100 | $0.0405 |
| 1,000 | $0.4005 |
| 10,000 | $4.0005 |
| 100,000 | $40.0005 |
What gets charged
- One
transcript-scrapedevent per transcript row written to the dataset. Nothing else is metered per row. - Free: the sample row an empty run returns, and every diagnostic row. They all carry
"charged": false. - A video with no caption track is a free
NO_TRANSCRIPTrow, not a charge. - Deleted, private, age-restricted and region-locked videos are free diagnostic rows too.
- A link pasted twice, or pasted once as a share link and once as a full URL, is fetched once and charged once.
- A run that finds nothing costs the start fee and nothing else.
- Rows never leave the dataset without a charge and are never charged without a row. The billed event is a named one, so nothing is quietly attached to
apify-default-dataset-item.
Input
{"videoUrls": ["https://www.tiktok.com/@baobei55555j/video/7516208601434819862","https://www.tiktok.com/@studywithlizzz/video/7657803613355412766","7673152431932378389"],"maxItems": 10,"concurrency": 6}
| Field | What it does |
|---|---|
videoUrls | The videos you want transcribed. A full link, a vm.tiktok.com or vt.tiktok.com share link, or the bare numeric video id. All three work and you can mix them. Up to 1,000 per run. |
maxItems | How many transcripts to return at most. The list is read in order and the run stops as soon as it has this many, so it's a spend cap as much as a row cap. Links past that point cost nothing. Default 10, hard ceiling 5,000. |
language | A language code such as es, fr, de or ja. When TikTok holds a translated caption track for the video you get that one and the row is marked isTranslated: true. When it doesn't, you get the original spoken track instead of an error. Leave empty for the original. |
concurrency | How many videos to read at once. Default 6, maximum 12. Lower it on a very long list if you want to be gentle. There's no reason to raise it for small runs. |
sessionCookies | Optional, and empty is the normal case. See Age-restricted videos. |
proxyUrls | Leave empty. Only for callers who want traffic to leave through proxy servers they already pay for, as http://user:pass@host:port. |
Run it with empty input and you get one labelled sample row, free.
Output
One row per transcript. This is a real row from a real run:
{"ok": true,"charged": true,"recordType": "transcript","videoId": "7516208601434819862","url": "https://www.tiktok.com/@baobei55555j/video/7516208601434819862","inputUrl": "https://www.tiktok.com/@baobei55555j/video/7516208601434819862","authorUsername": "baobei55555j","authorName": "Baobei5","authorUrl": "https://www.tiktok.com/@baobei55555j","caption": "Real NASA Footage? Scientist Walks Moon! #NASA #MoonMission #MoonLanding #Space #Astronaut","hashtags": ["NASA", "MoonMission", "MoonLanding", "Space", "Astronaut"],"durationSeconds": 8,"createdAt": "2025-06-15T16:08:11.000Z","language": "eng-US","languageCode": "en","languageName": "English","isAutoGenerated": true,"isTranslated": false,"captionSource": "ASR","text": "So, guys, we've just landed on the moon. And as you can see, Tori, this view is insane. It's freezing out here. This is just day 1. More to come.","wordCount": 30,"characterCount": 145,"segmentCount": 5,"segments": [{"start": 0,"end": 0.46,"startTime": "00:00:00.000","endTime": "00:00:00.460","text": "So, guys,"},{"start": 0.461,"end": 1.741,"startTime": "00:00:00.461","endTime": "00:00:01.741","text": "we've just landed on the moon."}],"srt": "1\n00:00:00,000 --> 00:00:00,460\nSo, guys,\n\n2\n00:00:00,461 --> 00:00:01,741\nwe've just landed on the moon.","vtt": "WEBVTT\n\n00:00:00.000 --> 00:00:00.460\nSo, guys,\n","availableLanguages": ["eng-US"],"playCount": 40900,"likeCount": 795,"commentCount": 24,"shareCount": 18,"musicTitle": "original sound - aiunderstandyou4","coverUrl": "https://p16-common-sign.tiktokcdn.com/tos-no1a-p-0037-no/o8aRuyBFEiAfIwCTGAikA7CAF2u4fVUOog4Bgt~tplv-tiktokx-origin.image","scrapedAt": "2026-08-16T15:44:23.728Z"}
Field notes
textis the whole transcript as one readable string, with caption line breaks collapsed and stray spaces before punctuation cleaned up. The words themselves are untouched.segmentsis the same transcript as timed cues:startandendin seconds,startTimeandendTimeasHH:MM:SS.mmm, and the line of text. Use this for clipping, search-inside-video, or lining a transcript up with the footage.srtis the cues rebuilt as a standard SRT file, ready to save as.srt.vttis the original WebVTT exactly as served, for anyone who wants the untouched source.isAutoGeneratedis true when the track came from speech recognition rather than being written by a person.isTranslatedis true when the track is a machine translation rather than the language actually spoken.languageis the track's own code, likeeng-US.languageCodeis the two-letter form andlanguageNamethe English name, so you don't have to map it yourself.availableLanguageslists every caption track TikTok exposed for that video on that request, so you can see what else could have been asked for.durationSecondsis the video length, not the transcript length. A long video with two spoken words has a long duration and a short transcript.playCountis views at read time. It keeps moving.inputUrlis exactly what you pasted, so rows join back to your own list.urlis the canonical link with the real author handle filled in.
Real rows carry "charged": true. Sample rows carry "_sample": true, diagnostic rows carry "_diagnostic": true and an errorCode. Neither is billed.
How it works
It asks TikTok for the video's own page the way a phone browser does and reads the caption track out of the data the page already carries. One request per video, no page rendering, no headless browser, no login.
The caption file itself is fetched from TikTok's subtitle store and parsed into timed cues, then rebuilt into plain text and SRT. Requests leave through a rotating pool of addresses, so a per-address rate limit is answered by moving rather than waiting. Videos are read in parallel, with a small ladder of retries per video so one bad moment on one address doesn't cost you a row. Two independent readers run against every page, so a layout change on TikTok's side doesn't take the Actor down with it.
Age-restricted videos
Every video is read without an account. That's the fast path and it's what nearly all of them answer.
A few won't. An age-restricted video is the clear case: TikTok shows it only to a signed-in viewer. Those come back as free NOT_FOUND diagnostic rows and the run carries on with the rest of your list.
If you need them, paste your own TikTok cookie into sessionCookies:
- Sign in to TikTok in Chrome.
F12→ Application → Cookies →https://www.tiktok.com.- Copy the
sessionidvalue and pass it as"sessionid=<value>".
The cookie goes to TikTok's video pages and nowhere else. Caption files come from a CDN and no cookie is sent with them. Its value is never written to the log. You can pass several and the run rotates between them. The run's status line reports sessionState so you can tell which kind of run you had: keyless when nothing needed an account, then ok, degraded or exhausted.
How much of TikTok actually has a transcript
TikTok creates a caption track when it detects speech, and creators can upload their own. It doesn't create one for a clip that's only music, only sound effects, or silent, and a photo slideshow has no audio track at all.
On a random 120-video sample pulled from TikTok's own topic pages, 85 videos had a caption track and 35 did not. Talking-head, tutorial, news and review content is close to universally covered. Dance, comedy skits without dialogue, and music edits usually aren't.
The 35 that had nothing cost nothing. Each came back as a free NO_TRANSCRIPT row naming the video. So the worst case for a list of links that turns out to be all music is a run that bills the start fee and nothing else.
What people use it for
- Feeding TikTok content to a language model for summaries, topic tagging or translation, without paying a speech-to-text bill for audio that already has captions.
- Repurposing short video into blog posts and newsletters. The transcript is the first draft.
- Content research at scale. Pull the transcripts of a hundred videos in a niche and search them for the phrases and objections that keep coming up.
- Subtitle work. Take the
srtorvttstraight into an editor, retime it, translate it. - Accessibility archives, where the spoken content of published videos has to be kept in text form.
- Building a searchable index of a creator's back catalogue, so "which video mentioned X?" becomes a text query.
- Hook analysis.
segmentsgives you the first three seconds of speech separately from the rest, which is the part that decides whether anyone watches.
Reading the output
- Real rows carry
"charged": trueand"recordType": "transcript". One billed event each. - The sample row carries
"_sample": trueand"charged": false. There's exactly one, only when the input had no videos. - Diagnostic rows carry
"_diagnostic": true,"charged": falseand anerrorCode:NO_TRANSCRIPTwhen the video has no caption track,NOT_FOUNDwhen it's deleted, private, age-restricted or region-locked,BAD_INPUTwhen a line wasn't a TikTok link,BLOCKEDwhen the target refused the request,NETWORKwhen it couldn't be reached,TIME_BUDGETwhen time ran out. Each carries a plain-Englisherrorand theinputUrlit belongs to.
Filter on charged == true and you have exactly the rows you paid for.
Limits
- A video only has a transcript if TikTok generated a caption track for it or the creator uploaded one. Roughly seven in ten videos in a mixed sample have one. Silent clips, music-only edits and photo slideshows don't, and those come back as free diagnostic rows.
- Nothing here listens to audio. If TikTok has no caption track, this Actor won't invent one. It tells you the track is missing instead.
- Auto-generated captions are speech recognition, so they carry its mistakes. Proper nouns, brand names, numbers and heavy accents are where they slip. Punctuation and sentence boundaries are approximate.
- Translated tracks (
isTranslated: true) are machine translations, not human subtitles. - Which translated languages exist is TikTok's decision per video, not a setting. Asking for a language TikTok doesn't have for that video returns the original spoken track, marked as such, rather than failing.
- On-screen text burned into the picture (stickers, overlays, meme captions) isn't part of the caption track and isn't returned.
- Private, friends-only, deleted, age-restricted and region-locked videos come back as free diagnostic rows saying which it was.
- Timings come from the caption file, so they're cue timings rather than word-level timings. There's no per-word timestamp.
- View, like, comment and share counts are a snapshot at read time.
- Hard ceilings: 1,000 links and 5,000 transcripts per run.
- Live videos and stories are out of scope. This reads regular posted videos.
- The run works down your list until it has the number of transcripts you asked for, so extra links are a useful buffer against videos that turn out to have none. It gives up early only when a list is almost entirely caption-less, roughly three fruitless lookups per transcript requested and never fewer than 25, and it says so in a free diagnostic row rather than failing.
Questions
What happens if a video has no captions?
One free diagnostic row with errorCode: "NO_TRANSCRIPT" naming the video, and the run carries on.
Can I paste share links from the app?
Yes. vm.tiktok.com, vt.tiktok.com and tiktok.com/t/ links are all followed to the real video. You can also paste the bare numeric video id, and mix all of these in one list.
Does it transcribe the audio?
No, deliberately. It reads the caption track TikTok already made, which is the same text the app shows on screen. That's faster, it costs a fraction of running speech-to-text, and for the videos that have it, it's the better transcript.
Can I get the transcript in another language?
Set language to a code like es or fr. When TikTok holds a translated caption track for that video you get it, marked isTranslated: true. When it doesn't, you get the original spoken track rather than an error, so a batch never dies because one video wasn't translated.
Do I need a proxy?
No. The run brings its own egress and its cost is already inside the price. proxyUrls exists only for callers who want traffic to leave through servers they already own.
Will the run fail if something goes wrong?
No. A blocked, deleted or caption-less video produces an uncharged diagnostic row and the run still finishes as succeeded. A failed run would still bill the start fee, which would mean paying to be told something went wrong.
Can I run it on a schedule?
Yes. Nothing is held between runs. Use videoId to work out which rows are new since last time.