TikTok Video Transcript — AI Video to Text & SRT
Pricing
from $7.20 / 1,000 audio minutes
TikTok Video Transcript — AI Video to Text & SRT
Get a TikTok transcript from any public video with AI speech-to-text, even without captions. Paste video or share links; get timestamped text, SRT/VTT subtitles for vertical video, speaker labels and RAG-ready JSONL. No login or API key. $0.013 per 1-minute video + $0.005 per run.
Pricing
from $7.20 / 1,000 audio minutes
Rating
0.0
(0)
Developer
Sergey Andronik
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
14 hours ago
Last modified
Categories
Share
Get a TikTok transcript from any public TikTok video, with timestamps, as JSON, SRT or VTT. TikTok Video Transcript turns TikTok video to text with AI speech-to-text, so it works whether or not the video has captions. Paste one link or a list of up to 1,000 and get one result per video: the full text, timed segments, subtitle files laid out for vertical video, optional speaker labels and optional RAG-ready passages for search, summaries or content analysis. No TikTok login, cookies or speech-provider API key are needed.
What you get for each TikTok video
- Transcript text in
text, plustranscript_llmwith one line per segment, ready to paste into an LLM prompt. - Timestamps per segment (
t0,t1in seconds), or per word withtimestamps: "word". - SRT and VTT subtitles in the result and as downloads in the run's key-value store
(
transcript-000.srt,transcript-000.vtt, numbered by input position). - Subtitle QA for short video: cues laid out at 28 characters per line by default, with a report of lines that are too long, too fast or too short.
- Readable paragraphs in
paragraphs(start_s,end_s,speaker,text) and astranscript-000.txtandtranscript-000.mddownloads, at no extra charge. See Readable output. - Speaker labels (S1, S2, …) with
diarize: true. - RAG passages with source URL and original-video seconds, inline as
rag_chunksand as atranscript-000.rag.jsonldownload, withexportRag: true. - Language detection, or a language hint you set.
- Billing per item: every row shows which events were charged, so you can match the bill to the videos.
How to get a TikTok transcript
- Paste your video URLs. Use full
tiktok.com/@user/video/…links or the shortvm.tiktok.com/…,vt.tiktok.com/…andtiktok.com/t/…share links. - Keep the defaults or adjust them. The defaults give segment timestamps and the short-video subtitle layout. Add a language hint, speaker labels or RAG passages if you need them.
- Set a run budget. In the run options, set a maximum charge for the run. The run stops before work it cannot pay for.
- Start the run and open the Dataset. Each URL becomes one row. Export it as JSON, CSV or Excel, or read it through the API. Download SRT and VTT files from the run's key-value store.
Input
{"urls": ["https://www.tiktok.com/@bbcnews/video/7654853125945183510"],"timestamps": "segment","subtitleProfile": "short"}
| Field | What it does |
|---|---|
urls | Up to 1,000 public TikTok video URLs. Required unless you set datasetId. |
datasetId | Read URLs from another run's dataset. See Chain from another Actor. |
datasetUrlField, maxItems | The dataset field that holds the URL (detected when empty), and how many rows to read (default 100, at most 1,000). |
language | Optional language code such as en, es or pt-BR. Omit it for automatic detection. |
timestamps | none (text only: no segments, words, SRT or VTT), segment (default) or word. |
subtitleProfile | short (28 characters per line, 0.5–4 s cues) or standard (42 characters per line, 1–7 s cues). Longer segments are split into cues within their time range, and the subtitle QA report is added. When you leave it empty and timestamps are on, short is used. Needs segment or word timestamps, so leave it empty with timestamps: "none". |
diarize | Speaker labels. Billed at the speaker-label rate instead of the normal per-minute rate. |
exportRag | Adds rag_chunks and a .rag.jsonl download. Needs segment or word timestamps. |
Start from a profile
Put public profile URLs in TikTok profiles (profileUrls) to transcribe their newest videos:
{"profileUrls": ["https://www.tiktok.com/@bbcnews"],"maxItemsPerSource": 10,"publishedAfter": "2026-10-01"}
- Profile URLs look like
https://www.tiktok.com/@bbcnews. The newest videos are listed and sorted by date, so pinned videos do not crowd out new ones. - Each row adds
source_url,source_type(tiktok_profile) andsource_title. publishedAfter(YYYY-MM-DD, UTC) uses the exact upload time from the listing.- TikTok's profile listing fails intermittently (in tests from one network on 2026-10-31, 4 of 10 attempts succeeded), so each profile is tried up to 3 times with a pause between tries.
- Rows of listed videos also carry
published_at, the upload time from the listing. maxItemsPerSource(default 20, at most 200) limits how many of the newest items each source contributes. A run holds at most 1,000 items in total, countingurlsand dataset rows.- Each listed item is processed and charged exactly like a URL you submit. Listing itself is free.
- The example link in the URL list is processed and charged too: remove it when you want only listed items.
- Listed items run after
urlsand dataset rows, source by source in input order; an item already in the run is skipped. - A source that cannot be listed becomes one error row with
source_urland anerrornaming it (for exampleprofileUrls[1]: …), and it is not charged. The other sources continue. If no source lists anything, the run fails before any charge. - The listing is saved when the run starts, so a restarted run keeps the same items even if the source changed meanwhile.
Scheduled runs: only new items
Turn on Skip items processed by earlier runs (skipPreviouslyProcessed) and run the
Actor on a schedule to get only what is new
since the last run.
- The Actor keeps a key-value store named
polyglot-processed-tiktokin your Apify account, orpolyglot-processed-tiktok--<memoryKey>when you set Memory name (memoryKey), so separate schedules can keep separate memories. Other Actors keep their own stores, even with the samememoryKey. It records each item after the item is delivered and charged; failed items are tried again next time. - It applies to every URL in the run: listed ones, dataset rows and the items listed from sources.
- When nothing is new, the run ends without any charge. Only error rows appear then, for sources or dataset rows that could not be used.
- If the store cannot be opened or read, the run stops before any charge, and the next scheduled run tries again. If an item's record cannot be written, the item is still delivered and the log says so; a later run may process and charge it again.
- Delete the store in Apify Console (Storage → Key-value stores) to start over. Do not run two runs with the same memory at the same time: both would process the same new items.
Chain from another Actor
Run a TikTok scraper such as clockworks/tiktok-scraper first, then paste the dataset ID of that run into Dataset ID
(datasetId) to transcribe every one of its TikTok videos:
{ "datasetId": "<dataset ID from the other run>", "maxItems": 200 }
- The Actor reads up to
maxItemsrows (default 100) with your own run's Apify token and takes each row's URL fromwebVideoUrl,url,postUrl,videoUrl,inputUrlorlink, or from the field you name indatasetUrlField. - Dataset URLs run after any
urlsyou list, in dataset order; a dataset URL that is already in the run is skipped. A run takes at most 1,000 URLs in total. - A row without a usable URL becomes an error item with its
dataset_rowindex, and it is not charged. Items from the dataset also carrydataset_row, so you can join the results back to the source rows. - The example link in the URL list is processed and charged too: remove it when you want only the dataset's items.
Output example
A real result from an Apify run on 2026-10-30, trimmed: 3 of 12 segments, the text cut, and the SRT, VTT and QA fields shortened.
{"url": "https://www.tiktok.com/@bbcnews/video/7654853125945183510","text": "If that's not a leader, I don't know what is. I think Harry Kane because he's a great leader, he's cool under pressure. …","language": "en","duration_s": 42.98,"engine": "groq/whisper-large-v3","segments": [{ "t0": 0, "t1": 2.08, "text": "If that's not a leader, I don't know what is." },{ "t0": 2.3, "t1": 5.98, "text": "I think Harry Kane because he's a great leader, he's cool under pressure." },{ "t0": 6.6, "t1": 8.04, "text": "Yeah, it's got to be Harry Kane for me." }],"srt": "1\n00:00:00,000 --> 00:00:02,080\nIf that's not a leader, I\ndon't know what is.\n\n…","subtitle_qa": { "profile": "short", "cue_count": 12, "issue_count": 18, "issues": [{ "cue_number": 1, "code": "reading_speed", "actual": 21.6, "limit": 20 }] },"usage": { "minutes": 1, "diarized": false, "platform_fetch": true },"billing": {"status": "paid","events": [{ "event": "platform-video-fetch", "requested_count": 1, "charged_count": 1, "state": "confirmed" },{ "event": "audio-minute", "requested_count": 1, "charged_count": 1, "state": "confirmed" }]}}
Clips with little speech or loud music can have their language misdetected. If you know
the language, set it, for example "language": "en".
Results also contain vtt, transcript_llm, source_duration_s, start_time_s and
end_time_s. A URL that fails returns a row with url and error. Very large results
may carry result_record_key instead of inline text; read that key from the run's
key-value store.
Readable output
Every transcript row has paragraphs: the transcript in order, grouped into blocks you can
read. A paragraph starts at a speaker change, after a pause of 2 seconds or more, and
before it would pass 800 characters or 90 seconds. Once it holds 400 characters, the next
sentence end closes it. No text is dropped or reordered, and a segment is never split in
timed output. Each paragraph is { "start_s", "end_s", "speaker", "text" }; speaker appears
only with diarize: true, and with timestamps: "none" there are no times and paragraphs
are cut at sentence ends by length alone. Rows without speech have no paragraphs.
The same paragraphs are saved to the run's key-value store, numbered by input position:
transcript-000.txt: paragraphs separated by blank lines, withS1:style speaker labels.transcript-000.md: a title when known, a list with the source URL, language and duration (and the author name when known), then each paragraph with its[mm:ss](or[h:mm:ss]) start time and bold speaker label.
When a row would pass the Dataset size limit, paragraphs is left out of the row first
(the text stays) and the downloads still hold it. Both downloads are free, like SRT and VTT.
How much does a TikTok transcript cost?
Pay per event, with no subscription. These are the Free-plan prices; paid Apify plans get lower per-minute prices. The Pricing tab shows the current prices for your plan.
| Event | Price | When |
|---|---|---|
| Run setup | $0.005 | Once per run. |
| TikTok video download | $0.005 | Per video whose audio was downloaded. |
| Audio minute | $0.008 | Per started minute of video, after transcription succeeds. |
| Diarized audio minute | $0.016 | Per started minute with speaker labels, instead of the audio minute. |
Worked examples, without speaker labels:
| Video length | 1 URL in a run | 100 URLs in a run |
|---|---|---|
| 1 minute or shorter | $0.005 + $0.005 + $0.008 = $0.018 | $0.005 + 100 × $0.013 = $1.305 |
| 3 minutes | $0.005 + $0.005 + 3 × $0.008 = $0.034 | $0.005 + 100 × $0.029 = $2.905 |
| 10 minutes | $0.005 + $0.005 + 10 × $0.008 = $0.090 | $0.005 + 100 × $0.085 = $8.505 |
With speaker labels, a 1-minute video costs $0.026 alone, and 100 of them cost $0.005 + 100 × $0.021 = $2.105.
- Minutes are rounded up once per video, and silence counts. A 61-second video is 2 minutes.
- A video with no detected speech (only music, silence or noise) returns
no_speech: truewith empty text and is not charged minutes, up to 30 such minutes per run; after that its minutes are charged. The download fee still applies. - Put many URLs in one run: the run setup fee is paid once per run, not per video.
- A failed download is not charged, and neither is a download that is not a playable audio or video file. A successful download stays charged if the transcription fails afterwards.
- Apify's own small run-start event is separate and is shown on the Pricing tab.
Use it from the API
Start a run with the Apify API client for JavaScript and read the results:
import { ApifyClient } from 'apify-client'const client = new ApifyClient({ token: process.env.APIFY_TOKEN })const run = await client.actor('andronixmd/tiktok-video-transcript').call({ urls: ['https://www.tiktok.com/@bbcnews/video/7654853125945183510'] },{ maxTotalChargeUsd: 0.1 },)const { items } = await client.dataset(run.defaultDatasetId).listItems()for (const item of items) console.log(item.url, item.error ?? item.text)
Or start one run over HTTP:
curl -X POST \-H "Authorization: Bearer $APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"urls":["https://www.tiktok.com/@bbcnews/video/7654853125945183510"]}' \'https://api.apify.com/v2/actors/andronixmd~tiktok-video-transcript/runs?maxTotalChargeUsd=0.1'
The Actor also works from n8n and other automation tools through Apify's integrations.
Use it from an AI agent (MCP)
Connect your agent to https://mcp.apify.com. It can find this Actor with search-actors, or
call it by name, andronixmd/tiktok-video-transcript, with call-actor. Use fetch-actor-details first for the
input schema and pricing. Every call starts a new paid run, so always set
callOptions.maxTotalChargeUsd and keep the urls list short:
{ "actor": "andronixmd/tiktok-video-transcript", "input": { "urls": ["https://www.tiktok.com/@bbcnews/video/7654853125945183510"], "timestamps": "segment", "subtitleProfile": "short" }, "callOptions": { "maxTotalChargeUsd": 0.1 } }
call-actor returns the run status and storage IDs, not the results. Read the rows with
get-dataset-items and the run's dataset ID. The fields to use are text, paragraphs and error.
With an Apify account, use your API token or MCP OAuth. Without one, an agent can buy a prepaid token from Apify AGI over x402 or MPP and use it as the Bearer token. It starts at $1, the balance is a hard spending cap, and the token expires after 14 days. This is experimental; see agentic payments.
Limitations
- Public videos only. Private, friends-only, age-restricted, region-blocked and removed videos, and anything that needs a login, are not supported. The Actor uses no accounts or cookies and does not try to get around TikTok's access checks.
- Videos and profiles. Hashtag, search, sound, photo-post and live URLs are not
accepted; profiles go in
profileUrls. Profile listing from Apify's servers has not been tested at scale. One URL in a wrong format rejects the whole input before the run starts. A short link that has expired or leads to something other than a video fails for that item only. - Not every public video will download. TikTok limits access from some networks and
regions and changes its site often, so some URLs return an error row instead of a
transcript. Check each row's
errorandbillingfields and retry failed URLs later. - Spoken audio only. Text drawn into the picture is not read. When TikTok lists the licensed music as a separate track, that track is not transcribed.
- Music-only videos can come back with lyrics or artefacts like the one in the example above, which are billed as speech. A video detected as having no speech is billed its minutes only after the run's 30 free no-speech minutes.
FAQ
Does it use TikTok's captions? No. It transcribes the audio, so it also works on videos without captions or subtitles.
Which languages does it support?
It detects the language automatically, and the supported languages depend on the
speech engine. For short clips with music, a language hint such as en, es or de
gives better results.
Can I transcribe a whole TikTok profile or hashtag?
A profile, yes: put it in profileUrls and set maxItemsPerSource. Hashtags, no.
Can I get SRT subtitles for a TikTok video?
Yes. With segment or word timestamps (segment is the default), each result contains
srt and vtt, and the files are saved in the run's key-value store.
What happens if a video fails?
You get a row with url and error. A failed download is not charged.
Do you store my transcripts or audio? Results stay in your Apify run storage, under your account's access and retention settings. The audio is sent to the speech-to-text provider that transcribes it. Only submit videos you are allowed to process.
Related Actors
- TikTok Video Scraper: views, likes,
hashtags, author and music for the same URLs, without the transcript, for $0.002 per
video. Submit the same URLs to both and join the results on
url. - Instagram Reel Transcript: the same transcript output for Instagram Reels.
- YouTube Transcript: YouTube captions, with AI speech-to-text when a video has none.
- Audio & Video Transcriber: podcasts, audio and video files and other sites.