# YouTube Shorts, TikTok & Reels Transcript Scraper (`lergassy/tiktok-reels-shorts-transcript-scraper`) Actor

One run for all three platforms: YouTube Shorts, TikTok and Instagram Reels turned into text — transcript with timestamps, on-screen captions and the first-3-second hook. Shorts use YouTube's own captions, so they cost less. Links or whole profiles, no login.

- **URL**: https://apify.com/lergassy/tiktok-reels-shorts-transcript-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** AI, Videos, Social media
- **Stats:** 7 total users, 4 monthly users, 97.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 videos

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

**YouTube Shorts, TikTok & Reels Transcript Scraper** covers all three short-video platforms in one
run — **without a login, cookies or an official API**. Paste links, or a TikTok handle and a YouTube
channel, and get one clean row per video: transcript with timestamps, the text burned into the
picture, and the first-3-second hook.

YouTube Shorts use the caption track YouTube has already made, so they come back in seconds and are
billed at the video price alone, with no charge for audio.

If you only ever work with one platform, we keep narrower Actors for
[TikTok](https://apify.com/lergassy/tiktok-transcript-scraper) and Instagram Reels — same engine,
same price, a simpler form.

### What is YouTube Shorts, TikTok & Reels Transcript Scraper?

**YouTube Shorts, TikTok & Reels Transcript Scraper** turns a short vertical video into structured text: the **spoken transcript**, the **text written on screen**, and the **first three seconds** of both — the hook. It works on **Instagram Reels**, **TikTok** videos and **YouTube Shorts**, with **no login, no cookies and no official API needed**.

Most transcript scrapers stop at the audio. In short-form video the audio is often not where the message is: in our test set of 26 real videos, **only 69% carried a narrated script**, 19% had no usable speech at all, and 12% ran on someone else's trending sound. **81% had text on screen.** An actor that reads only the audio returns noise or nothing on roughly a third of a real feed.

This one reads both, tells them apart, and says which kind of video you gave it.

### What data can YouTube Shorts, TikTok & Reels Transcript Scraper extract?

| Field | Example |
|---|---|
| `transcriptText` | `Today, I wanted to do a quick tips and tricks or best practices for posting reels…` |
| `firstThreeSecondsSpeech` | `Today, I wanted to do a quick tips and tricks or best practices for` |
| `onScreenText` | `Reels Tips & Tricks`, `No Watermarks`, `Under 3 Minutes`, `Add Music/Audio` |
| `firstThreeSecondsOnScreen` | `Reels Tips & Tricks` |
| `contentClass` | `narrated` · `borrowed_audio` · `silent` · `empty` |
| `speechDetected`, `speechCoverage` | `true`, `0.89` |
| `burnedInCaptionCount` | `41` |
| `screenRecording` | `false` |
| `language`, `durationSeconds`, `platform`, `videoId` | `en`, `61.3`, `instagram`, `DFIWSVoy1UQ` |

#### Why on-screen text is separated from subtitles

Half the videos we measured carry **burned-in subtitles** that simply repeat the speech. Dumping every recognised string into one field means the same sentence appears twice and the actual title cards drown in it.

This actor separates them by two signals: how closely a line matches what is being said **at that exact moment**, and which horizontal band of the frame it lives in. On a labelled video with 54 text tracks the split came out with **no errors**. `onScreenText` therefore contains what the author wrote for the viewer; `burnedInCaptionCount` tells you how many subtitle tracks were removed.

#### Why the content class matters

Speech recognition models do not stay silent over music — they invent. On a wordless branded clip the model returned `"We'll be right back."`, and its own confidence score for that invention was **0.00 false positive** — the metric that is supposed to catch this says nothing. So the class is decided from word density and how much of the clip speech actually covers.

| Class | What it means | What you get |
|---|---|---|
| `narrated` | The voice carries the script | Transcript + on-screen text |
| `borrowed_audio` | A trending sound or a clip from someone else — not the author's words | On-screen text; the audio is labelled, not passed off as a script |
| `silent` | No speech; the meaning is in the captions | On-screen text only |
| `empty` | Neither speech nor on-screen text | An explicit refusal instead of blank fields |

A looping trending sound is caught by its own repetition: when one line comes back word for word three times or more, it is a sound, not a script.

### How much does it cost to extract Reel transcripts?

Pay-per-event, no subscription, and short clips are not billed as if they were long ones.

| Event | Price |
|---|---|
| `reel-processed` — one video: transcript with timestamps, language, hook | **$0.002** |
| `audio-10-seconds` — each started 10 seconds of speech recognised | **$0.001** |
| `on-screen-text` — one video read frame by frame for burned-in text | **$0.06** |

A 15-second TikTok costs **$0.004**. A 30-second Reel costs **$0.005**. A 60-second Short costs
**$0.008**. Reading on-screen text is a separate switch and a separate charge, because it is a
separate job: the video is downloaded and read frame by frame.

**Failed URLs, videos above your duration limit and silent videos are never billed.** A row you
cannot use is a row you do not pay for.

#### Bulk export: what 50,000 videos actually cost

This Actor is built for bulk jobs — put hundreds of URLs into one run, or call it from the API on a
schedule. Videos are processed three at a time, and there is **no fee per run, no fee per page and
no proxy charge**.

| Job | This Actor | Most-used transcript Actor in this category |
|---|---|---|
| 50,000 TikToks or Reels of 30 seconds | **$250** | $305 |
| 50,000 YouTube Shorts (captions, no recognition) | **$100** | $305 |
| 50,000 clips of 15 seconds | **$200** | $239 |

Checked on the Apify Store on 21 September 2026 against the Reel-transcript Actor with the most
monthly users, which charges per dataset item plus per minute of audio, rounded to the minute. Ours
is billed in 10-second steps, which is where most of the difference comes from: a 9-second TikTok
should not cost the same as a 59-second one.

Two things here that the alternatives do not do at all: **three platforms in one run** — TikTok,
Instagram Reels and YouTube Shorts, one integration instead of three — and **on-screen text read
and separated from speech**, so caption cards and hard subtitles do not get mixed into what the
author actually said.

### How to extract TikTok, Reels and Shorts transcripts

1. Click **Try for free**.
2. Paste one or more video URLs into **🔗 Reel, TikTok or Shorts URLs**. The field comes prefilled with a working example, so you can just press Start.
3. Press **Start**. Results appear in the dataset, one row per video.

### ⬇️ Input

[![TikTok, Reels and Shorts transcript scraper input form with prefilled video URL](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/tiktok-reels-shorts-transcript-scraper/tiktok-reels-shorts-transcript-scraper-input-form.png)](https://console.apify.com/sign-up)

```json
{
  "videoUrls": [
    "https://www.instagram.com/reel/DFIWSVoy1UQ",
    "https://www.tiktok.com/@duolingo/video/7683994892506270989"
  ],
  "ocrFps": "1.5",
  "includeTranscriptSegments": true
}
```

#### Video URLs

Public Instagram Reels, TikTok videos and YouTube Shorts. Private and deleted videos return an error row naming the reason.

#### On-screen text sampling

How many frames per second are read for on-screen text. On our labelled video, 1.5 frames per second found **every** caption card; 1 frame per second lost three of six. 1.5 is the default; raise it only for dense motion graphics.

#### Whole profiles, not just links

Paste a TikTok handle (`@duolingo`), a TikTok profile link or a YouTube channel into **Whole
profiles**, set how many of the newest videos you want, and the Actor collects the links itself.
Add a date in **Only videos newer than** to keep a weekly watch cheap: anything older is skipped
before it is downloaded, so it costs nothing.

```json
{
  "profiles": ["@duolingo", "https://www.youtube.com/@MrBeast"],
  "resultsLimitPerProfile": 20,
  "onlyPostsNewerThan": "2026-09-01"
}
```

Instagram profiles need a login, so they are not supported — paste Reel URLs instead. A profile link
dropped into the URL field is understood too; you do not have to pick the right box.

#### YouTube Shorts cost less than the rest

For YouTube the Actor takes the caption track YouTube has already made, instead of downloading the
video and recognising speech. That means Shorts are billed at the video price alone, with **no
per-audio charge at all**, and they come back in seconds.

### ⬆️ Output

[![Dataset table with TikTok and Instagram Reels transcripts, on-screen text and hooks](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/tiktok-reels-shorts-transcript-scraper/tiktok-reels-shorts-transcript-scraper-output-table.png)](https://console.apify.com/sign-up)

One row per video:

```json
{
  "type": "reel",
  "url": "https://www.instagram.com/reel/DFIWSVoy1UQ",
  "platform": "instagram",
  "videoId": "DFIWSVoy1UQ",
  "durationSeconds": 61.3,
  "language": "en",
  "contentClass": "narrated",
  "contentClassReason": "speech covers most of the clip",
  "speechDetected": true,
  "speechCoverage": 0.891,
  "transcriptText": "Today, I wanted to do a quick tips and tricks…",
  "firstThreeSecondsSpeech": "Today, I wanted to do a quick tips and tricks or best practices for",
  "onScreenText": [
    { "t": "0.33-4.33", "text": "Reels Tips & Tricks" },
    { "t": "7.33-8.67", "text": "No Watermarks" },
    { "t": "11.67-13.0", "text": "Under 3 Minutes" }
  ],
  "onScreenTextJoined": "Reels Tips & Tricks\nNo Watermarks\nUnder 3 Minutes",
  "firstThreeSecondsOnScreen": "Reels Tips & Tricks",
  "burnedInCaptionCount": 41,
  "screenRecording": false,
  "scrapedAt": "2026-09-18T09:20:31Z"
}
```

#### Error rows

A URL that cannot be processed returns a row of its own and is not billed:

```json
{ "type": "error", "url": "…", "errorCode": "download_failed", "errorMessage": "…" }
```

Codes: `download_failed`, `timeout`, `unsupported_url`, `audio_failed`, `transcription_failed`, `ocr_failed`, `processing_failed`.

### Use cases for Reel and TikTok transcript data

#### Competitive research

Feed a list of a competitor's videos and read their hooks side by side. `firstThreeSecondsSpeech` and `firstThreeSecondsOnScreen` are cut on the 3.0-second boundary, so the comparison is between what viewers actually received, not between opening sentences of different lengths.

#### Content repurposing

Turn a back catalogue into text for blog posts, newsletters and captions. `onScreenTextJoined` gives the written layer separately, which is what carries the message in silent videos.

#### Feeding an LLM or a RAG index

The output is flat, typed and one row per video. The content class tells your prompt when the transcript is not the author's words — which is what stops a summarising agent from confidently describing someone else's trending sound as this creator's message.

#### Accessibility and archiving

Transcripts and on-screen text for captioning, search and long-term storage of a feed that platforms may take down.

### Integrations

- **API**: run it from any language with the [Apify API](https://docs.apify.com/api/v2), or the [Python](https://docs.apify.com/api/client/python/) and [JavaScript](https://docs.apify.com/api/client/js/) clients.
- **MCP**: callable by AI agents through the [Apify MCP server](https://mcp.apify.com), like any other Actor.
- **No-code**: Make, Zapier, n8n, Google Sheets, Slack through Apify's integrations.
- **Webhooks**: trigger a downstream run when a batch finishes.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lergassy/tiktok-reels-shorts-transcript-scraper").call(run_input={
    "videoUrls": ["https://www.tiktok.com/@duolingo/video/7683994892506270989"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["firstThreeSecondsSpeech"], "|", item["onScreenTextJoined"])
```

### ❓ FAQ

#### Is it legal to scrape Instagram Reels and TikTok?

This Actor reads only public videos, the same ones any visitor can open without logging in, and it does not collect personal profiles. Laws differ by country and by intended use; consult a lawyer before building a commercial product on scraped data.

#### How much does it cost to transcribe 1,000 reels?

About $5 for 30-second clips and about $4 for 15-second ones — one event per video plus the seconds of speech actually recognised. Failed URLs are free.

#### Can I use it with the Apify API?

Yes — it is a standard Actor. Start a run, poll it, read the dataset, or use a webhook.

#### Can I use it through an MCP server?

Yes. It is exposed through Apify's MCP server and its input schema is written so an agent can call it correctly without reading this page.

#### Does it return one row per video?

Yes. One row per video, plus a separate error row for any URL that failed. Nested arrays (`transcript`, `onScreenText`) are provided alongside flat string versions so spreadsheets stay readable.

#### What languages does it handle?

Speech recognition is multilingual. On-screen text has been verified on **Latin and Cyrillic scripts**; other scripts are not claimed.

#### Why is the transcript empty on some videos?

Because the video has no speech. Rather than return an invented sentence, the Actor sets `speechDetected` to false and tells you the class. This is intended behaviour, not a failure.

#### Does it need proxies?

No. It runs without residential proxies, which is why extraction is priced where it is.

### You might also like

Part of our speech-and-text toolkit — the Store only recommends within a category, so here they are:

| Actor | What it does |
|---|---|
| [Whisper Transcriber](https://apify.com/lergassy/whisper-transcriber) | Any audio or video file to text, 90+ languages |
| [YouTube Transcript Scraper](https://apify.com/lergassy/youtube-transcript-scraper) | Transcripts from YouTube videos and playlists |
| [SRT Subtitle Generator](https://apify.com/lergassy/srt-subtitle-generator) | Ready-to-upload subtitle files from any video |
| [Audio Transcriber](https://apify.com/lergassy/audio-transcriber) | Podcasts, calls and meetings to text |
| [OCR Text Extractor](https://apify.com/lergassy/ocr-text-extractor) | Text out of images and screenshots |

Use this Actor for short vertical video, where the message is split between the voice and the screen; use the others when you already have a file or a long-form video.

### Your feedback

Found a video it handles badly? Open an issue on the Actor's **Issues** tab with the URL — that is the fastest way to get it fixed, and every issue gets a reply.

# Actor input Schema

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

Add one or more public video URLs — TikTok (tiktok.com/@user/video/...), Instagram Reels (instagram.com/reel/...) and YouTube Shorts. A profile link pasted here is understood too. No login or cookies needed.

## `profiles` (type: `array`):

Give a TikTok handle (@duolingo), a TikTok profile link or a YouTube channel, and the Actor takes its latest videos — no need to collect links by hand. Instagram profiles need a login and are not supported; paste Reel URLs above instead.

## `resultsLimitPerProfile` (type: `integer`):

How many of the newest videos to take from each profile.

## `onlyPostsNewerThan` (type: `string`):

Skip anything published before this date. Leave empty to take the newest videos whatever their date.

## `transcriptionMode` (type: `string`):

Speech recognition is the default and works everywhere. The two caption modes are here for platforms that publish their own subtitles — as of September 2026 TikTok, Instagram and YouTube do not expose them, so leave this on speech recognition unless a run tells you otherwise.

## `includeOnScreenText` (type: `boolean`):

Read the text burned into the picture — caption cards, title cards, hard subtitles — and split it from what the author actually says. No other Actor does this. It downloads the video and reads it frame by frame, so it is billed separately and takes several minutes per video. Off by default.

## `quality` (type: `string`):

Only used when a video has no captions of its own. Fast is enough for clear speech in short video; accurate helps with noise, accents and music.

## `language` (type: `string`):

Leave on Auto unless the video is short and the language is being guessed wrong.

## `maximumVideoDurationSeconds` (type: `integer`):

Videos longer than this are skipped with a free error row, before anything is downloaded. 0 means no limit. Useful when a profile mixes Shorts with hour-long uploads.

## `ocrFps` (type: `string`):

How often frames are read when “Read on-screen text” is on. On our labelled test video 1.5 frames per second found every caption card, while 1 lost three of six. Higher values cost more time, not more accuracy.

## `includeTranscriptSegments` (type: `boolean`):

Return the transcript as timestamped segments in addition to the plain text. Turn off for a flatter table.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@duolingo/video/7683994892506270989"
  ],
  "profiles": [
    "@duolingo"
  ],
  "resultsLimitPerProfile": 10,
  "transcriptionMode": "ai-only",
  "includeOnScreenText": false,
  "quality": "fast",
  "language": "auto",
  "maximumVideoDurationSeconds": 300,
  "ocrFps": "1.5",
  "includeTranscriptSegments": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per video: transcript, on-screen text, content class and, with the add-on, the teardown.

## `overview` (type: `string`):

Table view with the spoken and on-screen hooks side by side.

# 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/@duolingo/video/7683994892506270989"
    ],
    "profiles": [
        "@duolingo"
    ],
    "resultsLimitPerProfile": 10,
    "transcriptionMode": "ai-only",
    "includeOnScreenText": false,
    "quality": "fast",
    "language": "auto",
    "maximumVideoDurationSeconds": 300,
    "ocrFps": "1.5",
    "includeTranscriptSegments": true
};

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

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "videoUrls": ["https://www.tiktok.com/@duolingo/video/7683994892506270989"],
    "profiles": ["@duolingo"],
    "resultsLimitPerProfile": 10,
    "transcriptionMode": "ai-only",
    "includeOnScreenText": False,
    "quality": "fast",
    "language": "auto",
    "maximumVideoDurationSeconds": 300,
    "ocrFps": "1.5",
    "includeTranscriptSegments": True,
}

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

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

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

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.tiktok.com/@duolingo/video/7683994892506270989"
  ],
  "profiles": [
    "@duolingo"
  ],
  "resultsLimitPerProfile": 10,
  "transcriptionMode": "ai-only",
  "includeOnScreenText": false,
  "quality": "fast",
  "language": "auto",
  "maximumVideoDurationSeconds": 300,
  "ocrFps": "1.5",
  "includeTranscriptSegments": true
}' |
apify call lergassy/tiktok-reels-shorts-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/tiktok-reels-shorts-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/v4rqQsnYN6uuGjWI0/builds/8aIHzwdQnsD8pU1ap/openapi.json
