# TikTok & YouTube Transcript Scraper (`paintedwinter/tiktok-youtube-transcript`) Actor

Transcribe TikTok & YouTube videos — even ones with no captions. Clean transcripts with per-phrase timestamps and automatic language detection, or a cheaper metadata-only mode.

- **URL**: https://apify.com/paintedwinter/tiktok-youtube-transcript.md
- **Developed by:** [painted Labs](https://apify.com/paintedwinter) (community)
- **Categories:** AI, Videos, Social media
- **Stats:** 19 total users, 0 monthly users, 82.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 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.

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

Turn any TikTok or YouTube video into text. This Actor runs **speech-to-text on the video's audio**, so it returns a transcript even when the video has no captions or subtitles. Paste video URLs, get clean transcripts with per-phrase timestamps — or switch to a cheaper **metadata-only** mode when you just need titles, captions and durations. Built and maintained by [Painted Labs](https://painted-labs.com).

### What does this Actor do?

- 🎙️ **Speech-to-text transcription** — runs on the actual audio. Works on videos that have no captions at all.
- ⏱️ **Per-phrase timestamps** — each transcript comes with `{ start, end, text }` segments, ready for subtitles or clip search.
- 🌐 **Automatic language detection** — the spoken language is detected per video and returned in the output. No configuration needed.
- 📋 **Metadata-only mode** — flip one switch to skip transcription and fetch just the title, description/caption and duration, at a much lower price.
- 🔗 **TikTok and YouTube in one run** — `tiktok.com`, `youtube.com` and `youtu.be` links, mixed freely.
- 👤 **Whole profiles, channels & playlists** — paste a TikTok profile or YouTube channel/playlist URL and its newest videos are pulled in automatically, up to a per-source limit you set.
- 🔍 **YouTube keyword search** — turn a search query straight into transcripts of the top matching videos.
- 🎛️ **Date & popularity filters** — when pulling from profiles, channels or search, keep only videos from a date range or above a view count, newest-first or most-viewed-first.

### What data you get

| Field | Description |
|---|---|
| `url` | The video URL you submitted |
| `success` | Whether the video was processed |
| `transcript` | The spoken words, as text (empty in metadata-only mode or when there is no speech) |
| `segments` | Timestamped `{ start, end, text }` phrases (transcription mode) |
| `language` | Detected spoken language |
| `durationSeconds` | Video length in seconds |
| `title` | Video title |
| `description` | Video caption / description |
| `viewCount` | View count at scrape time (videos discovered via profiles/channels/search) |
| `postedAt` | Post date (videos discovered via profiles/channels/search) |
| `jobId` | Internal id for the processed video |

### How to use it

1. Open the Actor and press **Try for free**.
2. Paste your TikTok / YouTube links into **Video URLs**, one per line — and/or add profile, channel or playlist URLs (or a YouTube search) to pull whole feeds.
3. Leave **Transcribe audio** on for full transcripts, or switch it off for metadata only.
4. Press **Start**. Results stream into the dataset as each video finishes.
5. Export the results as JSON, CSV, or Excel from the **Storage** tab.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `videoUrls` | array | — | TikTok or YouTube video links, one per line. |
| `profileUrls` | array | — | TikTok usernames (`@user`) or profile URLs, YouTube channel or playlist URLs — each expands into its newest videos. |
| `searchQueries` | array | — | YouTube keyword searches — each expands into the top matching videos. |
| `maxVideosPerSource` | integer | `30` | Videos taken from each profile, channel, playlist, or search query (1–1,000). |
| `postedAfter` / `postedBefore` | date | — | Only include discovered videos posted in this date range. |
| `minViews` | integer | — | Only include discovered videos with at least this many views. |
| `sourceSorting` | string | `newest` | Take each source's videos newest-first or most-viewed-first (`mostViewed`). |
| `transcribe` | boolean | `true` | On: speech-to-text with timestamps. Off: metadata only (title, caption, duration). |
| `includeSegments` | boolean | `true` | Include timestamped `{ start, end, text }` segments with each transcript. |
| `subtitleFormat` | string | `none` | Also render each transcript as a subtitle file: `srt` or `vtt`. Free. |
| `translateTo` | string | `none` | Add a translation of each transcript in the `translation` field ($0.01/video, only charged when delivered). Requires `transcribe: true`. |
| `maxConcurrency` | integer | `4` | Number of videos processed in parallel (1–8). |
| `perVideoTimeoutSecs` | integer | `900` | Give up on a single video after this many seconds (60–3600). |

At least one of `videoUrls`, `profileUrls`, or `searchQueries` is required. The date/views filters and sorting apply to videos discovered through profiles, channels, playlists and search — direct `videoUrls` are always processed as given. When a platform's listing doesn't expose a video's post date or view count, an active filter skips that video.

```json
{
    "videoUrls": [
        "https://www.tiktok.com/@username/video/7301234567890123456",
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "profileUrls": ["https://www.tiktok.com/@username"],
    "searchQueries": ["keyword to look up on youtube"],
    "maxVideosPerSource": 30,
    "transcribe": true
}
```

### Output

One dataset item per input URL. A transcription result:

```json
{
    "url": "https://www.tiktok.com/@username/video/7301234567890123456",
    "success": true,
    "transcript": "Okay so in this video I'm going to walk you through the whole process step by step, it's easier than it looks and it takes about ten minutes...",
    "language": "en",
    "durationSeconds": 47.3,
    "title": "How to do it in 10 minutes",
    "description": "Full walkthrough in the video #howto #tutorial",
    "segments": [
        { "start": 0.0, "end": 3.4, "text": "Okay so in this video I'm going to walk you through the whole process" },
        { "start": 3.4, "end": 6.9, "text": "step by step, it's easier than it looks" }
    ],
    "jobId": "e9b1d2c4-5f6a-4b7c-8d9e-0f1a2b3c4d5e"
}
```

A metadata-only result (`transcribe: false`):

```json
{
    "url": "https://www.tiktok.com/@username/video/7301234567890123456",
    "success": true,
    "title": "How to do it in 10 minutes",
    "description": "Full walkthrough in the video #howto #tutorial",
    "durationSeconds": 47.3,
    "jobId": "meta_766d7d3ea24fe0f309e6ff6e"
}
```

Special cases:

- **No speech** (music-only or photo/slideshow posts): `success: true`, `noSpeech: true`, `transcript: ""` — the caption is returned instead, and no transcription fee is charged. This is only reported when the audio was actually processed; an empty result that can't be verified comes back as a failure (`EMPTY_RESULT_UNVERIFIED`), not as "no speech".
- **Failure** (unavailable video, over the length limit, timeout, or unsupported URL): `{ "url": ..., "success": false, "error": "..." }` — not charged.

### Pricing

| Event | Price | When |
|---|---|---|
| **Result** | $0.0018 ($1.80 / 1,000) | Every successfully processed video. |
| **Transcription** | +$0.018 per started minute | Only when audio is actually transcribed, once per started minute of video. |
| **Translation** | +$0.01 ($10 / 1,000) | Only when a requested translation is actually delivered. |

A video under a minute — most short-form content — is one started minute: $0.0198 all-in, about $19.80 per 1,000 videos. A 3m20s video counts as 4 minutes ($0.0738 all-in). Metadata-only runs cost $1.80 per 1,000 videos. Failed videos, timeouts, unsupported URLs and no-speech videos are never charged the transcription fee.

Everything else is free: pulling videos from profiles, channels, playlists and search queries costs nothing (discovered videos are billed exactly like directly submitted URLs), and so are the date/popularity filters, sorting, timestamped segments, and SRT/VTT subtitle files. A failed translation is never charged.

**Free Apify plan:** limited to 5 videos and 1 transcription per month, without add-ons (translation, subtitle files). Any paid Apify plan unlocks everything.

### What you can build with it

- 🤖 **LLM & RAG pipelines** — feed clean, timestamped speech into your models.
- 📈 **Content research** — analyse what creators actually say, not just what they caption.
- 🎬 **Subtitles & clips** — per-phrase segments drop straight into SRT/VTT and clip-search tools.
- 🔎 **Search & indexing** — make video audio searchable as text.

### API usage

#### JavaScript (`apify-client`)

```js
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "YOUR_APIFY_TOKEN" });

const run = await client.actor("paintedwinter/tiktok-youtube-transcript").call({
    videoUrls: [
        "https://www.tiktok.com/@username/video/7301234567890123456",
        "https://youtu.be/dQw4w9WgXcQ",
    ],
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.url, "->", item.transcript);
```

#### Python (`apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("paintedwinter/tiktok-youtube-transcript").call(run_input={
    "videoUrls": ["https://www.tiktok.com/@username/video/7301234567890123456"],
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["url"], "->", item["transcript"])
```

#### curl (synchronous, small batches)

```bash
curl -X POST "https://api.apify.com/v2/acts/paintedwinter~tiktok-youtube-transcript/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"] }'
```

> `run-sync-get-dataset-items` waits for the run and returns items directly, capped at 5 minutes. For larger batches, start an async run and fetch the dataset when it finishes (as in the examples above).

### Use with AI assistants (MCP)

This Actor can be called directly as a tool by AI assistants and agents through [Apify's MCP server](https://mcp.apify.com) — ask your assistant to transcribe a video and it runs the Actor for you.

**Claude Code / Claude Desktop:**

```bash
claude mcp add --transport http apify https://mcp.apify.com?actors=paintedwinter/tiktok-youtube-transcript --header "Authorization: Bearer YOUR_APIFY_TOKEN"
```

**Cursor and other MCP clients:** add `https://mcp.apify.com?actors=paintedwinter/tiktok-youtube-transcript` as a streamable-HTTP MCP server with your Apify token as the Authorization bearer header.

