# Youtube Text, AI & Metadata Scraper (`ilborso/youtube-text-scraper`) Actor

Extract YouTube transcripts, AI summary, subtitles, video metadata, hashtags, thumbnails, views, duration, and release dates from YouTube videos using either a search query or a list of direct YouTube URLs. It helps you turn YouTube search results and specific video links into structured JSON data

- **URL**: https://apify.com/ilborso/youtube-text-scraper.md
- **Developed by:** [Fabio Borsotti](https://apify.com/ilborso) (community)
- **Categories:** AI, Lead generation, Developer tools
- **Features:** Limited permissions
- **Stats:** 42 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Actor

Extract YouTube transcripts, AI summary, subtitles, video metadata, hashtags, thumbnails, views, duration, and release dates from YouTube videos using either a search query or a list of direct YouTube URLs. This YouTube transcript scraper helps you turn YouTube search results and specific video links into structured JSON data for research, SEO, lead generation, monitoring, and content analysis.

### What does YouTube Transcript Scraper do?

YouTube Transcript Scraper is an APIFY Actor that can search YouTube videos by keyword, apply a time filter, collect video metadata, and retrieve the first available transcript based on your preferred language order. It can also process direct YouTube video URLs and include those videos in the final output.

This Actor is ideal if you want to:

- train RAG algorithms for AI
- scrape YouTube transcripts
- extract YouTube subtitles
- collect YouTube video metadata
- monitor YouTube search results
- build datasets from YouTube videos
- automate YouTube content research
- extract transcripts from specific YouTube videos

### Why use this YouTube scraper?

If you work with YouTube data, transcripts are one of the most valuable sources of structured content. Video transcripts help you analyze what creators actually say, not just what appears in titles and descriptions.

This Actor is useful because it supports two collection modes in the same run:

- search by keyword using `query`
- direct processing of specific YouTube videos using `direct_url`

This makes it practical both for broad monitoring and for targeted transcript extraction from known videos.

#### Common use cases

- SEO research for YouTube videos and keywords
- competitor monitoring on YouTube
- AI training and text dataset preparation
- content repurposing from video to text
- lead generation from niche YouTube channels
- trend monitoring by date range
- transcript-based topic clustering
- YouTube video catalog enrichment
- transcript extraction from manually selected videos

### What data does the Actor extract?

For each processed YouTube video, the Actor can return:

- YouTube video ID
- video title
- video URL
- channel name
- channel URL
- transcript text with timestamps
- available subtitles metadata
- video view count
- video duration in seconds
- release date
- thumbnail URL
- keywords / hashtags
- likes count
- comments count
- video description
- video categories
- live stream indicator
- geographical availability
- video language
- chapters (if available)
- series, season, and episode information

**Note:** By default, the Actor extracts transcript only and returns empty values for metadata fields. To include video metadata and subtitles, set `enableMetadata: true` in the input. See the "Metadata Retrieval Strategy" section for details.

#### Output Fields Reference

| Field | Type | Description | Availability |
|-------|------|-------------|--------------|
| `id` | string | YouTube video ID | Always |
| `title` | string | Video title (short form) | Always |
| `url` | string | YouTube video watch URL | Always |
| `autor` | string | Channel/creator name (from search) | Always |
| `text` | string | Video transcript with timestamps in format \[MM:SS] | Always if available. It uses before list languages specified. If not available get the first language available in subtitle list |
| `channel_name` | string | Channel/uploader name | With enableMetadata = true |
| `channel_url` | string | URL to the channel page | With enableMetadata = true |
| `video_title` | string | Full video title | With enableMetadata = true |
| `video_url` | string | YouTube video URL | With enableMetadata = true |
| `views_count` | integer | Total number of video views | With enableMetadata = true |
| `duration_seconds` | integer | Video duration in seconds | With enableMetadata = true |
| `release_date` | string | Video publish date in format YYYY-MM-DD | With enableMetadata = true |
| `thumbnail_url` | string | URL to the video thumbnail image | With enableMetadata = true |
| `hashtags` | array | Hashtags associated with the video | With enableMetadata = true |
| `like_count` | integer | Number of likes on the video | With enableMetadata = true |
| `comment_count` | integer | Number of comments on the video | With enableMetadata = true |
| `description` | string | Full video description text | With enableMetadata = true |
| `keywords` | array | Keywords associated with the video | With enableMetadata = true |
| `categories` | array | Video categories/topics | With enableMetadata = true |
| `is_live` | boolean | Whether the video is a live stream | With enableMetadata = true |
| `availability` | string | Geographical availability status | With enableMetadata = true |
| `language` | string | Primary language code of the video | With enableMetadata = true |
| `chapters` | array | Chapter markers with timestamps (if available) | With enableMetadata = true |
| `series` | string | Series name if video is part of a series | With enableMetadata = true |
| `season` | integer | Season number if video is part of a series | With enableMetadata = true |
| `episode` | integer | Episode number if video is part of a series | With enableMetadata = true |
| `subtitles` | array | Available subtitle/transcript languages with metadata | With enableMetadata = true |
| `summary` | string | AI-generated summary of the video transcript using Gemini flash lite (always the latest version). | With summarize = true |

### Why this Actor is useful

This YouTube Transcript Scraper is useful when you need structured YouTube data without building and maintaining your own scraping workflow. It is designed for users who want fast access to transcript-rich video data in a reusable JSON format.

Compared with a basic YouTube metadata scraper, this Actor focuses on transcript extraction and subtitle discovery, which makes it especially helpful for:

- content intelligence
- SEO workflows
- machine learning pipelines
- research automation
- enrichment of video datasets

### Input

#### Metadata Retrieval Strategy (`enableMetadata` flag)

By default, the Actor extracts **transcripts only** for optimal performance and minimal proxy credit consumption.

However, you can enable comprehensive metadata retrieval by setting `enableMetadata: true`:

- **`enableMetadata: false` (default)**: Fast, low-credit mode
  - Extracts: transcript text + video URL
  - Output fields for metadata are present but empty (`None`, `[]`)
  - Recommended for large-scale transcript extraction

- **`enableMetadata: true`**: Full metadata mode
  - Extracts: transcript + video metadata + available subtitles
  - Metadata fields populated: channel name/URL, view count, duration, release date, thumbnail, hashtags
  - Subtitles field includes full list of available subtitle languages
  - Useful for comprehensive video data collection

When `enableMetadata: true`, the Actor emits a single `metadata-enabled` event per run to notify external systems.

##### Example: Enabling metadata

```json
{
  "query": "apify tutorial",
  "limit": 5,
  "langs": ["it", "en"],
  "enableMetadata": true,
  "file_output": "output.json"
}
```

#### Supported input fields

- `direct_url` (array of strings, optional): list of direct YouTube video URLs to process. Supported formats include `youtube.com/watch?v=...`, `youtu.be/...`, and `youtube.com/shorts/...`
- `query` (string, optional): YouTube search query. Optional if `direct_url` is provided
- `range` (array of strings): time filter for YouTube search, one of `hour`, `today`, `this_week`, `this_month`, `this_year`
- `limit` (integer): maximum number of videos to process from search results
- `langs` (array of strings): preferred language order used when selecting transcripts (see table before)
- `file_output` (string): name of the JSON file saved in the key-value store
- `enableMetadata` (boolean, optional): if `true`, fetches video metadata and subtitles; if `false` or omitted, extracts transcript only (default: `false`)
- `summarize` (boolean, optional): if `true`, summarizes video transcript using Gemini Flash Lite (always the latest) into output field `summary` (default: `false`)
- `max_words` (integer, optional): maximum word count of the generated AI summary (default: `300`)

#### AI Summarization Strategy (`summarize` and `max_words` flags)

When `summarize: true`, the Actor uses the `google.genai` library to call Google Gemini service to summarize each video's transcript.

- **Environment Variables**:
  - `GEMINI_KEY`: API key for accessing Gemini AI service
  - `MODEL`: Gemini model name (default: `gemini-flash-lite-latest`)
  - `AI_SUMMARIZE_PROMPT`: Custom prompt template for Gemini summarization (default: `"Summarize the following YouTube video transcript in maximum {max_words} words:\n\n{text}"`)
  - `PARALLEL`: Concurrency limit for parallel summarization of video transcripts

- **Event Emission**:
  When `summarize: true`, after saving the dataset and key-value store output, the Actor iterates through the output items and emits an `ai-enabled` Apify event for each returned video.

##### Example: Enabling AI Summarization

```json
{
  "query": "apify tutorial",
  "limit": 5,
  "langs": ["it", "en"],
  "summarize": true,
  "max_words": 300,
  "file_output": "output.json"
}
```

At least one between `query` and `direct_url` must be provided.

#### Supported languages (iso ISO 639-1)

| Codice | Lingua            | Codice | Lingua           | Codice | Lingua         | Codice | Lingua      | Codice | Lingua          | Codice | Lingua     |
| ------ | ----------------- | ------ | ---------------- | ------ | -------------- | ------ | ----------- | ------ | --------------- | ------ | ---------- |
| aa     | Afar              | ab     | Abkhaz           | ae     | Avestan        | af     | Afrikaans   | ak     | Akan            | am     | Amharic    |
| ar     | Arabic            | as     | Assamese         | av     | Avaric         | ay     | Aymara      | az     | Azerbaijani     | ba     | Bashkir    |
| be     | Belarusian        | bg     | Bulgarian        | bi     | Bislama        | bm     | Bambara     | bn     | Bengali         | bo     | Tibetan    |
| br     | Breton            | bs     | Bosnian          | ca     | Catalan        | ce     | Chechen     | ch     | Chamorro        | co     | Corsican   |
| cr     | Cree              | cs     | Czech            | cu     | Church Slavic  | cv     | Chuvash     | cy     | Welsh           | da     | Danish     |
| de     | German            | dv     | Divehi           | dz     | Dzongkha       | ee     | Ewe         | el     | Greek           | en     | English    |
| eo     | Esperanto         | es     | Spanish          | et     | Estonian       | eu     | Basque      | fa     | Persian         | ff     | Fulah      |
| fi     | Finnish           | fj     | Fijian           | fo     | Faroese        | fr     | French      | fy     | Western Frisian | ga     | Irish      |
| gd     | Scottish Gaelic   | gl     | Galician         | gn     | Guarani        | gu     | Gujarati    | gv     | Manx            | ha     | Hausa      |
| he     | Hebrew            | hi     | Hindi            | ho     | Hiri Motu      | hr     | Croatian    | ht     | Haitian         | hu     | Hungarian  |
| hy     | Armenian          | hz     | Herero           | ia     | Interlingua    | id     | Indonesian  | ie     | Interlingue     | ig     | Igbo       |
| ii     | Sichuan Yi        | ik     | Inupiaq          | io     | Ido            | is     | Icelandic   | it     | Italian         | iu     | Inuktitut  |
| ja     | Japanese          | jv     | Javanese         | ka     | Georgian       | kg     | Kongo       | ki     | Kikuyu          | kj     | Kuanyama   |
| kk     | Kazakh            | kl     | Kalaallisut      | km     | Central Khmer  | kn     | Kannada     | ko     | Korean          | kr     | Kanuri     |
| ks     | Kashmiri          | ku     | Kurdish          | kv     | Komi           | kw     | Cornish     | ky     | Kirghiz         | la     | Latin      |
| lb     | Luxembourgish     | lg     | Ganda            | li     | Limburgan      | ln     | Lingala     | lo     | Lao             | lt     | Lithuanian |
| lu     | Luba-Katanga      | lv     | Latvian          | mg     | Malagasy       | mh     | Marshallese | mi     | Maori           | mk     | Macedonian |
| ml     | Malayalam         | mn     | Mongolian        | mr     | Marathi        | ms     | Malay       | mt     | Maltese         | my     | Burmese    |
| na     | Nauru             | nb     | Norwegian Bokmål | nd     | North Ndebele  | ne     | Nepali      | ng     | Ndonga          | nl     | Dutch      |
| nn     | Norwegian Nynorsk | no     | Norwegian        | nr     | South Ndebele  | nv     | Navajo      | ny     | Chichewa        | oc     | Occitan    |
| oj     | Ojibwa            | om     | Oromo            | or     | Oriya          | os     | Ossetian    | pa     | Panjabi         | pi     | Pali       |
| pl     | Polish            | ps     | Pashto           | pt     | Portuguese     | qu     | Quechua     | rm     | Romansh         | rn     | Rundi      |
| ro     | Romanian          | ru     | Russian          | rw     | Kinyarwanda    | sa     | Sanskrit    | sc     | Sardinian       | sd     | Sindhi     |
| se     | Northern Sami     | sg     | Sango            | sh     | Serbo-Croatian | si     | Sinhala     | sk     | Slovak          | sl     | Slovenian  |
| sm     | Samoan            | sn     | Shona            | so     | Somali         | sq     | Albanian    | sr     | Serbian         | ss     | Swati      |
| st     | Southern Sotho    | su     | Sundanese        | sv     | Swedish        | sw     | Swahili     | ta     | Tamil           | te     | Telugu     |
| tg     | Tajik             | th     | Thai             | ti     | Tigrinya       | tk     | Turkmen     | tl     | Tagalog         | tn     | Tswana     |
| to     | Tonga             | tr     | Turkish          | ts     | Tsonga         | tt     | Tatar       | tw     | Twi             | ty     | Tahitian   |
| ug     | Uighur            | uk     | Ukrainian        | ur     | Urdu           | uz     | Uzbek       | ve     | Venda           | vi     | Vietnamese |
| vo     | Volapük           | wa     | Walloon          | wo     | Wolof          | xh     | Xhosa       | yi     | Yiddish         | yo     | Yoruba     |
| za     | Zhuang            | zh     | Chinese          | zu     | Zulu           |        |             |        |                 |        |            |

#### Example input with direct URLs only

```json
{
  "direct_url": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/9bZkp7q19f0"
  ],
  "langs": ["it", "en"],
  "file_output": "output.json"
}
```

#### Example input with query and direct URLs

```json
{
  "direct_url": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "query": "apify tutorial",
  "range": ["this_week"],
  "limit": 5,
  "langs": ["it", "en"],
  "file_output": "output.json"
}
```

#### Example input with direct URLs only and enableMetadata = true

```json
{
  "direct_url": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/9bZkp7q19f0"
  ],
  "langs": ["it", "en"],
  "enableMetadata": true,
  "file_output": "output.json"
}
```

#### Example input with query, enableMetadata = true & summarize = true

```json
{
    "enableMetadata": true,
    "file_output": "output.json",
    "langs": [
        "en"
    ],
    "limit": 1,
    "max_words": 300,
    "query": "weather forecast new york",
    "range": [
        "today"
    ],
    "summarize": true
}
```

When both `direct_url` and `query` are provided, all videos listed in `direct_url` are processed and added to the output together with the search results. When `enableMetadata` is set to `true`, the Actor will fetch comprehensive metadata and available subtitles for each video and emit an `apify-actor-metadata` event upon completion.

### Output

Each dataset item contains structured YouTube transcript, metadata & AI summary fields like these:

```json
[
  {
    "id": "7mn-Slhcwkg",
    "title": "Nor'easter impacting Tri-State Area | 12:15 p.m. Sunday update",
    "url": "https://www.youtube.com/watch?v=7mn-Slhcwkg",
    "autor": null,
    "text": "[00:01] This is a First Alert Weather Special\n[00:04] Report.\n[00:05] >> Hey, good afternoon. It's uh 12:18. Hope\n[00:07] you enjoyed the uh point with Marsha\n[00:09] Kramer. I love that show. Um uh weather\n[00:11] show, I I don't know if anybody loves\n[00:15] this. It's so dreary. I love this shot,\n[00:17] but we could because we're talking about\n[00:18] like the a low [music] cloud deck. There\n[00:20] it is. Uh it's like we're playing with\n[00:22] half a deck. It's just dreary out there.\n[00:25] And then we're going to I'm just going\n[00:26] to show you here's another picture. So,\n[00:27] here's a camera that we positioned in\n[00:29] Where is the city? Where is the city? Uh\n[00:32] murky out there. And\n[00:34] >> [laughter]\n[00:34] >> it's still 62°. It's been 62°\n[00:38] for about 4 hours. Winds are gusting at\n[00:40] 32. That's a change. We'll talk about\n[00:42] that in just a minute. By the way,\n[00:44] thanks for spending some time with us\n[00:45] here on CBS News New York. Uh\n[00:48] visibility, uh we don't have any dense\n[00:49] fog advisories or anything like that.\n[00:51] Just was talking with our friends on the\n[00:53] desk and uh LaGuardia is still really\n[00:55] struggling. It's of our big three, it's\n[00:57] the one that's hurting the the the most.\n[00:59] Look at the Teterboro, it just went up\n[01:00] as far as visibility. They had a a\n[01:03] 59-minute ground delay due to visibility\n[01:05] earlier. Then there was a ground stop.\n[01:07] Now they're back to a delay. And it's\n[01:09] wind and visibility there. So, yeah, I\n[01:12] mean, you it's going to be challenging,\n[01:15] certainly not impossible. You're going\n[01:16] to get into a situation where it's just\n[01:18] a matter of making sure the planes are\n[01:20] there if we see major delays, but JFK\n[01:22] and Newark right now, okay. 62 in the\n[01:25] city and not that much warmer anywhere\n[01:27] else except out on the island. You have\n[01:29] that wind, and so we're actually that's\n[01:32] probably going to be the warm spot uh\n[01:34] for the afternoon. Now, the wind. Wind\n[01:36] is very important. You get a sense of\n[01:38] where the center of the low is. So, it's\n[01:40] come on board. It actually will make\n[01:42] another turn, and then it weakens, and\n[01:46] that's not until Monday. So, we are\n[01:48] stuck with this thing. Watch these winds\n[01:50] now stronger for parts of the Jersey\n[01:52] shore, and not as bad out on the East\n[01:54] End. Now, this is where we saw the 50s\n[01:56] and 60s. Those that wind is over. Here's\n[01:59] another snapshot. This is a composite\n[02:01] radar\n[02:03] and satellite. Look at this. The bands\n[02:05] stretch from almost, you know, the\n[02:07] border all the way down to the Delmarva.\n[02:11] So, it this is a big system, very well\n[02:14] organized, too. In the city, uh this\n[02:16] little batch is filling in right now.\n[02:18] We're on the west side and it's coming\n[02:19] down again. It's better in Queens right\n[02:21] now than it is in Manhattan or the\n[02:22] Bronx. And then over the sound into\n[02:24] parts of Westchester and Fairfield, it's\n[02:26] just showers. It's just dreary. I mean,\n[02:28] it's like the wipers can't make up their\n[02:30] mind. Are they on or are they on\n[02:32] intermittent? This heavier rain is to\n[02:34] our south, but this is what's going to\n[02:36] fill in. I was just talking to uh one of\n[02:39] my colleagues and friends on the desk\n[02:41] leaving the city at 4:00 to head out to\n[02:43] the island. Well, the concern is some of\n[02:45] this rain shield will fill in. So, let's\n[02:48] dive ahead. So, just uh setting this\n[02:50] ahead about an hour or so. Let let let\n[02:53] let let check on my times here. Um\n[02:55] this means it's probably a little wet at\n[02:57] Yankee Stadium, maybe okay uh for the\n[03:00] Giants, but there there'll be on again,\n[03:02] off again showers during the course of\n[03:04] both games. But, we're talking showers.\n[03:07] We don't see any convection with this,\n[03:08] so there's no lightning risk or anything\n[03:10] like that. I mean, I know the NFL's got\n[03:12] a different standard than the MLB, but\n[03:15] it's just going to be kind of gray and\n[03:16] wet at times. Now, games are over, but\n[03:19] you've got places to go. Here comes that\n[03:22] shield that that that leading edge of\n[03:24] that impulse that we showed you. So,\n[03:26] this is a pretty good estimate. Maybe\n[03:29] it'll verify a little farther to the\n[03:31] east, but this comes on board between\n[03:33] 5:00 and say 8:00 or 9:00 with pockets\n[03:36] of heavier rain. So, if you're wrapping\n[03:38] up a weekend trip or going out for the\n[03:40] evening, dinner tonight in Brooklyn,\n[03:42] yeah, anywhere, it's going to be a\n[03:43] little wet. And see how this takes over\n[03:45] tonight. So, Vanessa's coming in this\n[03:47] afternoon. She'll be watching this and\n[03:49] she'll take care of you on the the side\n[03:50] tonight. But, you're going to see more\n[03:52] rain falling a man right through Monday\n[03:54] morning. Early commuters,\n[03:56] yeah, have the rain gear ready and you\n[03:58] might need it coming and going. So, this\n[04:00] is for the kids. It's going to be wet\n[04:02] not for everybody in Jersey, but for the\n[04:03] city kids up in the Westchester, it's\n[04:06] still wet and then poof.\n[04:08] Lunchtime, dining outside. Well, if\n[04:10] you're a duck,\n[04:12] um look at that. There's more rain in\n[04:14] the parts of Connecticut. See there it\n[04:15] is. See what happened? It came here,\n[04:18] backed out, it wobbles a bit, then it\n[04:20] takes off. And so, it's not all the way\n[04:22] until\n[04:24] wow, Tuesday morning before we start to\n[04:26] see a break in this thing start to clear\n[04:28] out. So, just real quickly we're\n[04:31] updating this. Woah, now we're at 375\n[04:33] for Toms River. And if that makes its\n[04:35] way around, I mean, we could add another\n[04:37] inch to that. So, I do think we'll\n[04:39] pretty confident that there'll be a lot\n[04:41] of threes up to fives for totals for\n[04:44] this. The concern, even though the winds\n[04:46] are subsiding, is you still are dealing\n[04:48] with vulnerable trees. So, just be on\n[04:50] your game right now. I want to make sure\n[04:51] that everybody's ready for that. That's\n[04:53] why it's a first alert weather day\n[04:54] today. Just the heads-up too for Monday.\n[04:57] If you have a flight early tomorrow\n[04:58] morning or someplace you absolutely\n[05:00] positively have to be, have to factor in\n[05:02] extra time tomorrow morning. There's\n[05:04] going to be cleanup going on too. And\n[05:06] there's a better day for that. Tuesday,\n[05:08] Wednesday, Thursday of next week looks\n[05:10] so much better. It is getting better. I\n[05:13] mean, we're through with the worst of\n[05:15] this, but be mindful that there's still\n[05:17] rain. It's still going to slow you down\n[05:19] as you're heading out there and we're\n[05:20] not done with all of the heavy rain just\n[05:22] yet. So, that's why we're not done here.\n[05:24] We'll be back around 1:00 with another\n[05:26] update right here on CBS News New York.\n[05:31] >> This has been a first alert weather\n[05:33] special report.",
    "summary": "This First Alert Weather Special reports a large, well-organized low-pressure system bringing dreary, wet conditions, gusty winds, and flight delays to the New York area. Rain will persist through Monday, with total accumulations potentially reaching 3 to 5 inches, before finally clearing by Tuesday.",
    "channel_name": "CBS New York",
    "channel_url": "https://www.youtube.com/channel/UCNZyLULUQBp5e9Q1cKtvk6Q",
    "video_title": "Nor'easter impacting Tri-State Area | 12:15 p.m. Sunday update",
    "video_url": "https://www.youtube.com/watch?v=7mn-Slhcwkg",
    "views_count": 18170,
    "duration_seconds": 338,
    "release_date": "2026-09-27",
    "thumbnail_url": "https://i.ytimg.com/vi/7mn-Slhcwkg/maxresdefault.jpg",
    "hashtags": [
      "CBSN New York",
      "CBS News New York",
      "John Elliott",
      "First Alert Weather",
      "Nor'easter",
      "New York",
      "Local TV"
    ],
    "like_count": 126,
    "comment_count": 17,
    "description": "CBS News New York's John Elliott has a look at the First Alert Weather forecast. \n\nFor video licensing inquiries, contact: licensing@veritone.com",
    "keywords": [],
    "categories": [
      "News & Politics"
    ],
    "is_live": false,
    "availability": "public",
    "language": "en",
    "chapters": [],
    "series": null,
    "season": null,
    "episode": null,
    "subtitles": [
      {
        "language_code": "en",
        "language": "English (auto-generated)",
        "is_generated": true,
        "is_translatable": true
      }
    ]
  }
]
```

The Actor also saves the complete output array into the APIFY key-value store using the file name specified in `file_output`.

### How the YouTube transcript extraction works

The Actor follows this strategy:

1. If `direct_url` is provided, process each direct YouTube URL and extract transcript and metadata.
2. If `query` is provided, search YouTube videos using the selected time filter.
3. For each video, try to find a manually created transcript in the languages you requested.
4. If no manual transcript is available, try an auto-generated transcript.
5. If no requested language is available, fall back to the first available transcript.
6. Save transcript text and structured metadata in the output dataset.

This makes the Actor practical for multilingual transcript scraping, targeted video extraction, and broad topic monitoring.

### Who is this Actor for?

This Actor is a good fit for:

- SEO specialists
- marketers
- data engineers
- content analysts
- AI data learning teams
- researchers
- agencies monitoring YouTube niches
- users who need transcripts from specific YouTube links

### Limitations

The actor has the following limitations:

- **Public videos only**: Private or restricted videos are not supported.
- **Transcripts required**: The Actor can only extract data from videos that have transcripts enabled.
- **Age-gated videos not supported**: Videos marked as age-restricted (18+, 14+, etc.) cannot be accessed without YouTube account authentication. The Actor will return empty metadata and transcript for age-gated videos because YouTube blocks unauthenticated access to these videos for protection purposes.

To work with age-gated videos, you would need to implement YouTube account authentication, which is not currently supported by this Actor.

### Summary

If you need a YouTube transcript scraper for APIFY that extracts subtitles, transcript text, hashtags, thumbnails, views, duration, and release date from either search results or direct video URLs, this Actor gives you a clean starting point with structured JSON output and proxy support.

### Related Actors

Need full YouTube search result pages, channel details, playlists, Shorts, or sponsored ads data?

Check out **[YouTube Scraper API](https://apify.com/ilborso/youtube-scraper-api)**:

- **Comprehensive SERP Scraping**: Extracts videos, channel profiles, playlists, Shorts shelves, sponsored ads, and search refinement keywords.
- **Flat JSON for CSV & Excel**: Always-present columns designed specifically for seamless export to CSV and Excel.
- **Advanced Filtering & Sorting**: Filter by result type, video duration, 4K/HD/features, upload date, and sort by relevance, view count, or rating.
- **Localization**: Full control over interface language (`hl`) and country code (`gl`) for localized ranking and text.

Pair **[YouTube Scraper API](https://apify.com/ilborso/youtube-scraper-api)** with **YouTube Transcript Scraper** for an end-to-end YouTube intelligence and content analysis workflow!

# Changelog

This Actor's version history is a separate document: https://apify.com/ilborso/youtube-text-scraper/changelog.md

# Actor input Schema

## `direct_url` (type: `array`):

List of direct YouTube URLs to download the transcript from. Each URL can be in the format youtube.com/watch?v=..., youtu.be/..., or youtube.com/shorts/.... The specified videos are always added to the output, regardless of the query.

## `query` (type: `string`):

YouTube search query. Optional if direct_url is specified.

## `range` (type: `array`):

Time filter to apply to YouTube searches. If multiple values ​​are provided, the first one will be used.

## `limit` (type: `integer`):

Maximum number of videos to analyze via search query

## `langs` (type: `array`):

Preferred languages ​​to retrieve the first available transcript.

## `file_output` (type: `string`):

Name of the JSON file to save to the key-value store.

## `enableMetadata` (type: `boolean`):

If true, also fetches video metadata and available subtitles. If false or omitted, actor behaves as before.

## `summarize` (type: `boolean`):

If true, uses latest Gemini Fast Lite LLM to summarize the transcript of each video into an output field named 'summary'.

## `max_words` (type: `integer`):

Maximum number of words for the AI summary (default = 300).

## Actor input object example

```json
{
  "direct_url": [
    "https://www.youtube.com/watch?v=XqsDoIjXDPk"
  ],
  "limit": 10,
  "langs": [
    "it",
    "en"
  ],
  "file_output": "output.json",
  "enableMetadata": false,
  "summarize": false,
  "max_words": 300
}
```

# 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 = {
    "direct_url": [
        "https://www.youtube.com/watch?v=XqsDoIjXDPk"
    ],
    "langs": [
        "it",
        "en"
    ],
    "file_output": "output.json"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ilborso/youtube-text-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 = {
    "direct_url": ["https://www.youtube.com/watch?v=XqsDoIjXDPk"],
    "langs": [
        "it",
        "en",
    ],
    "file_output": "output.json",
}

# Run the Actor and wait for it to finish
run = client.actor("ilborso/youtube-text-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 '{
  "direct_url": [
    "https://www.youtube.com/watch?v=XqsDoIjXDPk"
  ],
  "langs": [
    "it",
    "en"
  ],
  "file_output": "output.json"
}' |
apify call ilborso/youtube-text-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ilborso/youtube-text-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/ziYv81xR6O1r8CdD4/builds/ZJwK09MlGrVQWCXJX/openapi.json
