YouTube Transcript & Subtitle Scraper
Pricing
from $1.00 / 1,000 transcript fetcheds
YouTube Transcript & Subtitle Scraper
Extract transcripts and subtitles from YouTube videos in bulk using video, playlist, channel URLs, or keyword search. Returns timed transcript segments, plain text, SRT, and WebVTT subtitle files, with optional auto-translation to other languages.
Pricing
from $1.00 / 1,000 transcript fetcheds
Rating
0.0
(0)
Developer
AbotAPI
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
YouTube Transcript & Subtitles Scraper
Pull transcripts and subtitles for YouTube videos in bulk. Give it video URLs, playlist URLs, channel URLs, or just keywords to search YouTube, and it returns each video's transcript as timed segments, as plain text, and as ready-to-use SRT and WebVTT subtitle files. It can also auto-translate transcripts into another language.
Why this scraper
- Four ways in: direct video URLs or IDs, playlist URLs, channel URLs (
@handle,/channel/UC...,/c/...,/user/...), and keyword searches, all in one run. - Every output record carries the transcript three ways: timed
segments, a single plain-texttranscriptfield, andsrtplusvttstrings you can save straight to disk. - Language control: list your preferred languages in priority order, or translate the result into any language YouTube supports.
- Handles both human-written captions and auto-generated ones, and falls back to whatever the video offers when your preferred language is not available.
- Concurrent fetching with automatic connection rotation, so large playlists and channels move quickly.
- Per-source time windows: trim each video's transcript to a specific second range (and only pay for the trimmed text).
- Pay only for what you get: failed or captions-disabled videos are not billed.
Data you get
Per video (one dataset record). Values below are illustrative placeholders, not from a live video.
| Field | Example |
|---|---|
videoId | EXAMPLE_ID1 |
videoUrl | https://www.youtube.com/watch?v=EXAMPLE_ID1 |
videoTitle | Sample Video Title |
channelName | Sample Channel |
channelUrl | https://www.youtube.com/@SampleChannel |
durationSeconds | 213 |
source | python tutorial |
sourceType | search (one of video, playlist, channel, search) |
language | English |
languageCode | en |
isGenerated | false |
isTranslated | false |
translatedTo | null |
charCount | 5234 |
segmentCount | 142 |
transcript | "Hello and welcome to this sample transcript ..." |
segments | [{ "text": "Hello and welcome", "start": 0.0, "duration": 1.84 }, ...] |
srt | "1\n00:00:00,000 --> 00:00:01,840\nHello and welcome\n\n2\n..." |
vtt | "WEBVTT\n\n00:00:00.000 --> 00:00:01.840\nHello and welcome\n\n..." |
trimmedStart | 0 (start of the time window applied; 0 = no trim) |
trimmedDuration | 0 (length of the time window applied; 0 = no trim) |
success | true |
error | null (a short message when a transcript could not be fetched) |
How to use
Pick a mode:
mode: "url"readsvideoUrls(paste video, playlist, or channel URLs).mode: "search"readssearchQueries(find videos by keyword).
The other field is ignored. Optionally set startSec and durationSec to trim every video's transcript to the same time window (durationSec: 0 means "until end of video").
Fetch one video's transcript:
{"mode": "url","videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],"languages": ["en"],"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Several videos at once (URLs or bare IDs both work):
{"mode": "url","videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ","https://youtu.be/dQw4w9WgXcQ","dQw4w9WgXcQ"],"languages": ["en", "en-US"],"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Search YouTube by keyword and transcribe the top results:
{"mode": "search","searchQueries": ["langgraph tutorial", "apify actor development"],"maxVideosPerSource": 5,"languages": ["en"],"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Expand a playlist and a channel, capped per source, and translate everything to English:
{"mode": "url","videoUrls": ["https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx","https://www.youtube.com/@SomeChannel"],"maxVideosPerSource": 25,"maxVideos": 100,"languages": ["en"],"translateToLanguage": "en","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Trim every video's transcript to seconds 30 to 60:
{"mode": "url","videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],"startSec": 30,"durationSec": 30,"languages": ["en"],"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
The trimmed transcript, segments, srt, and vtt only contain snippets inside the window, and the transcript billing event counts only the trimmed characters.
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string enum | "url" | One of "url" (read videoUrls) or "search" (read searchQueries). The other field is ignored. |
videoUrls | array of strings | [] | Used when mode = url. Watch URLs, youtu.be URLs, shorts URLs, playlist URLs, channel URLs (@handle, /channel/, /c/, /user/), or 11-character video IDs. Playlists and channels are expanded to their videos. |
searchQueries | array of strings | [] | Used when mode = search. Free-form keywords. Top results per query are fetched. |
startSec | integer | 0 | Trim every transcript to start at this second. 0 keeps from the beginning. |
durationSec | integer | 0 | Trim every transcript to this many seconds from startSec. 0 keeps until the end of each video. |
maxVideosPerSource | integer | 10 | How many videos to take from each playlist, channel, or search query. |
maxVideos | integer | 0 | Hard cap on the total number of videos across all sources. 0 means no overall cap. |
languages | array of strings | ["en"] | Preferred transcript language codes in priority order. The first available one is used; if none are available, any transcript the video offers is returned. |
translateToLanguage | string | "" | Optional language code to translate the transcript into using YouTube's auto-translation. Empty keeps the original language. |
preserveFormatting | boolean | false | Keep inline formatting tags (such as italics) in the transcript text instead of stripping them. |
proxyConfiguration | object | Apify Proxy, RESIDENTIAL | Proxy settings. YouTube blocks most datacenter / cloud IPs from fetching transcripts, so the RESIDENTIAL group is strongly recommended. |
Output example
Sample shape: values are illustrative placeholders, not from a live video.
{"videoId": "EXAMPLE_ID1","videoUrl": "https://www.youtube.com/watch?v=EXAMPLE_ID1","videoTitle": "Sample Video Title","channelName": "Sample Channel","channelUrl": "https://www.youtube.com/@SampleChannel","durationSeconds": 213,"source": "https://www.youtube.com/watch?v=EXAMPLE_ID1","sourceType": "video","language": "English","languageCode": "en","isGenerated": false,"isTranslated": false,"translatedTo": null,"charCount": 5234,"segmentCount": 142,"transcript": "Hello and welcome to this sample transcript.\nThis is the second line of the transcript.\n...","segments": [{ "text": "Hello and welcome to this sample transcript.", "start": 0.0, "duration": 2.32 },{ "text": "This is the second line of the transcript.", "start": 2.32, "duration": 2.08 }],"srt": "1\n00:00:00,000 --> 00:00:02,320\nHello and welcome to this sample transcript.\n\n2\n00:00:02,320 --> 00:00:04,400\nThis is the second line of the transcript.\n","vtt": "WEBVTT\n\n00:00:00.000 --> 00:00:02.320\nHello and welcome to this sample transcript.\n\n00:00:02.320 --> 00:00:04.400\nThis is the second line of the transcript.\n","success": true,"error": null}
Billing
You are charged once per run, plus a small amount per keyword search that was successfully resolved (URL inputs are not charged for resolution), plus a length-based unit per fetched transcript. One transcript unit covers roughly 4,000 characters of transcript text, about 1,000 LLM tokens. A short clip is about one unit, a 1-hour podcast around twelve, and a 3-hour video around thirty-five. Videos whose captions are disabled, unavailable, or could not be fetched are not billed. If you trim the transcript with startSec and durationSec, you only pay for the trimmed text. Exact amounts are shown on this actor's Store page.
Plan requirement
Works on any Apify plan, but YouTube blocks most datacenter and cloud IP ranges from fetching transcripts. For reliable results use Apify Proxy with the RESIDENTIAL group, which is available on the Starter plan and higher. On the free plan, expect many videos to return an error; the run will log a notice and add a record explaining the upgrade path.