YouTube Transcript Bulk Scraper - $0.40 per 1,000 avatar

YouTube Transcript Bulk Scraper - $0.40 per 1,000

Pricing

from $0.40 / 1,000 transcript extracteds

Go to Apify Store
YouTube Transcript Bulk Scraper - $0.40 per 1,000

YouTube Transcript Bulk Scraper - $0.40 per 1,000

Bulk YouTube transcripts from video links, a channel URL or a playlist: full text, per-cue timestamps, language, auto-generated flag, plus title, channel, duration and view count. Channel and playlist expansion is free and videos without captions are never charged. No API key.

Pricing

from $0.40 / 1,000 transcript extracteds

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

YouTube Transcript Bulk Scraper

Paste video links, a channel URL or @handle, or a playlist link. Every video that has captions comes back as one row: the full transcript text, the per-cue timestamps, the language, whether the track was written by a human or generated by machine, plus the video title, channel, duration and view count.

Channels and playlists get expanded into their videos for you, and that expansion is free. You pay only for transcripts that actually come back. A 900-video channel with maxItems: 20 costs you 20 transcripts, not 900 page loads.

It reads captions from YouTube's own player API as a first-time guest. No API key, no Google account, no browser.

Price

$0.40 per 1,000 transcripts, plus a $0.0005 start fee per run.

WhatCost
One transcript$0.0004
1,000 transcripts$0.40
Starting a run$0.0005
A run that returns nothing$0.0005

One transcript-scraped event per transcript row. Free: listing a channel or playlist, resolving an @handle, the sample row, and every diagnostic row — a video with no captions, a deleted video, a private video, a time-budget skip. A video that appears twice in your input, or in two of your playlists, is fetched and charged once.

Input

{
"videoUrls": [
"https://www.youtube.com/watch?v=aircAruvnKk",
"https://www.youtube.com/@3blue1brown",
"https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi"
],
"languages": ["en"],
"maxItems": 50,
"maxVideosPerSource": 25
}
FieldWhat it does
videoUrlsMix and match: watch / Shorts / youtu.be / embed links, bare 11-character video IDs, a channel URL or @handle, or a playlist link. Up to 500 entries.
maxItemsTotal transcripts this run returns across everything you pasted. This is what you pay for. Default 10, ceiling 5,000.
maxVideosPerSourceHow deep to go into each channel or playlist before moving on. Channels are read newest first. Default 25, ceiling 2,000.
languagesCodes in priority order, e.g. ["en","es","pt-BR"]. The first one the video actually has wins, and pt matches pt-BR. Set this. See the note below.
preferAutoGeneratedOff by default, so a human-written track beats a machine one — it has punctuation and speaker turns. Turn it on if you specifically want the machine transcript.
includeSegmentsOn by default. Keeps the per-cue array on each row. Turn it off for smaller rows when you only want the text.
concurrencyVideos fetched at once, 1–10. Default 6.
proxyUrlsLeave empty unless you already pay for proxy servers and want traffic to leave through them.

About languages. If you leave it empty you get whatever caption track YouTube lists first, preferring human-written over machine. On a channel with community translations that is often not the spoken language — a run against a 3Blue1Brown video with no languages set came back with the Arabic track, because it exists and is human-written. Put ["en"] in there if you want English.

Empty input gives you one labelled sample row, free.

Output

{
"ok": true,
"charged": true,
"recordType": "transcript",
"videoId": "aircAruvnKk",
"url": "https://www.youtube.com/watch?v=aircAruvnKk",
"title": "But what is a neural network? | Deep learning chapter 1",
"channelName": "3Blue1Brown",
"channelId": "UCYO_jab_esuFRV4b17AJtAw",
"channelUrl": "https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw",
"durationSeconds": 1120,
"viewCount": 23954297,
"thumbnailUrl": "https://i.ytimg.com/vi/aircAruvnKk/sddefault.jpg",
"language": "en",
"languageName": "English",
"isAutoGenerated": false,
"segmentCount": 217,
"wordCount": 2380,
"characterCount": 13433,
"text": "This is a 3. It's sloppily written and rendered at an extremely low resolution...",
"segments": [
{ "start": 4.22, "duration": 1.18, "end": 5.4, "text": "This is a 3." }
],
"availableLanguages": [
{ "languageCode": "en", "languageName": "English", "isAutoGenerated": false },
{ "languageCode": "es", "languageName": "Spanish", "isAutoGenerated": false }
],
"sourceType": "video",
"sourceUrl": "https://www.youtube.com/watch?v=aircAruvnKk",
"playlistId": null,
"scrapedAt": "2026-08-21T16:20:26.000Z"
}
  • availableLanguages lists every track the video has, so you can see what you could have asked for.
  • sourceType / sourceUrl say where the video came from — the link you pasted, or the channel or playlist it was expanded out of. Useful when one run mixes several sources.
  • playlistId for a channel is its uploads playlist. Stable and re-usable.
  • wordCount / characterCount are counted on text, which is what you want for budgeting a language-model pass.

Limits

  • It reads captions. It does not transcribe audio. A video with no caption track at all produces an uncharged NO_RESULTS row. Music videos, ambient footage and brand-new uploads are the usual cases — in a sample of eighty recent uploads across ten large channels, six had no track.
  • Auto-generated tracks have no punctuation, no capitalisation and no speaker labels, and they mangle names and technical terms. isAutoGenerated tells you which rows are affected.
  • Private, deleted, members-only, age-restricted and region-blocked videos come back as uncharged diagnostics.
  • Live streams have nothing usable until the recording is processed and captions appear.
  • Channels are listed newest first from their uploads playlist. There's no date filter and no oldest-first order — ask for more videos per source and filter afterwards.
  • A channel's uploads playlist leaves out unlisted videos and, on some channels, Shorts. Paste a Shorts link or the specific playlist if you need those.
  • No translation. You get the tracks the video publishes. Ask for a language it doesn't have and you fall back to one it does; language on the row tells you which.
  • Timings come from YouTube's caption file. Human tracks are cue-accurate; auto tracks drift by a fraction of a second and break lines mid-sentence.
  • Very long videos make very large rows. A four-hour lecture is a few thousand cues — turn includeSegments off if you only need the text.
  • Ceilings: 500 pasted entries, 2,000 videos per source, 5,000 transcripts per run.

Diagnostic codes

Uncharged rows carry "_diagnostic": true and an errorCode: NO_RESULTS (no caption track, or the caption file came back empty), NOT_FOUND (private, deleted, region-blocked, or the channel doesn't exist), BAD_INPUT (not a YouTube link), TIME_BUDGET, NETWORK. Each carries the videoId and a plain-English details.

Filter on charged == true and the count equals what you were billed for.

How it gets through

Traffic leaves through a large rotating pool. YouTube shows some addresses a "sign in to confirm you're not a bot" wall, and the run treats that as a signal to move rather than to wait: it hops to another address, mints a fresh guest token there and carries on. That's what lets long channel runs finish. Caption text is downloaded in YouTube's leanest caption format rather than the verbose one the player defaults to — same cues, same timings, about a ninth of the bytes.

Questions

Do I need a YouTube API key? No. Nothing is signed in and no quota is consumed.

Can I give it a channel and get everything? Paste the channel URL or @handle and raise maxVideosPerSource and maxItems. Listing the channel is free.

Will the run fail if YouTube blocks it? No. It moves to another address and continues. If it genuinely can't get through you get uncharged diagnostic rows and a succeeded run.

Can I schedule it? Yes. Point it at a channel daily and diff on videoId to pick up what's new.