Your assistant then gets a `tiktok-youtube-transcript` tool: pass video URLs, get transcripts back in the conversation.

### FAQ

**Does it work on videos without captions?**
Yes. It transcribes the audio directly, so it returns text whenever the video has speech — captions are not required.

**How long does a video take?**
Transcription takes about 5–10 seconds per 10 minutes of video. Metadata-only is a few seconds.

**Is there a length limit?**
Transcription is limited to 10 minutes per video; longer videos fail with a clear error and are not charged. Metadata-only mode has no length limit.

**Which languages does it support?**
All major languages are detected automatically. Each result reports the detected language.

**Can it do a whole profile or channel?**
Yes — put the profile/channel/playlist URL in **Profiles / channels / playlists** and its newest videos are pulled in automatically (set how many with **Videos per source**, optionally filtered by date or views).

**Can I search by keyword?**
On YouTube, yes — add your query to **YouTube search queries**. TikTok doesn't expose keyword search, so for TikTok use profile URLs instead.

**Does it support Instagram?**
Not yet. Instagram URLs currently return `success: false` — free of charge.

**Is it legal?**
This Actor processes publicly available videos only — the same content anyone can view without logging in. It uses no login credentials and collects no private data. You are responsible for using the output in line with the source platform's terms and the laws that apply to you.

