# YouTube Transcript Scraper & New Videos Monitor (`babymum7/youtube-transcript-monitor`) Actor

Get YouTube transcripts from videos, channels and playlists with timestamps and details. On a schedule, pay only for new videos.

- **URL**: https://apify.com/babymum7/youtube-transcript-monitor.md
- **Developed by:** [Trong Nguyen](https://apify.com/babymum7) (community)
- **Categories:** Videos, Social media, AI
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 transcripts

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 Transcript Scraper & New Videos Monitor

Get the transcript of any YouTube video, or of every new video on the channels you follow. Paste video, channel or playlist links, put it on a schedule, and each run returns only the videos uploaded since the last one, each with its full transcript, timestamps, title, publish date and view count.

Most YouTube transcript scrapers take one video link at a time. That is fine for a single video. Following ten channels for a newsletter, a research feed or an AI summary bot means finding the new uploads yourself every morning. This one does that part. The first run reads each channel's newest videos and remembers them. After that, a quiet day returns nothing and costs nothing, and an upload day returns just the new video.

### Who uses it

- **AI and automation builders** feed new videos from a list of channels into a summary, a newsletter or a RAG index, every day, without a video list to maintain.
- **Researchers and analysts** pull the transcripts of a whole channel or playlist into one table for search, quotes or text analysis.
- **Marketers and creators** follow what competitors and the leaders in their niche are saying, and turn talks into posts.
- **Students and teams** get the text of lectures, podcasts and webinars with timestamps to quote from.

### Why monitor instead of re-scraping

Following 10 channels every day, 20 recent videos each, at the same price per transcript:

| | Re-scrape the channels daily | This Actor |
| --- | --- | --- |
| Transcripts you pay for each day | 200 | Only the new videos |
| Cost over 30 days | about $9 | $0.30 for the baseline, then cents (3 new videos a day comes to $0.14) |
| What changed today | You compare the lists yourself | Every row is new, marked `isNew: true` |

### What you get

- The full transcript of each video as one text, plus every caption line with its start time and duration in seconds
- The uploader's own captions when there are some, YouTube's automatic captions when there are not, in the language you ask for when the video has it
- Title, channel, publish date and time (UTC), duration, view count and description of each video
- Every caption language the video has, and whether the transcript is automatic
- A clear status for videos without a transcript: no captions, private or removed, a premiere that has not started yet
- Results in JSON, CSV, Excel or HTML, through the API, or sent on to Slack, Google Sheets, Make, Zapier or n8n

### How to get YouTube transcripts

1. In **Videos, channels or playlists**, paste links: `https://www.youtube.com/watch?v=...`, `youtu.be/...`, a Shorts link, a channel (`@mkbhd` or its URL) or a playlist (`...playlist?list=...`). Mix them freely.
2. Pick the **Transcript language** (English by default).
3. Click **Start**. Videos come back with their transcripts. Channels and playlists return their newest videos and are saved as your baseline.
4. Add a daily schedule. From now on each run returns only the new uploads of your channels.

### Examples

#### 1. A daily feed of new videos from the channels you follow

```json
{
  "urls": ["https://www.youtube.com/@veritasium", "https://www.youtube.com/@3blue1brown", "https://www.youtube.com/@kurzgesagt"],
  "maxVideosPerChannel": 10,
  "onlyNewVideos": true
}
```

Schedule it daily and connect the dataset to Make, Zapier or n8n: each new row is a new video with its transcript, ready for a summary or a Slack post.

#### 2. Export a whole playlist once

```json
{
  "urls": ["https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab"],
  "maxVideosPerChannel": 500,
  "onlyNewVideos": false,
  "includeTimestamps": true
}
```

#### 3. Call it from your own code

```bash
curl -X POST "https://api.apify.com/v2/acts/babymum7~youtube-transcript-monitor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"], "language": "en"}'
```

That request waits up to 5 minutes, enough for a few hundred videos. For bigger runs use the Python client, which waits as long as the run takes:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("babymum7/youtube-transcript-monitor").call(run_input={
    "urls": ["https://www.youtube.com/@mkbhd"],
    "maxVideosPerChannel": 50,
})
for video in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(video["title"], len(video["transcript"] or ""))
```

#### What it costs

| Run | Transcripts | Cost |
| --- | --- | --- |
| One video | 1 | $0.0015 |
| First run on 10 channels, 20 videos each | 200 | $0.30 |
| A daily run that finds 3 new videos | 3 | $0.0045 |

A run of 40 channel videos took about a minute in our tests; a handful of videos takes under 30 seconds.

### Input reference

| Field | What it does |
| --- | --- |
| `urls` | Video, Shorts, live, channel or playlist links, @handles, or bare video, channel and playlist IDs |
| `language` | Two-letter code such as `en`, `es` or `de`. Uploader captions in it first, then automatic ones, else the video's main language |
| `maxVideosPerChannel` | Newest videos read from each channel or playlist on the first run (default 20) |
| `onlyNewVideos` | On (default): later runs return only videos uploaded since. Off: the newest videos every run, without changing the memory a scheduled run uses |
| `includeTimestamps` | Adds `segments`, each caption line with its start and duration (default on) |
| `proxyConfiguration` | Leave the default; blocked requests are retried on residential IPs at no extra cost to you |

Channels are read from their Videos tab. Shorts and past live streams on a channel are not listed there; paste their links directly to get their transcripts.

### Output example

```json
{
  "isNew": true,
  "source": "https://www.youtube.com/@mkbhd",
  "videoId": "g6Die8gVFn0",
  "url": "https://www.youtube.com/watch?v=g6Die8gVFn0",
  "title": "OLED iPad Mini is The Most Apple Product They've Ever Appled",
  "channelName": "Marques Brownlee",
  "channelId": "UCBJycsmduvYEL83R_U4JriQ",
  "channelUrl": "https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ",
  "publishedAt": "2026-11-03T14:01:31Z",
  "durationSeconds": 779,
  "viewCount": 5339113,
  "description": "iPad Mini 8 Refresh gets a big refresh and a big price bump...",
  "status": "ok",
  "statusReason": null,
  "language": "en",
  "languageName": "English",
  "isAutoGenerated": false,
  "availableLanguages": ["en", "ja", "pt", "ru", "tr", "vi"],
  "transcript": "Okay, so Apple finally updates the iPad Mini. We've been waiting years for this...",
  "segments": [
    {"start": 5.25, "duration": 2.042, "text": "Okay, so Apple finally updates the iPad Mini."},
    {"start": 7.374, "duration": 1.585, "text": "We've been waiting years for this..."}
  ]
}
```

### How "new" is decided

Each channel or playlist in your input keeps its own memory of the videos it has returned. The first run is the baseline: it returns the newest videos with `isNew: false`. Later runs list the channel again, skip every video already returned, and read only the rest. A brand-new upload that YouTube has not captioned yet (automatic captions can take a few hours) is not returned and not remembered: it comes back with its transcript on a later run. Video links you paste are returned every run.

### Pricing

$1.50 per 1,000 transcripts, and nothing else to pay for: no start fee and no charge for compute or proxies. Videos without a transcript are listed with their reason and cost nothing. Paid Apify plans get the same transcripts for less:

| Apify plan | Per 1,000 transcripts |
| --- | --- |
| Free | $1.50 |
| Starter (Bronze) | $1.20 |
| Scale (Silver) | $1.00 |
| Business (Gold) and up | $0.80 |

If one channel fails, the run says so in its status and in the `SUMMARY` record and carries on with the rest.

### FAQ

**How do I get the transcript of a YouTube video?**
Paste the video link in Videos, channels or playlists and click Start. The transcript comes back as one text, with every caption line and its timestamp alongside.

**Can I get the transcripts of a whole YouTube channel?**
Yes. Paste the channel link or @handle and raise Videos per channel or playlist to the number you want, up to 5,000.

**Does it work for videos without uploaded subtitles?**
Yes, when YouTube has made automatic captions, which it does for most videos with speech. `isAutoGenerated` tells you which kind you got. Videos with no captions at all are listed with status `no_captions` and are free.

**Can I get the transcript in another language?**
Set Transcript language. If the video has captions in it, from the uploader or automatic, you get those; if not, you get the video's main language, and `availableLanguages` lists what it has.

**Does it download the video or audio?**
No. It reads the captions YouTube already publishes, which is why it is fast and cheap.

**Can I use it for Shorts and live streams?**
Yes, paste their links. Live streams have a transcript once they have ended and YouTube has captioned them.

**How do I get new videos from a channel automatically?**
Keep Only new videos on and add a schedule in Apify (daily is typical). Each run returns only the videos uploaded since the last one.

# Actor input Schema

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

Paste YouTube links, one per line: a video (watch, youtu.be, Shorts or live link), a channel (@handle or its URL) or a playlist. Mix them freely, as many as you like.

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

Two-letter language code. The uploader's captions in this language come first, then YouTube's automatic ones in it. A video without captions in this language returns its main language instead, so you never get an empty row by accident.

## `maxVideosPerChannel` (type: `integer`):

How many of the newest videos to read from each channel or playlist on the first run. Later runs with Only new videos on read just the uploads since. Raise it to export a whole channel.

## `onlyNewVideos` (type: `boolean`):

On: the first run reads each channel's newest videos and remembers them, and every run after that returns only videos uploaded since. Ideal on a daily schedule. Off: every run returns the newest videos again, and the memory a scheduled run relies on is left as it is. Video links you paste are always returned.

## `includeTimestamps` (type: `boolean`):

Adds each caption line with its start time and duration in seconds, for subtitles, chapters or quoting. The full text is always in the transcript field.

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

YouTube asks many datacenter IPs to sign in; when that happens the video is retried on a residential IP at no extra cost to you. The default works for most runs.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/@mkbhd",
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "language": "en",
  "maxVideosPerChannel": 5,
  "onlyNewVideos": true,
  "includeTimestamps": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `transcripts` (type: `string`):

No description

## `summary` (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 = {
    "urls": [
        "https://www.youtube.com/@mkbhd",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw"
    ],
    "maxVideosPerChannel": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("babymum7/youtube-transcript-monitor").call(input);

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "urls": [
        "https://www.youtube.com/@mkbhd",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    ],
    "maxVideosPerChannel": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("babymum7/youtube-transcript-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.youtube.com/@mkbhd",
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "maxVideosPerChannel": 5
}' |
apify call babymum7/youtube-transcript-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,babymum7/youtube-transcript-monitor"
        }
    }
}
```

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/v61hPLbrr47xUrcbT/builds/FOUSs5UQI12rrxkc8/openapi.json
