Apify Actors / YouTube transcripts as text, SRT or WebVTT

Apify Actor

YouTube transcripts as text, SRT or WebVTT

YouTube's transcript panel is fine for one video and useless for two hundred. This Actor takes watch URLs, youtu.be links, Shorts, playlist URLs and channel handles in any mix, and returns one row per video with the transcript and the metadata next to it.

Pick the output format. Use plain text for search and LLM input, timestamped segments for clipping, and SRT or WebVTT for players and editors. Videos it cannot read come back as free rows with an error code (NO_CAPTIONS, AGE_RESTRICTED, PRIVATE), and the run carries on.

Run it on ApifySee input and output

$0.0025 per saved transcript · pay per result, no subscription

Price

EventPriceCharged when
Transcript (video)$0.0025Once per video whose transcript is saved to the dataset
Example runUnitsCost
The prefilled input (2 videos)2 transcripts$0.005
A playlist of 100 videos, all with captions100 transcripts$0.25

What you get

Input

Set the run options in the Apify console, or send the same object through the API.

{
  "videos": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://youtu.be/dQw4w9WgXcQ"
  ],
  "outputFormat": "segments",
  "languages": [
    "en"
  ],
  "allowAutoGenerated": true,
  "maxVideosPerPlaylist": 50
}

The prefilled input. One URL, playlist or @handle per line, up to 5,000 lines and 10,000 videos per run.

Output

{
  "status": "ok",
  "videoId": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "title": "Me at the zoo",
  "channelName": "jawed",
  "publishDate": "2005-04-23T20:31:52-07:00",
  "durationSeconds": 19,
  "viewCount": 447802112,
  "languageCode": "en",
  "isGenerated": false,
  "segmentCount": 6,
  "wordCount": 39,
  "outputFormat": "segments",
  "text": "All right, so here we are, in front of the elephants..."
}

One real row, trimmed. Segments, SRT and WebVTT add their own field next to text; error rows keep the video id and put a code in error.

Run it from your own code

The Actor takes the same input as a JSON body. This call starts a run, waits for it and returns the dataset items.

curl -X POST "https://api.apify.com/v2/acts/zovo-one~tubetext-youtube-transcript-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"videos": ["https://www.youtube.com/watch?v=jNQXAC9IVRw", "https://youtu.be/dQw4w9WgXcQ"], "outputFormat": "segments", "languages": ["en"], "allowAutoGenerated": true, "maxVideosPerPlaylist": 50}'

A sync call waits at most 300 seconds. For longer runs, start a run with POST /v2/acts/zovo-one~tubetext-youtube-transcript-scraper/runs, wait for it, then read /v2/datasets/<defaultDatasetId>/items.

Limits

Up to 5,000 input lines and 10,000 videos per run, 10 languages and 10 parallel videos. It reads public captions only and never signs in, so private, age-restricted and members-only videos give error rows. It does not transcribe audio and does not translate. A video without your language returns the original language, unless you turn the fallback off. YouTube Mix playlists cannot be listed. The default proxy is Apify residential, because YouTube blocks many datacenter IPs, and a traffic guard stops a run if the average response body passes 225 KB per video.

Questions

How do I get a YouTube transcript for many videos at once?

Paste watch URLs, youtu.be links, Shorts, playlist URLs or @handles, one per line, and run the Actor. You get one dataset row per video with the transcript and its metadata. A run takes up to 10,000 videos.

Does it work on playlists and channels?

Yes. A playlist URL lists the videos, and an @handle lists the channel's uploads, up to maxVideosPerPlaylist. Listing is free; you pay only for transcripts that are saved. YouTube Mix playlists (RD...) are made per viewer and return an error.

Can I get SRT or WebVTT subtitles?

Set outputFormat to srt or webvtt and the file text comes back in that format, with the same rows and metadata. segments gives you JSON with start and end times for each line.

Do I pay for videos without captions?

No. Error rows are pushed without a charge event, and listing a playlist or channel is free too. A video from a playlist costs the same as one you paste directly.

Can I get only human-written captions?

Yes. Turn off allowAutoGenerated and videos with only auto-generated captions return an error row instead of a transcript. isGenerated on each row tells you which kind you got.

Is scraping YouTube transcripts allowed?

The Actor reads public caption tracks the way a logged-out viewer does. It doesn't bypass a login or a paywall. YouTube's terms still apply to how you use the text, so check them for your case, especially if you plan to republish large parts of a transcript.

Support this work

If this Actor saves you time, you can support the work on GitHub Sponsors. Monthly tiers start at $5, and one-time tiers start at $15. Sponsorship is optional, and the tool works the same without it.

Built and maintained by Zovo. Actor on Apify · All Actors.