# TikTok Transcript & Video Metadata Scraper API (`lance_api/tiktok-transcript-scraper`) Actor

Extract existing TikTok transcripts, captions, WebVTT subtitles, timestamps, and structured metadata from public TikTok videos. Supports single URLs, bulk processing, and AI workflows.

- **URL**: https://apify.com/lance\_api/tiktok-transcript-scraper.md
- **Developed by:** [LanceAPI](https://apify.com/lance_api) (community)
- **Categories:** AI, Agents, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 🎬 TikTok Transcript & Video Metadata Scraper API

**Extract existing TikTok video transcripts as clean text, timestamped WebVTT subtitles, structured segments, and API-ready metadata.**

Submit one or more TikTok video URLs in a single `tiktokUrls` list. The Actor returns **plain transcript text for AI workflows**, **caption-level timestamps for programmatic processing**, and useful video, creator, engagement, music, and language metadata in a consistent dataset.

Built for **content research, script analysis, knowledge bases, searchable archives, AI pipelines, and API automation**—without downloading videos or running speech recognition.

- **Three transcript formats:** plain text, WebVTT, and structured timed segments
- **Transparent two-part pricing:** one video-result fee, plus a transcript fee only when transcript text is returned
- **Existing TikTok captions only:** no ASR, speech recognition, or AI-generated replacement text
- **Bulk-ready:** process up to 1,000 unique TikTok URLs with isolated per-URL statuses
- **Developer-friendly:** predictable JSON, complete field documentation, and API examples

> This Actor extracts captions already exposed for the video. If TikTok provides no caption, the result is `no_transcript`; the Actor does not generate one from audio.

### ⭐ Key features

#### Get transcript text ready for downstream use

Use `transcriptText` directly in your own summarization, search, classification, retrieval, or knowledge-base workflow without parsing subtitle syntax first.

#### Keep the original caption timeline

Receive both normalized `transcriptVtt` and `transcriptSegments`. Every segment contains `start`, `end`, and `text`, making it practical to build timestamp links, subtitle tools, and scene-level analysis.

#### Avoid unexpected ASR and AI processing

The Actor retrieves existing caption data only. It does not download video, extract audio, run speech recognition, infer speakers, translate content, or create text for videos without captions.

#### Combine transcripts with TikTok metadata

Enrich each successful result with the video description, creator identity, views, likes, comments, shares, bookmarks, hashtags, cover image, duration, dimensions, music, region, and processing time when available.

#### Process bulk inputs without batch-wide failures

Each URL is handled independently. An invalid, private, deleted, captionless, or temporarily unavailable video does not prevent other URLs from producing results.

#### Choose a preferred available caption language

`preferredLanguage` defaults to English (`en`). Set it to another language code such as `es` or `zh-Hans` when you prefer that existing TikTok caption. If the requested language is unavailable, the Actor falls back to English, then the original or another available caption. This option selects existing captions; it does not translate text.

### 🚀 Quick input example

In Apify Console, open the Actor's **Input** tab, paste a public TikTok video URL, and click **Start**:

```json
{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"
  ]
}
```

When the run finishes, open the **Dataset** or **Output** tab to view `transcriptText`, `transcriptVtt`, `transcriptSegments`, and the associated metadata.

### Short output example

```json
{
  "status": "success",
  "videoId": "7654471521490062605",
  "tiktokUrl": "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605",
  "transcriptText": "Here are three ways to improve your next video...",
  "transcriptSegments": [
    {
      "start": 0.46,
      "end": 3.2,
      "text": "Here are three ways to improve your next video"
    }
  ],
  "language": "en",
  "authorUsername": "samuelszuchan",
  "viewsCount": 125000,
  "processedAt": "2026-08-02T06:30:00.000Z"
}
```

A complete result with all currently supported transcript and metadata fields appears in [Complete output example](#complete-output-example).

### 🤖 Use with AI agents

#### What is AI Agent support?

AI Agent support lets ChatGPT, Claude, Cursor, Codex, and similar AI clients run this Actor for you. Instead of writing an API request yourself, you can describe what you want in normal language. Your AI Agent sends the TikTok URLs to the Actor, waits for the results, and then summarizes, compares, filters, or formats the returned transcripts and metadata.

#### Before you start

You need:

- An Apify account
- An Apify API token
- An AI client that supports MCP connections

| AI client | Supported |
| --- | :---: |
| ChatGPT | ✅ |
| Claude | ✅ |
| Cursor | ✅ |
| Codex | ✅ |

Keep your Apify API token private. Store it only in your AI client's secure connection settings—never paste it into a chat prompt or publish it in source code.

#### Connect your AI client

This Actor works with any AI client compatible with the Apify MCP Server. Connect your client using your own Apify account and API token, then make this Actor available to the Agent. Connection methods can differ between ChatGPT, Claude, Cursor, Codex, and other clients, so follow your client's current instructions or the [official Apify MCP Server documentation](https://docs.apify.com/integrations/mcp).

After connecting, use the prompt below or ask the Agent in your own words to process one or more public TikTok video URLs.

#### Copyable Agent prompt

```text
Use the Apify Actor `lance_api/tiktok-transcript-scraper` to retrieve existing
TikTok captions and video metadata.

Ask me which public TikTok video URLs to process. Put every URL in the
`tiktokUrls` array. The caption language defaults to English. Set
`preferredLanguage` only when I request another language; if it is unavailable,
expect English as the fallback. Do not describe this selection as translation.

For each result, report the status, canonical TikTok URL, transcript text,
caption language, creator, views, likes, comments, shares, hashtags, duration,
and publication time. If the status is `no_transcript`, explain that TikTok did
not expose a caption. Do not claim that the Actor performs ASR, speaker
diarization, word-level timing, translation, or comment extraction.

Things you should NEVER do:
- Never claim captions were generated with AI.
- Never describe preferredLanguage as translation.
- Never retry invalid URLs indefinitely.
- Never omit URLs whose status is no_transcript.
- Never claim that speaker diarization, ASR, or word-level timing exists.
- Never expose or repeat an Apify API token.

Start with this input:
{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"
  ]
}
```

#### Example conversations

These are normal chat requests—not API calls.

##### Example 1 — Summarize TikTok videos

```text
Use the TikTok Transcript & Video Metadata Scraper Actor to process these
TikTok URLs. Summarize each available transcript in five bullet points and
keep every URL in the final answer.
```

##### Example 2 — Compare opening hooks

```text
Extract the available transcripts from these TikTok videos. Compare the first
five seconds of each video, explain the hook style, and include views, likes,
comments, and shares beside each comparison.
```

##### Example 3 — Export a transcript table

```text
Process this list of TikTok URLs and return a table with URL, creator,
language, transcript, views, likes, hashtags, duration, and status. Keep rows
for videos that do not have transcripts.
```

##### Example 4 — Find videos without transcripts

```text
Run the Actor for these TikTok URLs and show only records whose status is
no_transcript. Include the URL, creator, and available video metadata.
```

Other things you can ask your Agent to do after it calls the Actor:

- “Extract the available transcript and summarize the video's main points.”
- “Process these TikTok URLs and compare their opening hooks with engagement metrics.”
- “Return a table with creator, transcript, views, likes, shares, hashtags, and duration.”
- “Save the transcript text and video metadata for my RAG or knowledge-base pipeline.”
- “Show which URLs returned `no_transcript` or `error` without stopping the rest of the batch.”

The summarization, comparison, classification, or RAG step is performed by your Agent after retrieval; this Actor itself returns source transcript and metadata only.

#### Pricing when used by AI Agents

AI Agent calls use exactly the same event-based pricing as runs started from Apify Console or the API.

| Result | Charged |
| --- | --- |
| `success` | `video-result` + `transcript-result` |
| `no_transcript` | `video-result` only |
| `private_video` | No |
| `deleted_video` | No |
| `invalid_url` | No |
| `error` | No |

- Billing is event-based.
- Billing is **not** based on the number or length of prompts.
- Using an AI client through MCP does **not** change the Actor's pricing.
- AI Agent pricing is identical to the pricing in the [Pricing](#-pricing) section.

#### AI Agent FAQ

##### Which AI clients can use this Actor?

Any AI client compatible with the Apify MCP Server can use it, including ChatGPT, Claude, Cursor, and Codex.

##### Does using an AI client change the Actor's price?

No. The same `video-result` and `transcript-result` event pricing applies whether the Actor is called by an AI Agent, from Apify Console, or through the API.

##### Where should I store my Apify API token?

Store it in your AI client's secure MCP or connection settings. Never place it in a prompt, screenshot, public repository, or shared document.

##### Does this Actor perform AI transcription?

No. It retrieves existing publicly available TikTok captions and does not generate a transcript from video audio.

##### Can my AI Agent summarize the transcript?

Yes. The Actor returns the source transcript; your AI Agent can then summarize, compare, classify, or format it according to your request.

### Input

Provide a non-empty `tiktokUrls` array. One item is a single-video run; multiple items form a batch.

| Field | Type | Required | Default | Limits and purpose |
| --- | --- | --- | --- | --- |
| `tiktokUrls` | string\[] | **Yes** | prefilled example | Between 1 and 1,000 normal TikTok video URLs, TikTok share URLs, `vm.tiktok.com` URLs, or `vt.tiktok.com` URLs. |
| `preferredLanguage` | string | No | `en` | Preferred existing caption language, such as `en`, `es`, or `zh-Hans`. If unavailable, falls back to English, then the original or another available caption. Does not translate captions. |

#### Input behavior

- One URL in `tiktokUrls` processes one video; multiple URLs run as a batch.
- Empty strings are ignored.
- Duplicate URL strings are removed before processing.
- After deduplication, URLs keep their first-seen order.
- Every unique URL produces one dataset record, including unsuccessful results.
- `preferredLanguage` selects among captions TikTok already exposes; it is not a translation request.
- When omitted or empty, English is preferred. The fallback order is: requested language → English → original caption → another available caption.
- Supported short TikTok links are resolved before processing.

### Input examples

#### Process one TikTok video

```json
{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"
  ]
}
```

#### Process a bulk URL list

```json
{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc",
    "https://vm.tiktok.com/ZMExample1/",
    "https://vt.tiktok.com/ZSExample2/"
  ]
}
```

#### Prefer a Simplified Chinese caption (with English fallback)

```json
{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc",
    "https://www.tiktok.com/t/ZTExample3/"
  ],
  "preferredLanguage": "zh-Hans"
}
```

### API usage

Actor ID used in all examples:

```text
lance_api/tiktok-transcript-scraper
```

Set your Apify API token in the standard `APIFY_TOKEN` environment variable. Never hard-code it in application source code.

#### JavaScript

Install the official client:

```bash
npm install apify-client
```

Run the Actor and retrieve its default dataset:

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

const client = new ApifyClient({
    token: process.env.APIFY_TOKEN,
});

const input = {
    tiktokUrls: [
        'https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc',
        'https://vm.tiktok.com/ZMExample1/',
    ],
    preferredLanguage: 'en',
};

const run = await client
    .actor('lance_api/tiktok-transcript-scraper')
    .call(input);

const { items } = await client
    .dataset(run.defaultDatasetId)
    .listItems();

console.log(items);
```

#### Python

Install the official client:

```bash
pip install apify-client
```

Run the Actor and iterate through its results:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run_input = {
    "tiktokUrls": [
        "https://www.tiktok.com/@samuelszuchan/video/"
        "7654471521490062605?is_from_webapp=1&sender_device=pc"
    ],
    "preferredLanguage": "en",
}

run = client.actor(
    "lance_api/tiktok-transcript-scraper"
).call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### cURL

Start a synchronous run and return dataset items:

```bash
curl --request POST \
  "https://api.apify.com/v2/acts/lance_api~tiktok-transcript-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "tiktokUrls": [
      "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc",
      "https://vm.tiktok.com/ZMExample1/"
    ],
    "preferredLanguage": "en"
  }'
```

For large runs, start the Actor asynchronously and retrieve its default dataset after completion.

### Output

The Actor writes **one normalized record per unique input URL** to the default dataset. Failed and no-transcript records are included, making bulk runs auditable without parsing logs.

Results are available through:

- Apify Console and Dataset API
- JavaScript and Python clients
- JSON, JSONL, CSV, Excel, XML, RSS, and HTML exports
- Tasks, schedules, webhooks, automation platforms, and custom applications

Core fields always use stable types. For unsuccessful records, transcript and metadata fields remain empty and `errorMessage` can explain the failure.

### Complete output field reference

#### Processing and core transcript fields

| Field | Type | Availability | Description |
| --- | --- | --- | --- |
| `status` | string | Always | One of `success`, `no_transcript`, `private_video`, `deleted_video`, `invalid_url`, or `error`. |
| `videoId` | string | Always; can be empty | TikTok video ID when available. Kept as a string to preserve identifier precision. |
| `tiktokUrl` | string | Always | Canonical TikTok video URL when identifiable; otherwise the submitted URL. |
| `transcriptText` | string | Always; empty unless successful | Plain text assembled from existing timed caption cues. |
| `transcriptVtt` | string | Always; empty unless successful | Normalized WebVTT subtitle document beginning with `WEBVTT`. |
| `transcriptSegments` | object\[] | Always | Timed caption cues. Empty when no transcript was returned. |
| `transcriptSegments[].start` | number | Successful segments | Cue start time in seconds. |
| `transcriptSegments[].end` | number | Successful segments | Cue end time in seconds. |
| `transcriptSegments[].text` | string | Successful segments | Cleaned text for the cue. |
| `language` | string | Always; can be empty | Selected TikTok caption language code. For `no_transcript`, it can fall back to the description language. |
| `processedAt` | ISO 8601 string | Always | Time the URL result was produced. |
| `errorMessage` | string | Errors only | Safe diagnostic text explaining why the URL could not be processed. Sensitive values are redacted. |

#### Video and creator metadata

| Field | Type | Availability | Description |
| --- | --- | --- | --- |
| `videoDescription` | string | Always; can be empty | Original public TikTok video description. |
| `authorUsername` | string | Always; can be empty | Creator username without the `@` prefix. |
| `authorNickname` | string | Always; can be empty | Creator display name. |
| `authorId` | string | Always; can be empty | TikTok creator identifier. |
| `coverImageUrl` | string | Always; can be empty | Public TikTok cover or thumbnail URL. The URL can expire. |
| `hashtags` | string\[] | When video detail is returned | Deduplicated hashtag names from TikTok metadata or the video description. |
| `videoDuration` | number | When video detail is returned | Video duration in seconds. |
| `videoWidth` | number | When video detail is returned | Video width in pixels. |
| `videoHeight` | number | When video detail is returned | Video height in pixels. |
| `createTime` | ISO 8601 string | When available | TikTok video publication time normalized to ISO 8601. |
| `locationCreated` | string | When video detail is returned; can be empty | Region code returned for the video. It is not a precise physical location. |
| `authorBio` | string | When video detail is returned; can be empty | Public creator profile bio returned with the video. |
| `authorVerified` | boolean | When video detail is returned | Public verification indicator returned with the video detail. |
| `isAd` | boolean | When video detail is returned | Whether the available TikTok metadata identifies the item as advertising content. |

#### Engagement and creator statistics

| Field | Type | Availability | Description |
| --- | --- | --- | --- |
| `viewsCount` | number | Always | Public video view count; `0` when unavailable. |
| `likesCount` | number | Always | Public video like count; `0` when unavailable. |
| `commentsCount` | number | Always | Video comment count only; individual comments are not collected. |
| `sharesCount` | number | Always | Public video share count. |
| `collectCount` | number | When video detail is returned | Bookmark/save count returned for the video. |
| `followerCount` | number | When video detail is returned | Creator follower count returned with the video. It can be `0` when profile totals are not populated. |
| `authorHeartCount` | number | When video detail is returned | Creator total-like count returned with the video. It can be `0` when unavailable. |
| `authorVideoCount` | number | When video detail is returned | Creator video count returned with the video. It can be `0` when unavailable. |

#### Music metadata

| Field | Type | Availability | Description |
| --- | --- | --- | --- |
| `musicTitle` | string | When video detail is returned; can be empty | Music or sound title returned for the video. |
| `musicAuthor` | string | When video detail is returned; can be empty | Music or sound author returned for the video. |
| `isOriginalSound` | boolean | When video detail is returned | Whether the available metadata identifies the attached sound as original. The Actor does not infer this from the title. |

### Status values

| Status | Meaning | Transcript fields | `video-result` | `transcript-result` |
| --- | --- | --- | --- | --- |
| `success` | An existing caption was downloaded, parsed, and produced non-empty `transcriptText`. | Populated | **One event** | **One event** |
| `no_transcript` | Video data was available, but TikTok exposed no caption metadata. | Empty | **One event** | **No event** |
| `private_video` | The video is non-public or restricted. | Empty | **No event** | **No event** |
| `deleted_video` | The video is deleted, missing, or unavailable. | Empty | **No event** | **No event** |
| `invalid_url` | The submitted value was malformed or not a supported TikTok hostname. | Empty | **No event** | **No event** |
| `error` | A temporary retrieval or processing problem prevented completion. | Empty | **No event** | **No event** |

One unsuccessful URL does not fail the rest of a bulk run. Every unique input still receives a dataset record.

#### No-transcript example

Selected fields from an illustrative `no_transcript` record. The values do not describe the current state of the example video:

```json
{
  "status": "no_transcript",
  "videoId": "7654471521490062605",
  "tiktokUrl": "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605",
  "transcriptText": "",
  "transcriptVtt": "",
  "transcriptSegments": [],
  "language": "en",
  "videoDescription": "Example video without available captions",
  "authorUsername": "samuelszuchan",
  "authorNickname": "Example Creator",
  "authorId": "7000000000000000001",
  "viewsCount": 1200,
  "likesCount": 45,
  "commentsCount": 3,
  "sharesCount": 2,
  "coverImageUrl": "https://example.com/public-cover.jpeg",
  "processedAt": "2026-08-02T06:30:00.000Z"
}
```

#### Error example

Complete core fields from an `error` record:

```json
{
  "status": "error",
  "videoId": "",
  "tiktokUrl": "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc",
  "transcriptText": "",
  "transcriptVtt": "",
  "transcriptSegments": [],
  "language": "",
  "videoDescription": "",
  "authorUsername": "",
  "authorNickname": "",
  "authorId": "",
  "viewsCount": 0,
  "likesCount": 0,
  "commentsCount": 0,
  "sharesCount": 0,
  "coverImageUrl": "",
  "errorMessage": "The existing caption could not be retrieved before the request timed out.",
  "processedAt": "2026-08-02T06:30:00.000Z"
}
```

### Complete output example

The example below demonstrates the complete schema using illustrative metadata values. Counts and profile values do not represent the example video's current live data.

```json
{
  "status": "success",
  "videoId": "7654471521490062605",
  "tiktokUrl": "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605",
  "transcriptText": "Here are three ways to improve your next video. Start with a clear hook.",
  "transcriptVtt": "WEBVTT\n\n00:00:00.460 --> 00:00:03.200\nHere are three ways to improve your next video\n\n00:00:03.200 --> 00:00:05.800\nStart with a clear hook\n",
  "transcriptSegments": [
    {
      "start": 0.46,
      "end": 3.2,
      "text": "Here are three ways to improve your next video"
    },
    {
      "start": 3.2,
      "end": 5.8,
      "text": "Start with a clear hook"
    }
  ],
  "language": "en",
  "videoDescription": "Three practical video tips #contenttips",
  "authorUsername": "samuelszuchan",
  "authorNickname": "Sample Creator",
  "authorId": "7000000000000000001",
  "viewsCount": 125000,
  "likesCount": 8400,
  "commentsCount": 316,
  "sharesCount": 540,
  "coverImageUrl": "https://example.com/public-cover.jpeg",
  "processedAt": "2026-08-02T06:30:00.000Z",
  "hashtags": [
    "contenttips"
  ],
  "collectCount": 1200,
  "videoDuration": 42.35,
  "videoWidth": 1080,
  "videoHeight": 1920,
  "createTime": "2026-07-20T14:00:00.000Z",
  "locationCreated": "US",
  "musicTitle": "Original sound - samuelszuchan",
  "musicAuthor": "Sample Creator",
  "isOriginalSound": true,
  "followerCount": 250000,
  "authorHeartCount": 8700000,
  "authorVideoCount": 415,
  "authorBio": "Public example creator profile.",
  "authorVerified": false,
  "isAd": false
}
```

### 💰 Pricing

Pricing has two transparent parts: a **video metadata result fee** and a **transcript add-on** that applies only when transcript text is returned.

| Charge | Free users | All other Apify tiers | When it applies |
| --- | ---: | ---: | --- |
| Video result (`video-result`) | **$0.002/result** (**$2/1,000**) | **$0.001/result** (**$1/1,000**) | Once when a video detail result is returned with `success` or `no_transcript`. |
| Transcript add-on (`transcript-result`) | **$0.001/result** (**$1/1,000**) | **$0.001/result** (**$1/1,000**) | Added only when `status` is `success` and `transcriptText` is non-empty. |

Total price for a video with a transcript:

- **Free users:** $0.003 per result, or $3 per 1,000.
- **All other Apify tiers:** $0.002 per result, or $2 per 1,000.

A `no_transcript` result pays only the video-result fee—**there is no transcript add-on**. `private_video`, `deleted_video`, `invalid_url`, and `error` records are returned for auditability but emit neither pricing event. A successful record is charged once per event regardless of how many caption segments it contains.

Exact duplicate URL strings are removed before processing, so a duplicate in the same `tiktokUrls` input does not create or charge another result. See the Actor's **Pricing** tab for the published event configuration and any Apify platform usage applicable to your plan.

### 🎯 Use cases

#### AI and agent workflows

Send `transcriptText` to your own summarizer, classifier, RAG pipeline, chatbot, or research agent without first converting subtitle files.

#### TikTok content research

Compare hooks, scripts, calls to action, topics, and publishing patterns while keeping video engagement and creator context beside the transcript.

#### Searchable transcript archives

Store normalized text and stable video identifiers in a database, search index, or internal knowledge system.

#### Script and creative analysis

Use caption-level timing to study pacing, structure, and the sequence of ideas in publicly available TikTok videos.

#### Dataset enrichment

Add transcript, language, hashtags, engagement, music, duration, and creator metadata to an existing list of TikTok video URLs.

#### API and no-code automation

Connect transcript extraction to scheduled Tasks, webhooks, automation platforms, data warehouses, or custom applications through Apify.

### How it works

1. Validate and deduplicate the submitted TikTok URLs.
2. Resolve supported TikTok video and short-link URLs.
3. Retrieve publicly available TikTok caption data.
4. Select the preferred available caption language, with English as the default fallback.
5. Normalize captions into plain text, WebVTT, and timed segments.
6. Normalize public video and creator metadata into a consistent structure.
7. Write one structured dataset record for every unique input URL.

The Actor does not bypass access controls, download the video, extract its audio, or use ASR as a fallback.

### Public data and responsible use

This Actor is designed for responsible processing of publicly accessible TikTok video and caption data.

- It does not access private accounts or non-public videos.
- It does not bypass login, permissions, geographic restrictions, or other access controls.
- It does not download video or audio files.
- It does not generate speech-to-text content for videos without captions.
- It does not collect individual comments or private creator information.

You are responsible for complying with TikTok's terms, Apify's terms, applicable privacy requirements, and copyright law. Do not use the Actor for harassment, spam, unlawful profiling, copyright infringement, or attempts to obtain non-public information.

### FAQ

#### What does this TikTok transcript scraper return?

For a successful video, it returns plain transcript text, normalized WebVTT, timed transcript segments, caption language, video metadata, creator fields, and engagement statistics.

#### Does the Actor transcribe TikTok audio?

No. It extracts existing captions only. It does not run ASR, speech-to-text, or an AI transcript generator.

#### What happens when a TikTok video has no transcript?

The result uses `status: "no_transcript"` and empty transcript fields. It emits the base `video-result` event, but **no `transcript-result` add-on** is charged.

#### Which TikTok URL formats are supported?

Normal `www.tiktok.com/@user/video/...` URLs, TikTok `/t/...` share links, `vm.tiktok.com` links, and `vt.tiktok.com` links are accepted.

#### Can I extract transcripts from multiple TikTok videos?

Yes. Add up to 1,000 URLs to `tiktokUrls`. One item is a single-video run; multiple items form a batch. Each URL is processed independently, and duplicate strings are removed before processing.

#### Does `preferredLanguage` translate the transcript?

No. It selects that language only when TikTok already exposes a matching caption. English is the default and first fallback; if English is also unavailable, the Actor uses the original or another available caption.

#### Why can a video return `error` even when captions are available on TikTok?

Public captions can sometimes be temporarily unavailable because of access, regional, rate-limit, or network conditions. In that case, the Actor reports `error` instead of incorrectly reporting `no_transcript`.

#### Are speaker labels or word-level timestamps included?

No. `transcriptSegments` contains caption-level start time, end time, and text. Speaker diarization, word-level timing, confidence scores, and translation are not generated.

#### Does the Actor return TikTok comments?

No. `commentsCount` is the public count returned with video metadata; individual, pinned, and creator comments are not collected.

#### Why can creator totals be zero?

Publicly available video metadata can omit profile-level totals such as followers, total likes, or video count. The Actor returns `0` when a value is unavailable and never replaces it with a guess.

#### How are failed URLs handled in a bulk run?

They are written to the same dataset with their own status and, when available, `errorMessage`. Other URLs continue processing.

#### How can I control cost?

Start with a small `tiktokUrls` list, remove unnecessary inputs, and set an Apify maximum charge limit. Exact duplicate URL strings are already removed automatically.

### Limitations

- Only captions already exposed for publicly accessible TikTok videos can be extracted.
- Private, deleted, region-restricted, age-restricted, or otherwise unavailable videos cannot be accessed.
- Public caption availability can vary by video, region, and time.
- Temporary TikTok, rate-limit, or network conditions can affect individual results.
- `preferredLanguage` defaults to English, does not translate captions, and cannot create a language TikTok does not provide.
- The Actor does not download videos, extract audio, run ASR, infer speakers, generate word-level timestamps, translate transcripts, or collect individual comments.
- Some metadata fields can be empty or `0` when the public video data does not include them.
- Engagement counts can change after a run and reflect the public value available at processing time.
- Short-link resolution and caption availability can change over time.

### Support

Need help, want to report an issue, or have a feature request?

- Open the Actor's **Issues** tab in Apify Console
- Email **lanceapi2026@hotmail.com**

For faster diagnosis, include the **Run ID**, the returned `status`, the non-sensitive `errorMessage`, and a public example URL when appropriate. Never send your Apify API token, cookies, session IDs, or other secrets.

# Actor input Schema

## `tiktokUrls` (type: `array`):

One or more normal, share, vm.tiktok.com, or vt.tiktok.com video URLs. Duplicate strings are removed. Maximum 1,000 unique URLs per run.

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

Select a preferred existing caption language. English is the default and fallback. If needed, enter another valid language code. This selects available captions and does not translate them.

## Actor input object example

```json
{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"
  ],
  "preferredLanguage": "en"
}
```

# Actor output Schema

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

Normalized transcript and TikTok metadata records.

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

Counts grouped by processing status.

# 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 = {
    "tiktokUrls": [
        "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lance_api/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 = { "tiktokUrls": ["https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"] }

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

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

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

```

## CLI example

```bash
echo '{
  "tiktokUrls": [
    "https://www.tiktok.com/@samuelszuchan/video/7654471521490062605?is_from_webapp=1&sender_device=pc"
  ]
}' |
apify call lance_api/tiktok-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=lance_api/tiktok-transcript-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/jW1iFDg3thLoOg4ic/builds/61xcJaeZ9MUbcKUBT/openapi.json
