# TikTok Transcript & Video Scraper (`dz_omar/tiktok-video-downloader`) Actor

Extract spoken transcripts from TikTok videos as text, SRT or WebVTT with timestamps. Every video also returns 58 fields: upload date, views, likes, saves, hashtags, sounds, and creator follower counts. Pick a caption language, or download watermark-free MP4s. No login needed.

- **URL**: https://apify.com/dz_omar/tiktok-video-downloader.md
- **Developed by:** [FlowExtract API](https://apify.com/dz_omar) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 136 total users, 40 monthly users, 84.7% runs succeeded, 8 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.30 / 1,000 📊 video scrapeds

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

Turn any TikTok URL into structured data. Get the spoken transcript, 58 metadata fields, creator profile stats, and an optional watermark-free MP4 download. No login, no API key.

### Features

- 📝 **Transcripts** - Spoken content as plain text, timestamped segments, SRT or WebVTT
- 🌍 **Language Choice** - Pick which caption track you get when a video offers more than one
- 📊 **58 Fields Per Video** - Upload date, engagement stats, hashtags, mentions, sound details, AI-content flags
- 👥 **Creator Data** - Handle, bio, follower count, total likes, video count, verified status
- 🎬 **Watermark-Free Links** - Direct MP4 URLs at your chosen frame rate
- 💾 **Optional Download** - Store MP4s on Apify with permanent links
- 🔄 **Resumable Runs** - State persistence survives migration, timeout and abort
- 🛡️ **Block Handling** - Detects TikTok's firewall challenge and rotates proxy sessions automatically

### Input

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `videoUrls` | array | ✅ | - | TikTok video URLs. Standard, short (`vm.tiktok.com`) and mobile formats all work. |
| `includeTranscript` | boolean | ❌ | `true` | Extract the spoken transcript |
| `transcriptFormats` | array | ❌ | `["text","segments"]` | Any of `text`, `segments`, `srt`, `vtt` |
| `preferredLanguage` | string | ❌ | `"auto"` | Caption language to prefer, e.g. `eng-US`. `auto` uses the video's original language. |
| `preferredFps` | string | ❌ | `"60"` | Video frame rate: `"30"` or `"60"` |
| `downloadVideo` | boolean | ❌ | `false` | Store MP4 files on Apify |
| `proxyConfig` | object | ❌ | - | Proxy configuration. Residential is strongly recommended. |

#### Example Input

```json
{
    "videoUrls": [
        { "url": "https://www.tiktok.com/@username/video/1234567890" },
        { "url": "https://vm.tiktok.com/ABC123" }
    ],
    "includeTranscript": true,
    "transcriptFormats": ["text", "segments", "srt"],
    "preferredLanguage": "auto",
    "proxyConfig": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### How Transcripts Work

TikTok runs speech recognition on videos that contain speech and publishes the result as a caption track. This Actor reads that track directly. Nothing is re-transcribed, so the text matches what TikTok itself shows viewers, and extraction is fast and cheap.

**Transcripts are only returned when the video has one.** A video with no speech, such as music or sound effects, returns `available: false` along with TikTok's own reason. That is a normal result, not an error, and it is never charged.

In a sample of 31 public videos, 13 carried a transcript. Coverage is much higher on talking-head, news and tutorial content than on music or dance videos.

#### Choosing a language

Some videos carry more than one caption track: the original spoken language plus machine translations TikTok has already generated. Set `preferredLanguage` to pick one.

```json
{ "preferredLanguage": "eng-US" }
```

If the language you ask for is not available on a given video, you get that video's original track instead, and `transcript.language` tells you what you actually received. `transcript.availableLanguages` lists every track the video offers, and `transcript.source` is `ASR` for speech recognition or `MT` for a translation of it.

The Actor never invents a translation. It only returns tracks TikTok has already published.

### Sample Output

Each video produces one dataset record. Abbreviated below.

```json
{
    "videoId": "1234567890",
    "webVideoUrl": "https://www.tiktok.com/@username/video/1234567890",
    "directUrl": "https://v16-webapp-prime.tiktok.com/...",
    "title": "Video caption text",
    "createTime": "2026-04-02T15:22:04.000Z",
    "hashtags": ["cooking", "recipe"],
    "mentions": ["someoneelse"],

    "authorUsername": "username",
    "author": "Creator Name",
    "authorVerified": true,
    "authorFollowers": 4800000,
    "authorLikes": 120400000,
    "authorBio": "Profile bio text",

    "viewCount": 734500,
    "likeCount": 24600,
    "commentCount": 181,
    "shareCount": 411,
    "collectCount": 1573,
    "repostCount": 0,

    "duration": 8,
    "quality": "540p",
    "musicTitle": "original sound",
    "musicIsOriginal": true,

    "transcript": {
        "available": true,
        "language": "eng-US",
        "source": "ASR",
        "isAutoGenerated": true,
        "wordCount": 42,
        "segmentCount": 9,
        "availableLanguages": ["eng-US", "spa-ES"],
        "text": "Full spoken transcript as a single string",
        "segments": [
            { "start": "00:00:00.380", "end": "00:00:03.600", "startSeconds": 0.38, "endSeconds": 3.6, "text": "First line of speech" }
        ],
        "srt": "1\n00:00:00,380 --> 00:00:03,600\nFirst line of speech\n",
        "error": null
    },

    "download": {
        "available": true,
        "url": "https://api.apify.com/v2/key-value-stores/.../records/...",
        "status": "completed",
        "fileSizeHuman": "1.5 MB"
    },

    "success": true
}
```

### Dataset Views

Seven pre-configured views, switchable from the dataset tab:

| View | Shows |
|------|-------|
| Overview | Thumbnail, caption, creator, date, engagement, transcript availability |
| Transcripts | Transcript text, language, source and word count per video |
| Engagement | Views, likes, comments, shares, saves and reposts |
| Creator Data | Handle, follower count, total likes, bio, profile link |
| Sounds | Sound title, author, duration and audio link |
| Download Links | Stored file links and direct MP4 URLs |
| Failed Extractions | Error code and message for anything that did not work |

### Pricing

Pay per event. You are billed for results, not for runtime.

| Event | Charged when |
|-------|--------------|
| Run start | Once per run start, including a restart after a platform migration |
| Video scraped | A video is successfully scraped, for the full record |
| Transcript extracted | A transcript is actually returned |
| Video downloaded | An MP4 is stored, and only if you switch downloads on |

Failed videos are never charged. Videos with no speech are charged as a scrape but not as a transcript.

#### Downloads start a second Actor

If you switch `downloadVideo` on, this Actor hands the file transfer to [Universal Downloader](https://apify.com/dz_omar/universal-downloader). You will see **two Actor runs** in your account for the same job, and that second Actor bills you separately on top of the download event here.

This is why the download event is priced low. It is meant to sit alongside the other Actor's charge rather than duplicate it.

Downloads are **off by default**. If you only need transcripts and metadata, leave them off and no second Actor is ever started.

### Proxy Configuration

TikTok blocks datacenter traffic aggressively. Residential proxies are strongly recommended:

```json
{
    "proxyConfig": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
}
```

The Actor detects TikTok's firewall challenge, which arrives as a normal-looking HTTP 200 rather than an error, and retries on a fresh session automatically.

### State Persistence & Resumability

Runs are resumable. If a run is interrupted by migration, timeout or abort, the next run with the same input picks up where it stopped. State is saved every 3 videos, on migration, on abort and before exit.

### Error Handling

| Error Type | Retryable | Behavior |
|------------|-----------|----------|
| Firewall challenge | ✅ | New proxy session, then retry |
| Network timeout | ✅ | Exponential backoff |
| Rate limiting (429) | ✅ | Extended backoff |
| Server errors (5xx) | ✅ | Standard backoff |
| Video not found (404) | ❌ | Immediate fail |
| Private/restricted video | ❌ | Immediate fail |
| Invalid URL | ❌ | Immediate fail |

### Run Summary

A summary is written to the Key-Value Store under `RUN_SUMMARY`:

```json
{
    "total": 10,
    "processed": 10,
    "successful": 9,
    "failed": 1,
    "transcripts": {
        "enabled": true,
        "extracted": 6,
        "unavailable": 3,
        "coverageRate": 67
    },
    "downloads": { "enabled": true, "successful": 9, "failed": 0 },
    "resumed": false,
    "completedAt": "2026-09-11T10:35:00.000Z"
}
```

### Limitations

- Memory is capped at 512 MB. Runs use around 110 MB in practice, and the work is network-bound rather than memory-bound, so more allocation would cost you without running faster.
- Transcripts exist only where TikTok generated captions. Videos without speech return none.
- Translated tracks are returned only where TikTok already published them. The Actor does not translate.
- Direct MP4 URLs expire after a few hours. Use `downloadVideo: true` for permanent links.
- Private videos cannot be extracted, and some region-restricted videos may be unavailable.

***

### 🤝 Support & Resources

- 🌐 **Website**: [flowextractapi.com](https://flowextractapi.com)
- 📧 **Email**: <flowextractapi@outlook.com>
- 🙋 **Apify Profile**: [FlowExtract API](https://apify.com/dz_omar?fpr=smcx63)
- 💬 **GitHub Issues**: [FlowExtractAPI](https://github.com/FlowExtractAPI)

#### Social Media

- 💼 **LinkedIn**: [flowextract-api](https://www.linkedin.com/in/flowextract-api/)
- 🐦 **Twitter**: [@FlowExtractAPI](https://x.com/@FlowExtractAPI)
- 📱 **Facebook**: [flowextractapi](https://www.facebook.com/flowextractapi)

#### Related Actors

- **[Universal File Downloader](https://apify.com/dz_omar/universal-downloader?fpr=smcx63)**: Powers the intelligent download system

***

### ⚖️ Legal & Compliance

This Actor extracts publicly available data from TikTok. It does not log in, bypass authentication, or access private content. You are responsible for using the output in line with TikTok's Terms of Service, applicable copyright law, and data protection regulations such as GDPR and CCPA. Transcripts and video files remain the property of their creators.

***

*Built and maintained by FlowExtract API.*

# Changelog

This Actor's version history is a separate document: https://apify.com/dz_omar/tiktok-video-downloader/changelog.md

# Actor input Schema

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

List of TikTok video URLs to process. Supports multiple URL formats:

**Standard URLs:**

- https://www.tiktok.com/@username/video/1234567890

**Short URLs:**

- https://vm.tiktok.com/ABC123

**Mobile URLs:**

- https://m.tiktok.com/v/1234567890

## `includeTranscript` (type: `boolean`):

Extract the spoken words from each video as text.

TikTok auto-generates captions for videos containing speech, and this pulls that track directly. Videos with no speech (music, sound effects) return no transcript, which is normal.

Typical coverage is 60-70% of videos.

## `transcriptFormats` (type: `array`):

Choose which transcript formats to include in the output:

- **Plain text**: the full transcript as one string
- **Timed segments**: array of lines with start/end times
- **SRT**: subtitle file content, ready to save as .srt
- **WebVTT**: the raw caption file exactly as TikTok serves it

## `preferredLanguage` (type: `string`):

Language to prefer when a video has more than one caption track.

Leave as **Auto** to use the video's original spoken language. If the requested language is not available, the original track is returned instead.

## `preferredFps` (type: `string`):

Choose your preferred video frame rate:

- **60 FPS**: Higher quality, smoother playback
- **30 FPS**: Standard quality, smaller files

## `downloadVideo` (type: `boolean`):

Enable to download and store video files in Apify storage:

- **Disabled**: Only metadata and direct TikTok URLs
- **Enabled**: Download MP4 files with persistent links

⚠️ **This starts a second Actor.** Downloading is handled by [Universal Downloader](https://apify.com/dz_omar/universal-downloader), so you will see two Actor runs in your account. It bills separately, on top of this Actor's download event. Leave this off if you only need transcripts and metadata.

## `proxyConfig` (type: `object`):

Configure proxy settings. Residential proxies recommended for better success rates.

## Actor input object example

```json
{
  "videoUrls": [
    {
      "url": "https://www.tiktok.com/@chasseurdesons/video/7470583049239956758",
      "method": "GET"
    }
  ],
  "includeTranscript": true,
  "transcriptFormats": [
    "text",
    "segments"
  ],
  "preferredLanguage": "auto",
  "preferredFps": "60",
  "downloadVideo": false,
  "proxyConfig": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `videos` (type: `string`):

No description

# 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": [
        {
            "url": "https://www.tiktok.com/@chasseurdesons/video/7470583049239956758",
            "method": "GET"
        }
    ],
    "proxyConfig": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dz_omar/tiktok-video-downloader").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": [{
            "url": "https://www.tiktok.com/@chasseurdesons/video/7470583049239956758",
            "method": "GET",
        }],
    "proxyConfig": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("dz_omar/tiktok-video-downloader").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": [
    {
      "url": "https://www.tiktok.com/@chasseurdesons/video/7470583049239956758",
      "method": "GET"
    }
  ],
  "proxyConfig": {
    "useApifyProxy": false
  }
}' |
apify call dz_omar/tiktok-video-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dz_omar/tiktok-video-downloader"
        }
    }
}
```

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/hHOebBYQcDKgqzyI2/builds/DFxN7xWhfxd1Aseso/openapi.json