***

Built and maintained by [Painted Labs](https://painted-labs.com).

# Actor input Schema

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

TikTok or YouTube video links to transcribe (full URLs, one per line). Works on videos with no captions — the audio itself is transcribed. Instagram support is coming soon.

## `profileUrls` (type: `array`):

TikTok usernames (@user) or profile URLs, YouTube channel URLs (youtube.com/@handle, /channel/, /c/, /user/) or YouTube playlist URLs. Each one expands into its newest videos, up to 'Videos per source'.

## `searchQueries` (type: `array`):

Keyword searches (YouTube only — TikTok does not expose keyword search). Each query expands into the top matching videos, up to 'Videos per source'.

## `maxVideosPerSource` (type: `integer`):

How many videos to take from each profile, channel, playlist, or search query (a whole run is capped at 1,000 videos).

## `postedAfter` (type: `string`):

Only include discovered videos posted on or after this date (YYYY-MM-DD). Applies to profiles/channels/searches, not to direct video URLs. Videos whose post date the platform listing doesn't expose are skipped.

## `postedBefore` (type: `string`):

Only include discovered videos posted on or before this date (YYYY-MM-DD). Applies to profiles/channels/searches, not to direct video URLs.

## `minViews` (type: `integer`):

Only include discovered videos with at least this many views. Videos whose view count the platform listing doesn't expose are skipped. Applies to profiles/channels/searches, not to direct video URLs.

## `sourceSorting` (type: `string`):

Order in which each source's videos are taken before the per-source cap is applied: newest first (the platform's feed order) or most viewed first.

## `transcribe` (type: `boolean`):

ON: transcribes the spoken audio (per-phrase timestamps included). OFF: metadata only — title, description/caption, duration — at a fraction of the price, no transcription fee. Note: free Apify accounts are limited to 5 videos and 1 transcription per month — any paid Apify plan unlocks everything.

## `translateTo` (type: `string`):

Optionally add a translation of each transcript, returned in the item's `translation` field ($0.01 per video, charged only when a translation is actually delivered — if translation fails, the item simply has no translation field and nothing is charged). Requires 'Transcribe audio' to be ON.

## `subtitleFormat` (type: `string`):

Also render each transcript as a ready-to-save subtitle file in the chosen format, returned in the item's `subtitles` field. Free — no extra charge.

## `includeSegments` (type: `boolean`):

Include timestamped segments ({start, end, text}) in each result when the transcription backend provides them.

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

How many videos to transcribe in parallel.

## `perVideoTimeoutSecs` (type: `integer`):

Give up on a single video after this many seconds. A typical video finishes in 15-60 seconds; the default leaves plenty of headroom for queue spikes.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@user/video/1234567890"
  ],
  "maxVideosPerSource": 30,
  "sourceSorting": "newest",
  "transcribe": true,
  "translateTo": "none",
  "subtitleFormat": "none",
  "includeSegments": true,
  "maxConcurrency": 4,
  "perVideoTimeoutSecs": 900
}
```

# Actor output Schema

## `results` (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": [
        "https://www.tiktok.com/@user/video/1234567890"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("paintedwinter/tiktok-youtube-transcript").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/@user/video/1234567890"] }

# Run the Actor and wait for it to finish
run = client.actor("paintedwinter/tiktok-youtube-transcript").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 '{
  "videoUrls": [
    "https://www.tiktok.com/@user/video/1234567890"
  ]
}' |
apify call paintedwinter/tiktok-youtube-transcript --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/7XAIO5hdnimHYD4Vf/builds/mamtWOIh5aaMJ5epP/openapi.json
