A TikTok transcript gives you text to search, quote or use in a draft. Social Fetch reads the video's caption track by default. If there is no track, you can opt into AI transcription of its audio. Neither route extracts the post description, hashtags or text drawn onto the video.
Caption tracks are WebVTT: each cue has words and a start and end time. AI transcripts are plain text with no timings. Text can be missing or inaccurate, so check the format and listen before quoting.
Get a transcript without code
- Open the free TikTok transcript generator.
- Paste a public video's full link, then click Get transcript. The Playground example below uses Duolingo's chess announcement.
- When text appears, choose Copy text, or Download for TXT, SRT or VTT. Timed downloads depend on the result having timings.

For the API you'll need a Social Fetch account, credits and, for code, an API key. The Quickstart shows how to create one. Keep the key on your server, outside browser code and public repositories.
Try the Playground
- Open the TikTok transcript request. Sign in if asked.
- Check that the endpoint is Get TikTok video transcript and url holds your video's link. Leave useAiFallback set to
falsefor this caption-only request. - Click Send, then read Response. This spends credits just like code. The example returns
found, awebvtttranscript and a charge of 1 credit.

Call it from code
The route is GET /v1/tiktok/videos/transcript. Send your key in x-api-key and the video link in the url query parameter. The link must start with https://; use a full public video URL so you can check which video you requested.
Set SOCIALFETCH_API_KEY in your terminal environment, then run this in a shell that supports the shown line continuations:
For TypeScript, run npm install @socialfetch/sdk tsx. Save this as transcript.ts, set the same environment variable and run npx tsx transcript.ts:
The SDK returns a Result: check ok before reading value. A successful HTTP request can still have no video or no transcript, so check lookupStatus and transcript too.
| Query parameter | Meaning |
|---|---|
url | Required HTTPS video link, trimmed and limited to 4,096 characters. |
language | Optional two-letter code, such as en, requesting that language when available. |
useAiFallback | Optional boolean. Defaults to off; true tries AI only when there is no caption track. |
allowLongTranscription | Optional boolean. Defaults to off; requires useAiFallback=true for long AI transcription and its per-minute price. |
language does not guarantee translation. This endpoint returns no detected language, language code or list of available languages. Do not infer those from the parameter you sent.
When there are no captions
A video can resolve as found with transcript: null: it was resolved, but no transcript was returned. This public Duolingo video returned no caption track on our caption-only lookup:

To try its audio, set useAiFallback to true and click Send again. In the TypeScript example, change useAiFallback: false to useAiFallback: true. In curl, add --data-urlencode 'useAiFallback=true'. This is another billed request. AI can still return no text; it cannot recover a private or deleted video.

Costs and longer videos
| Completed lookup | Credits charged |
|---|---|
| Caption track, no transcript, or video not found | 1 |
| Standard AI produces text, with useAiFallback true | 11 (base 1 + AI 10) |
| Long mode produces AI text, with both flags true | 1 + 10 per started minute of video, capped at 60 billed minutes / 601 credits |
Standard AI covers videos up to 120 seconds. For longer audio, set both useAiFallback: true and allowLongTranscription: true in the SDK request. In curl, send both --data-urlencode 'useAiFallback=true' and --data-urlencode 'allowLongTranscription=true'.
Long mode changes the price for short AI clips too: 61 seconds costs 21 credits, and 121 seconds costs 31. It replaces the flat AI surcharge; it does not add another flat 10 on top. The billing cap does not promise every long video will be available or transcribable. Caption reads and empty results still cost 1 credit with either flag on.
Keep at least 1 credit available for caption-only requests, 11 for standard AI, and 601 for long-mode AI. The preflight checks the maximum possible charge before the lookup, even if it eventually returns captions for 1 credit. Read meta.creditsCharged for the actual completed charge. Cached lookups still cost credits.
A photo carousel is a billed domain failure: 400 transcript_target_not_video costs 1 credit. Validation and authentication failures, 502 lookup_failed and 503 temporarily_unavailable cost nothing. See Credits and Errors. In the app, open Usage, then Request history to check a request's cost.
Read and save the result
Every successful response has data and meta. TikTok's data contains:
| Field | What to check |
|---|---|
data.lookupStatus | found or not_found. HTTP 200 alone does not mean a video was found. |
data.video | Resolved id and canonical url, or null when not found. |
data.transcript | An object with format and content, or null when no transcript is available. |
data.transcript.format | webvtt for timed caption cues; text for an untimed AI transcript. |
data.transcript.content | Raw text to save or parse. There is no TikTok plainText or segments field. |
meta.creditsCharged | The actual charge. |
meta.requestId and meta.version | Request identifier for support, and API version. |
For not_found, do not read video.id or transcript content. For found with a null transcript, skip the video or deliberately opt into AI. Private, removed and unavailable videos cannot be guaranteed to resolve, even if their links open for you in a signed-in TikTok account.
From WebVTT to plain text
Keep WebVTT unchanged for timed captions. This helper joins cue text from simple tracks like the example and accepts an AI transcript unchanged. It is not a complete subtitle renderer; use a WebVTT parser if you need styling or other cue metadata.
Call transcriptToText(data.transcript.format, data.transcript.content) after checking that data.transcript is not null. Below are the first three real cues from the chess announcement and the same words joined together:

Research the first caption cues
For hook research, pair the first caption cue with views from getProfileVideos. This saved Duolingo sample includes videos with and without caption tracks. Nulls stay empty rather than being filled with guessed words.

Keep the original URL alongside saved text so you can return to the source. Listen before publishing quotes, check names and unclear speech, and get permission where your intended use requires it.
Troubleshooting
foundwithtranscript: null: no transcript was returned. Try AI deliberately, or skip the video. It is still a 1-credit completed lookup.not_found: check that the link identifies a public video. Deleted or private content may not be available. Repeating the same completed lookup still costs credits.400 transcript_target_not_video: the target has no video, such as a photo post. Use a video link. This domain failure costs 1 credit.400 bad_request: check the required HTTPS link, two-letter language code and boolean options against the endpoint reference.402 insufficient_credits: top up enough for your chosen mode's preflight maximum, not just the charge you expect.502 lookup_failedor503 temporarily_unavailable: back off before retrying; followRetry-Afterwhen present. These failures cost nothing.
Keep the requestId and contact support if a request still looks wrong.