TikTok Video Transcript — AI Video to Text & SRT avatar

TikTok Video Transcript — AI Video to Text & SRT

Pricing

from $7.20 / 1,000 audio minutes

Go to Apify Store
TikTok Video Transcript — AI Video to Text & SRT

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

Sergey Andronik

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

14 hours ago

Last modified

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, plus transcript_llm with one line per segment, ready to paste into an LLM prompt.
  • Timestamps per segment (t0, t1 in seconds), or per word with timestamps: "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 as transcript-000.txt and transcript-000.md downloads, 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_chunks and as a transcript-000.rag.jsonl download, with exportRag: 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

  1. Paste your video URLs. Use full tiktok.com/@user/video/… links or the short vm.tiktok.com/…, vt.tiktok.com/… and tiktok.com/t/… share links.
  2. 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.
  3. Set a run budget. In the run options, set a maximum charge for the run. The run stops before work it cannot pay for.
  4. 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"
}
FieldWhat it does
urlsUp to 1,000 public TikTok video URLs. Required unless you set datasetId.
datasetIdRead URLs from another run's dataset. See Chain from another Actor.
datasetUrlField, maxItemsThe dataset field that holds the URL (detected when empty), and how many rows to read (default 100, at most 1,000).
languageOptional language code such as en, es or pt-BR. Omit it for automatic detection.
timestampsnone (text only: no segments, words, SRT or VTT), segment (default) or word.
subtitleProfileshort (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".
diarizeSpeaker labels. Billed at the speaker-label rate instead of the normal per-minute rate.
exportRagAdds 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) and source_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, counting urls and 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 urls and 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_url and an error naming it (for example profileUrls[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-tiktok in your Apify account, or polyglot-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 same memoryKey. 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 maxItems rows (default 100) with your own run's Apify token and takes each row's URL from webVideoUrl, url, postUrl, videoUrl, inputUrl or link, or from the field you name in datasetUrlField.
  • Dataset URLs run after any urls you 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_row index, and it is not charged. Items from the dataset also carry dataset_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, with S1: 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.

EventPriceWhen
Run setup$0.005Once per run.
TikTok video download$0.005Per video whose audio was downloaded.
Audio minute$0.008Per started minute of video, after transcription succeeds.
Diarized audio minute$0.016Per started minute with speaker labels, instead of the audio minute.

Worked examples, without speaker labels:

Video length1 URL in a run100 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: true with 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 error and billing fields 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.