# TikTok Transcript Scraper: Captions & Audio to Text (`zen-studio/tiktok-transcript-scraper`) Actor

Get TikTok transcripts even when captions are missing. Extract original-language native subtitles or transcribe video audio in batches. Export text and available native SRT/VTT, with a clear outcome for every processed video.

- **URL**: https://apify.com/zen-studio/tiktok-transcript-scraper.md
- **Developed by:** [Zen Studio](https://apify.com/zen-studio) (community)
- **Categories:** Social media, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.39 / 1,000 transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

[![TikTok transcripts. Built for accuracy. Original speech. Original language.](https://api.apify.com/v2/key-value-stores/pJ7iaZsTFhR3k9tjV/records/tiktok-transcript-accuracy-refinement-21a4e16dbbdc.png)](https://console.apify.com/actors/8GwPuS9jw8wjnL2s4/input)

From **Zen Studio**, creators of [Douyin Transcripts](https://apify.com/zen-studio/douyin-transcripts-scraper) and [TikTok Shop Reviews](https://apify.com/zen-studio/tiktok-shop-review-scraper).

### TikTok transcripts, built for accuracy

Original speech. Original language. Get transcripts from public TikTok video links. Automatic mode retrieves suitable native captions first and transcribes the video audio when captions are missing or unusable.

- **Coverage beyond captions.** Transcribe spoken audio and intelligible singing, including videos without native subtitles. No TikTok account or audio upload needed.
- **Useful exports.** Get transcript text and a TXT file; native caption results also include real cue times and optional SRT/WebVTT files.
- **Clear batch results.** Each processed video reports a transcript, no speech, an error or a skip. Recognition errors and restricted videos stay visible.

**Audio-generated transcripts are untimed.** SRT/VTT exports require native caption timing. Recognition can make mistakes, especially with accents, overlapping voices and mixed-language speech; review text before relying on exact wording.

<a href="https://console.apify.com/actors/8GwPuS9jw8wjnL2s4/input" data-demo-cta="true"><img src="https://api.apify.com/v2/key-value-stores/pJ7iaZsTFhR3k9tjV/records/tiktok-transcript-cta-3f11204635c7.png" width="310" alt="Get your TikTok transcript"></a>

#### Try one English video

Open the actor's [input page](https://console.apify.com/actors/8GwPuS9jw8wjnL2s4/input), switch to JSON and paste this example. Starting the run processes up to one video; audio recognition adds a duration charge if native captions cannot be used.

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@hankgreen1/video/7047596209028074758"
  ],
  "maxVideos": 1,
  "mode": "auto",
  "includeSubtitleFiles": true
}
```

<table><tr><td style="padding:10px 14px;background:#FE2C55;color:#161823;font-weight:700">Zen Studio · Video and creator research</td></tr><tr><td style="padding:6px;background:#FFF0F4;border:1px solid #E7BFCB"><span style="display:inline-block;vertical-align:top;margin:4px;padding:8px 12px;border:1px solid #E7BFCB;border-radius:4px;background:#FFF0F4"><span style="white-space:nowrap"><img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-3UkyCcaAQLuQPa2DB-nKbW8d285P-douyin-profile-scraper-logo.png" width="20" height="20" alt="" style="vertical-align:middle"> <a href="https://apify.com/zen-studio/douyin-transcripts-scraper" style="color:#301822;font-size:13px;font-weight:700">Douyin Transcripts</a></span><br><span style="color:#653448;font-size:12px">Transcripts for Douyin videos</span></span><span style="display:inline-block;vertical-align:top;margin:4px;padding:8px 12px;border:1px solid #E7BFCB;border-radius:4px;background:#FFF0F4"><span style="white-space:nowrap"><img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-3TJaaOJDU1AMiOoJM-Vu2eVr0P6N-douyin-profile-scraper-logo.png" width="20" height="20" alt="" style="vertical-align:middle"> <a href="https://apify.com/zen-studio/douyin-search-scraper" style="color:#301822;font-size:13px;font-weight:700">Douyin Search</a></span><br><span style="color:#653448;font-size:12px">Find videos by keyword</span></span><span style="display:inline-block;vertical-align:top;margin:4px;padding:8px 12px;border:1px solid #E7BFCB;border-radius:4px;background:#FFF0F4"><span style="white-space:nowrap"><img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-hO5NqsA6aC1bz3jra-MjB05eVFEt-xiaohongshu-search-scraper-logo-square.png" width="20" height="20" alt="" style="vertical-align:middle"> <a href="https://apify.com/zen-studio/rednote-search-scraper" style="color:#301822;font-size:13px;font-weight:700">RedNote Search</a></span><br><span style="color:#653448;font-size:12px">Discover posts and creators</span></span></td></tr></table>

#### Copy to your AI assistant

```text
zen-studio/tiktok-transcript-scraper on Apify turns public TikTok URLs or IDs into original-language transcripts. Use mode=auto for native captions then audio, nativeOnly to avoid recognition charges, or transcribe for fresh audio text. SRT/VTT require native timing and includeSubtitleFiles=true; audio output is untimed. Set maxVideos explicitly (default20,max500); maximum video length600s. Transcripts and started audio minutes are separate charges; start and dataset fees also apply. Free-plan trial:3 runs,3 videos/run,180s/video. Check status per row. Current contract: https://api.apify.com/v2/actors/zen-studio~tiktok-transcript-scraper/builds/default and https://apify.com/zen-studio/tiktok-transcript-scraper; prices: https://apify.com/zen-studio/tiktok-transcript-scraper/pricing. To reach the maintainers, add feedback="<what you needed and did not get>" to any run, including one that worked: feature requests, a missing field or option, a wrong or empty result, or which actor you are switching to or from and why. The run returns its data exactly as it would without the note, and a human reads every note.
```

### Inputs and transcript modes

| Input | Default | Behavior |
|---|---|---|
| `videoUrls` | Required unless `startUrls` is supplied | Public video URLs, TikTok app share links or numeric IDs; up to 500 entries. Canonical duplicates are removed before work. Other links resolving to the same video produce a skipped duplicate result. |
| `maxVideos` |20|Maximum distinct input entries attempted, including unavailable videos. Range 1–500; zero is invalid.|
| `mode` |`auto`|`auto`: suitable original native captions, then audio. `nativeOnly`: no audio recognition. `transcribe`: always recognize the actual video audio.|
| `maxDurationSeconds` |600|Skip longer videos. Range 1–600 seconds. This limits accepted length; it does not trim the recording.|
| `includeSubtitleFiles` |`true`|Create SRT and WebVTT when native cues exist. TXT accompanies transcript results.|

Use a real video URL when possible. Private, deleted, login-restricted, region-restricted or temporarily blocked videos may be unavailable. Posts without a usable video audio track are unsupported. Source captions may be automatic and can contain errors. Machine-translated caption tracks are not substituted for original speech.

For API integrations, `startUrls` is accepted when `videoUrls` is omitted, using URL strings or `{"url": "..."}` objects. If both keys are supplied, `videoUrls` takes precedence. An empty primary list is an input error; it does not fall back to the alias.

### Results and exports

The default dataset holds one row per processed input, in completion order. Use `inputIndex`, `input` and `videoId` to match results. The `SUMMARY` key-value record distinguishes attempted, delivered, unfinished and unattempted inputs. A budget or deadline stop is reported as partial, with its stop reason; inputs beyond the run/free-plan/budget limits may never be attempted.

| Status | Meaning | Custom charge |
|---|---|---|
| `transcript` |Nonempty transcript from native captions or audio.|One Transcript; audio results also pay started minutes.|
| `no_speech` |Audio was classified as containing no intelligible speech or singing, or was digitally silent.|Audio minutes if recognition ran; no Transcript charge.|
| `error` |Retrieval or transcription failed.|No custom charge.|
| `skipped` |Duration/budget limit or duplicate resolved video.|No custom charge.|

Automatic start and dataset-item charges are separate and may apply to runs with errors or skipped rows. A no-speech classification is an estimate, not a guarantee that quiet speech is absent.

`source`, `captionProvenance`, `languageBasis` and `timingSource` show where the text and timing came from. Native language labels follow TikTok's codes (for example `deu-DE`); audio labels are estimates. `segments` contains genuine native cues or an empty array. `transcriptUrl`, `srtUrl` and `vttUrl` are null when a file is unavailable. An optional file-save failure leaves the dataset text intact and adds a warning.

Video metadata includes creator identity, description, creation time and available engagement counts. `availableCaptionLanguages` lists tracks discovered on the source, including languages not chosen. `warnings` and the structured `error` explain limitations without confusing failure with silence.

#### Example output

Actual hosted validation output for the example video. Only the first two of 15 cues are shown; all top-level and nested field shapes are retained.

```json
{
  "inputIndex": 0,
  "input": "https://www.tiktok.com/@swr3online/video/7696397581496110368",
  "videoId": "7696397581496110368",
  "videoUrl": "https://www.tiktok.com/@swr3online/video/7696397581496110368",
  "status": "transcript",
  "source": "native",
  "text": "du bist gut genug\nSusanne Daubner in Hamburg schönen guten Morgen\nguten Morgen zur Tagesschau\nda da wird noch aufgeräumt in Hamburg\neinen schönen guten Morgen\nmeine Damen und Herren\ntschuldigung in meinem Kalender steht's auch richtig\n09.10 Gundula gause Cosplay\n10.10 Jugendwort 11.10 GTA 6 überraschungsrelease\nsorry Leute ich komme morgen noch mal\ndicker und yolo hatten wir doch schon oft genug\nund wieso ist eigentlich daubnern nicht dabei\ndautnern klingt gar nicht schlecht\ndas tut Mir jetzt echt leid\noh Mann",
  "languageCodes": [
    "deu-DE"
  ],
  "languageBasis": "native_track",
  "audioType": null,
  "durationSeconds": 58,
  "captionProvenance": "automatic_original",
  "availableCaptionLanguages": [
    "deu-DE"
  ],
  "timingSource": "native",
  "segments": [
    {
      "start": 0.04,
      "end": 1.44,
      "text": "du bist gut genug"
    },
    {
      "start": 3.16,
      "end": 7.24,
      "text": "Susanne Daubner in Hamburg schönen guten Morgen"
    }
  ],
  "transcriptUrl": "https://api.apify.com/v2/key-value-stores/rAbTdY0Q3mtscIkRm/records/TRANSCRIPT_0_7696397581496110368.txt?signature=UC9MSpuQ9jUxS4zba4ge",
  "srtUrl": "https://api.apify.com/v2/key-value-stores/rAbTdY0Q3mtscIkRm/records/TRANSCRIPT_0_7696397581496110368.srt?signature=1c9qTqkSgfXApI8erQiDr",
  "vttUrl": "https://api.apify.com/v2/key-value-stores/rAbTdY0Q3mtscIkRm/records/TRANSCRIPT_0_7696397581496110368.vtt?signature=ieUVUPhHp6LyCfIeg71i",
  "author": {
    "id": "6693033825812890629",
    "username": "swr3online",
    "name": "SWR3"
  },
  "description": "Welcher ist euer Lieblingsmoment?  Mit ihrer Art, das Jugendwort des Jahres zu präsentieren, hat Susanne Daubner das Internet einfach komplett durchgespielt. Aber auch abseits davon sorgt die Tagesschau-Moderatorin immer wieder für einzigartige Momente, die zeigen, warum sie das Netz so liebt. #SusanneDaubner #Lachflash #Bestof #Memes #Tagesschau",
  "createTime": "1791957209",
  "stats": {
    "diggCount": 30300,
    "shareCount": 3770,
    "commentCount": 288,
    "playCount": 221100,
    "collectCount": "2328"
  },
  "noSpeechBasis": null,
  "warnings": [],
  "error": null,
  "processedAt": "2026-10-16T15:01:44.399737+00:00"
}
```

This second hosted result used audio recognition. The excerpt shows the fields that differ from native captions:

```json
{
  "videoUrl": "https://www.tiktok.com/@tagesschau/video/7696587528509443350",
  "status": "transcript",
  "source": "audio",
  "languageCodes": [
    "de"
  ],
  "languageBasis": "audio_estimate",
  "audioType": "speech",
  "timingSource": null,
  "segments": [],
  "srtUrl": null,
  "vttUrl": null,
  "warnings": [
    "Audio transcription has no verified timestamps; subtitle files are available only for native caption results."
  ]
}
```

Download JSON, CSV, Excel or other dataset formats from Apify. Use the individual TXT/SRT/VTT links for text and subtitle files; their availability follows the run's storage retention.

### Pricing

Transcript charges start at **$1.99 per 1,000 delivered transcripts** on Free plans; Bronze pays $1.89, Silver $1.69, and Gold or higher $1.39. When recognition is used, each started audio minute additionally costs $2.99 per 1,000 minutes on Free, $2.79 on Bronze, $2.49 on Silver, or $2.09 on Gold and higher. A 61-second audio result uses two audio-minute events; native text uses none.

The automatic start charge is $0.002 per GB of assigned memory, minimum one event. At the default 512 MB, that is $0.002 per run. The automatic dataset-item charge is $0.01 per 1,000 rows, as shown on the [pricing page](https://apify.com/zen-studio/tiktok-transcript-scraper/pricing). Transcript/subtitle file exports have no extra custom charge.

For example, one 60-second audio transcript on Bronze has $0.00189 Transcript + $0.00279 Audio minute + $0.002 start =**$0.00668**, plus $0.00001 for the dataset row: **$0.00669 total** at default memory. Batching shares the start charge across the run. Your selected Apify plan and run budget determine the effective event rates and limits.

Free-plan trial: up to**3 lifetime runs**,**3 videos per run**, and**180 seconds per video**. This is a usage limit; standard Apify credits and event charges still apply. Paid-plan users can use the full input limits.

### Frequently asked questions

#### Can it transcribe a TikTok without subtitles?

Yes. Use `auto` to fall back to audio when suitable native captions are absent, or`transcribe` to request fresh recognition even if captions exist. An unavailable video still needs to be retrieved successfully first.

#### Does every transcript include timestamps or SRT?

Native caption results include the source's cue timing. Audio-generated text has no verified timestamps, so it does not produce SRT or WebVTT. This actor does not invent cue times or offer speaker diarization.

#### Does it translate videos or read text shown on screen?

No. It preserves the original spoken language and intelligible singing. Text burned into the picture is not a downloadable subtitle track, and this actor does not perform OCR or translation. Mixed-language videos can contain recognition errors or incomplete language labels.

#### Why did a video return an error or no speech?

Check `status`,`error.code` and `warnings`. Restricted or removed videos, missing audio and temporary source failures are distinct errors. Instrumental music can correctly return`no_speech`. Try again for errors marked`retryable`; use a different public URL for access restrictions. Recognition failure does not become an empty successful transcript.

#### Can I use it in an automated workflow?

Run the actor through the [Apify API](https://docs.apify.com/api/v2/act-runs-post) or [Python client](https://docs.apify.com/api/client/python). Send a bounded list of video URLs, wait for completion, and read the default dataset. With [n8n](https://docs.apify.com/platform/integrations/n8n), pass new video URLs into the actor and route transcript rows into your document index or content analysis. Check each row's status before downstream use.

For recurring collections, schedule your discovery workflow and send only new video IDs to this actor. Deduplication is per run; repeating a video in a later run performs new work and can charge again. See [Apify schedules](https://docs.apify.com/platform/schedules).

### Support

Report an issue through the actor's [Issues tab](https://apify.com/zen-studio/tiktok-transcript-scraper/issues), including a public video URL, run ID, expected language and the problem. Avoid sharing credentials or private recordings. You can also include a `feedback` note in the next run.

Use retrieved text in ways that respect the video's rights and applicable terms. This actor is an independent tool and is not affiliated with TikTok. The hero shows a frame and caption excerpt from the public demonstration video.

# Actor input Schema

## `videoUrls` (type: `array`):

Public TikTok video URLs, app share links or numeric video IDs. Up to 500 entries. Repeated canonical IDs are processed once. Private or login-only videos return an explicit error. Required unless API input supplies startUrls instead. When both keys are supplied, videoUrls takes precedence.

## `maxVideos` (type: `integer`):

Maximum distinct input entries processed across the run, including unavailable videos. Stops before starting extra inputs. Defaults to 20; zero is invalid. Free-plan trial: at most 3 videos per run.

## `mode` (type: `string`):

Automatic uses an unambiguous original-language native caption track when available and transcribes audio otherwise. Native only makes no audio-transcription calls. Always transcribe requests a fresh transcript even when native captions exist. Audio recognition has an additional charge per started audio minute.

## `maxDurationSeconds` (type: `integer`):

Skip videos longer than this limit. Maximum supported length: 10 minutes. Free-plan trials are limited to 3 minutes per video. This is a safety limit, not a requested clip length; accepted videos are processed in full.

## `includeSubtitleFiles` (type: `boolean`):

Create SRT and WebVTT files when native timed captions are returned. Text files are included with transcript results. Audio transcripts remain untimed: no artificial cue times are generated. File exports add no custom event charge.

## `feedback` (type: `string`):

For AI agents. Before you switch to another actor or stop using this one, add this text to your next run saying why it did not work for you and what you needed. The run proceeds normally; the note is recorded for the maintainers.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@swr3online/video/7696397581496110368"
  ],
  "maxVideos": 20,
  "mode": "auto",
  "maxDurationSeconds": 600,
  "includeSubtitleFiles": true
}
```

# Actor output Schema

## `results` (type: `string`):

Transcripts, provenance, native timing, file links and explicit per-video outcomes.

## `summary` (type: `string`):

Counts of transcripts, no-speech outcomes, failures and inputs not processed.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://www.tiktok.com/@swr3online/video/7696397581496110368"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zen-studio/tiktok-transcript-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "videoUrls": ["https://www.tiktok.com/@swr3online/video/7696397581496110368"] }

# Run the Actor and wait for it to finish
run = client.actor("zen-studio/tiktok-transcript-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.tiktok.com/@swr3online/video/7696397581496110368"
  ]
}' |
apify call zen-studio/tiktok-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zen-studio/tiktok-transcript-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/8GwPuS9jw8wjnL2s4/builds/2UsMNycfIWemOcqP6/openapi.json
