# TikTok Transcript & Subtitle Scraper (`autofacts/tiktok-subtitle-transcript-scraper`) Actor

Extract TikTok subtitles & transcripts instantly from native captions — no Whisper, no API key. Get timestamped JSON, SRT, VTT, plain text, or LLM-ready output. Supports video URLs, short links, and @profile batch scraping. Rich metadata included. Pay only for successful extractions.

- **URL**: https://apify.com/autofacts/tiktok-subtitle-transcript-scraper.md
- **Developed by:** [Richard Feng](https://apify.com/autofacts) (community)
- **Categories:** AI, Videos, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 transcript extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Subtitle & Transcript Scraper

Extract subtitles and transcripts from any public TikTok video — instantly, accurately, at scale. No API key, no Whisper, no speech-to-text. Just the exact captions TikTok already generated, delivered in the format you need.

### 💡 Why this Actor?

Most TikTok transcript tools on Apify use **Whisper AI** to re-transcribe audio. That's slow, expensive, and can hallucinate words that were never said.

This Actor takes a different approach: it extracts TikTok's **native captions** directly from their CDN. The same subtitles viewers see on-screen, pulled in milliseconds instead of minutes.

| | This Actor | Whisper-based actors |
|---|---|---|
| Speed | ~2s per video | 10–30s per video |
| Accuracy | Exact (TikTok's own captions) | ~95% (AI can mishear) |
| Cost | Pay per result only | Pay per result + Whisper API |
| Languages | All that TikTok provides | Depends on model |

### 🚀 Quick start

Paste one or more TikTok URLs and hit **Start**:

```json
{
    "urls": [
        "https://www.tiktok.com/@tiktok/video/7627209981670001950"
    ]
}
```

That's it. You'll get the full transcript with timestamps, metadata, and engagement stats.

### 📋 What you can pass as input

The `urls` field accepts any mix of:

```
https://www.tiktok.com/@username/video/7123456789012345678   (video URL)
https://vm.tiktok.com/ZMrAbCdEf                             (short link)
https://vt.tiktok.com/ZSrXyZ123                             (short link)
https://www.tiktok.com/t/ZTRaBcDeF                           (short link)
https://www.tiktok.com/@username                             (all videos from profile)
@username                                                    (profile shorthand)
7123456789012345678                                          (raw video ID)
```

When you pass a profile URL or `@username`, the Actor enumerates that user's videos and extracts subtitles from each one. Use `maxVideos` to limit how many.

### 📋 Input reference

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `urls` | string\[] | *required* | TikTok URLs, short links, `@username` handles, or raw video IDs |
| `outputFormat` | select | `json` | `json` `srt` `vtt` `text` `llm` |
| `languages` | string\[] | `["eng"]` | Preferred languages in priority order. Prefix matching supported — `eng` matches `eng-US` |
| `includeAutoGenerated` | boolean | `true` | Include TikTok's auto-generated captions |
| `maxVideos` | integer | `0` | Max videos to process **in total across all inputs**. `0` = unlimited. Videos you name explicitly are taken first, then profiles fill whatever budget is left |
| `maxConcurrency` | integer | `3` | Parallel workers (1–10). Lower = safer from rate limits |
| `proxyConfiguration` | object | Apify residential | Proxy to route requests through. Residential is strongly recommended; you can also supply your own `proxyUrls`, or disable the proxy for local testing |

### 📤 Example output

Real output from `@tiktok/video/7627209981670001950`:

```json
{
    "videoId": "7627209981670001950",
    "url": "https://www.tiktok.com/@tiktok/video/7627209981670001950",
    "title": "your TikTok grandpa @writers cramp is proud of you",
    "authorName": "TikTok",
    "authorId": "tiktok",
    "description": "your TikTok grandpa @writers cramp is proud of you",
    "createTime": "2026-04-10T19:10:35.000Z",
    "playCount": 54600,
    "likeCount": 3656,
    "commentCount": 837,
    "shareCount": 291,
    "thumbnail": "https://p16-common-sign.tiktokcdn-us.com/...",
    "availableLanguages": ["eng-US"],
    "language": "eng-US",
    "isAutoGenerated": true,
    "segments": [
        { "text": "I'm 81 years old and I'm known as the TikTok Grandpa", "start": 0.04, "end": 3.64 },
        { "text": "my name is Ian Smith", "start": 3.641, "end": 4.721 },
        { "text": "and I make positive thinking and motivational videos as writers cramp", "start": 4.722, "end": 9.001 }
    ],
    "text": "I'm 81 years old and I'm known as the TikTok Grandpa my name is Ian Smith and I make positive thinking and motivational videos...",
    "duration": 77,
    "wordCount": 243,
    "segmentCount": 29,
    "extractedAt": "2026-04-12T02:45:36.000Z",
    "error": null
}
```

The `segments` array (with `start`/`end` timestamps in seconds) is included when `outputFormat` is `json`. Other formats populate the `text` field and optionally `srt` or `vtt`.

### 📤 Output formats

| Format | What you get | Best for |
|--------|-------------|----------|
| **json** | `text` + `segments[]` with timestamps | RAG pipelines, structured data, analytics |
| **srt** | `text` + `srt` (SubRip subtitle file) | Video editing, subtitle files |
| **vtt** | `text` + `vtt` (WebVTT subtitle file) | Web players, accessibility |
| **text** | `text` only (plain transcript) | Search indexing, simple analysis |
| **llm** | `text` cleaned of `[Music]`, speaker labels, annotations | AI training, summarization, content repurposing |

### 🗂️ Output fields

Every result includes full video metadata alongside the transcript:

| Field | Description |
|-------|-------------|
| `videoId` | TikTok video ID |
| `url` | Canonical video URL |
| `title` / `description` | Video caption text |
| `authorName` / `authorId` | Creator display name and handle |
| `createTime` | ISO 8601 publish timestamp |
| `playCount` / `likeCount` / `commentCount` / `shareCount` | Engagement metrics |
| `thumbnail` | Cover image URL |
| `availableLanguages` | All subtitle languages found on this video |
| `language` | Language code of the extracted transcript, e.g. `eng-US` |
| `languageName` | Human-readable language, e.g. `English (United States)` |
| `isAutoGenerated` | `true` if captions are auto-generated, `false` if creator-uploaded |
| `segments` | Array of `{ text, start, end }` (JSON format only) |
| `text` | Full transcript as a single string |
| `srt` / `vtt` | Subtitle file content (only when that format is selected) |
| `duration` | Video length in seconds |
| `wordCount` / `segmentCount` | Transcript statistics |
| `extractedAt` | When the extraction happened |
| `error` | `null` on success. Inputs that fail still produce a row, with `error` set and the other fields empty — so every input is accounted for in the dataset |

### 🎯 Profile scraping

Pass `@username` or a profile URL to extract subtitles from multiple videos:

```json
{
    "urls": ["@tiktok"],
    "maxVideos": 10,
    "outputFormat": "llm"
}
```

The Actor fetches the profile, enumerates videos via TikTok's creator API, then processes each video's subtitles individually. Pagination is handled automatically — set `maxVideos` to control how many.

### 💳 Pricing

**Pay-Per-Event** — you're charged a fixed amount per successfully extracted transcript. You are **never** charged for:

- Failed extractions (video has no captions, network error, etc.)
- URL resolution (short links, profile enumeration)
- Videos that are private, deleted, or region-locked

If you set a maximum total charge on the run, the Actor stops as soon as the platform
reports that budget is reached, rather than continuing to extract unpaid.

### ⚙️ Proxy

TikTok blocks datacenter IPs aggressively. **Residential proxies are strongly recommended** for reliable operation on Apify. The Actor defaults to Apify's residential proxy group and rotates the proxy session on every video.

You can change this with the `proxyConfiguration` input — pick a different Apify proxy group, supply your own `proxyUrls`, or turn the proxy off entirely for small local batches.

### ⚠️ Limitations

- **Public videos only** — private or restricted content is not accessible
- **Existing captions only** — this Actor extracts captions that TikTok already has. Videos without any subtitles (no auto-generated or creator-uploaded captions) will return an error. For those, you need a Whisper-based transcription tool
- **Auto-caption availability** — TikTok doesn't generate captions for every video. Very short clips, music-only content, or videos in unsupported languages may not have captions
- **Thumbnail URLs expire** — TikTok serves cover images from a signed CDN, and the `thumbnail` link stops working within hours. Download the image if you need to keep it
- **Rate limits** — TikTok rate-limits requests per IP. The Actor handles this with proxy session rotation and configurable concurrency, but very large batches may need lower concurrency settings

### 💡 Use cases

- **RAG pipelines** — feed TikTok transcripts into vector databases for retrieval-augmented generation
- **Content repurposing** — convert viral TikToks into blog posts, newsletters, or threads
- **Competitive analysis** — extract and analyze competitor content at scale
- **Trend research** — analyze language, topics, and messaging across thousands of videos
- **Accessibility** — generate subtitle files (SRT/VTT) for reposting on other platforms
- **Training data** — build multilingual datasets from TikTok's auto-generated captions
- **SEO** — make TikTok video content searchable and indexable

***

### 🤖 Use with AI agents

This Actor is callable as a tool by any MCP-capable agent — Claude, Cursor, VS Code — or by your
own code, with no wrapper and nothing extra to deploy.

**Connect over MCP**

```
https://mcp.apify.com?tools=autofacts/tiktok-subtitle-transcript-scraper
```

In a client that reads an `mcpServers` configuration block:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=autofacts/tiktok-subtitle-transcript-scraper",
      "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
    }
  }
}
```

The agent reads this Actor's parameters and their descriptions straight from the input
schema, and the hosted server infers the result field types from the dataset schema — so a
model knows what to send and what comes back before it ever calls anything.

**Or call the API directly**

```bash
curl -X POST "https://api.apify.com/v2/acts/autofacts~tiktok-subtitle-transcript-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"urls": ["https://www.tiktok.com/@tiktok/video/7627209981670001950"], "languages": ["eng"]}'
```

The response body is the dataset records described above.

### 🧰 Other Actors by autofacts

Apify only auto-recommends Actors in the same category, so here are the ones that actually pair with this scraper:

| Actor | What it's for |
| :--- | :--- |
| [YouTube Subtitle & Transcript Scraper](https://apify.com/autofacts/youtube-subtitle-transcript-scraper) | Video captions as clean text |
| [Bluesky Scraper](https://apify.com/autofacts/bluesky-scraper) | Posts, profiles, feeds and interactions |
| [Schema Markup Scraper & SEO Auditor](https://apify.com/autofacts/metadata-scraper) | JSON-LD, Open Graph and a 0-100 SEO audit of any URL |
| [Universal Web Printer](https://apify.com/autofacts/universal-web-printer) | Turn any URL or HTML into PDF, PNG, JPEG or WebP |

All of them: [apify.com/autofacts](https://apify.com/autofacts)

# Actor input Schema

## `urls` (type: `array`):

TikTok video URLs, short links, profile handles (@username), or raw video IDs.

## `outputFormat` (type: `string`):

Format for the transcript output.

## `languages` (type: `array`):

Preferred subtitle languages in order of priority (e.g. 'eng', 'jpn', 'zho'). TikTok uses language codes like 'eng-US', 'jpn-JP'. Prefix matching is supported. Leave empty for any available language.

## `includeAutoGenerated` (type: `boolean`):

Whether to include TikTok's auto-generated captions if manually-created ones are not available.

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

Maximum number of videos to process (useful for limiting profile scrapes). 0 = unlimited.

## `maxConcurrency` (type: `integer`):

Maximum number of videos to process in parallel. Higher values are faster but increase rate-limit risk.

## `proxyConfiguration` (type: `object`):

TikTok blocks datacenter IPs aggressively, so residential proxies are strongly recommended. A fresh proxy session is used for every video. You can also supply your own proxy URLs instead, or turn the proxy off for local testing.

## Actor input object example

```json
{
  "urls": [
    "https://www.tiktok.com/@tiktok/video/7627209981670001950"
  ],
  "outputFormat": "json",
  "languages": [
    "eng"
  ],
  "includeAutoGenerated": true,
  "maxVideos": 0,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset containing extracted transcripts with timestamps, metadata, and formatted text for each video.

# 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 = {
    "urls": [
        "https://www.tiktok.com/@tiktok/video/7627209981670001950"
    ],
    "languages": [
        "eng"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("autofacts/tiktok-subtitle-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 = {
    "urls": ["https://www.tiktok.com/@tiktok/video/7627209981670001950"],
    "languages": ["eng"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("autofacts/tiktok-subtitle-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 '{
  "urls": [
    "https://www.tiktok.com/@tiktok/video/7627209981670001950"
  ],
  "languages": [
    "eng"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call autofacts/tiktok-subtitle-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,autofacts/tiktok-subtitle-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/QTf4IwuUiR9pZeI3W/builds/rFxhcoMAfgh3dVkLY/openapi.json
