YouTube Transcript Scraper avatar

YouTube Transcript Scraper

Pricing

from $7.00 / 1,000 transcripts

Go to Apify Store
YouTube Transcript Scraper

YouTube Transcript Scraper

Get YouTube video transcripts with timestamps plus video and channel metadata, for single videos, lists of videos, or a whole channel within a date range. No API key needed. You only pay for videos that return a transcript.

Pricing

from $7.00 / 1,000 transcripts

Rating

0.0

(0)

Developer

Mr T

Mr T

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

YouTube Transcript Scraper

Get the full transcript of any YouTube video, with a timestamp on every line, plus the video's and channel's details. Works on single videos, lists of videos, or a whole channel within a date range. No YouTube API key, no Google account, no setup.

You only pay for videos that return a transcript. Videos without captions, private or removed videos, and bad URLs still appear in your results so you know what happened, but they are free.

What you get for each video

  • Transcript as timed segments (text, start, end in seconds), and optionally as one plain-text block
  • Caption details: which language you got, whether it is auto-generated, and every language the video offers
  • Video details: title, description, publish date and time (UTC), duration, views, likes, comment count, thumbnail
  • Channel details: name, ID, handle, subscriber count, channel picture

How to use it

  1. Paste a video URL into Video URL, or several into Video URLs (bulk). Watch links, youtu.be links, Shorts, live and embed links, and bare video IDs all work.
  2. Or paste a channel into Channel URL (https://www.youtube.com/@handle, /channel/UC…, /c/… or /user/…), and set Max videos and a Start date / End date. Without dates you get the last 30 days.
  3. Optionally set Transcript language (for example en, es, de).
  4. Click Start. Results appear in the Output tab and can be downloaded as JSON, CSV, Excel or HTML.

Example input

{
"youtube_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"language": "en",
"include_transcript_text": true
}
{
"channel_url": "https://www.youtube.com/@taostats",
"max_videos": 20,
"start_date": "2026-01-01",
"end_date": "2026-06-30"
}

How the language is chosen

  • With a language set: manual captions in that language first, then auto-generated captions in it.
  • If the video has no captions in that language, the row has error_code language_unavailable. Another language is never substituted, and captions are never machine-translated.
  • With no language set: the track YouTube shows by default.

Example output

{
"video_id": "sGYS42SjRkg",
"url": "https://www.youtube.com/watch?v=sGYS42SjRkg",
"title": "This Bitcoin developer is on a power trip",
"channel_name": "CoinDesk",
"channel_id": "UC7TghOL755nBk7HelHoi9LQ",
"channel_username": "CoinDesk",
"channel_thumbnail": "https://yt3.ggpht.com/…=s800-c-k-c0x00ffffff-no-rj",
"subscriber_count": 196000,
"timestamp": 1759059043,
"published_at": "2025-09-28T11:30:43Z",
"view_count": 921,
"like_count": 17,
"comment_count": null,
"duration_seconds": 86,
"description": "Catch the latest episode of 'BITCOIN SEASON 2' …",
"thumbnail": "https://i.ytimg.com/vi/sGYS42SjRkg/maxresdefault.jpg",
"language": "en",
"selected_language": "English (auto-generated)",
"available_languages": ["English (auto-generated)"],
"is_auto_generated": true,
"geo_restrict": null,
"transcript": [
{ "text": "Then the last one which is kind of the", "start": 0.56, "end": 2.639 },
{ "text": "one that I kind of but my head against", "start": 2.639, "end": 4.64 }
],
"transcript_text": "Then the last one which is kind of the one that I kind of but my head against …",
"status": "success",
"error_code": null,
"message": "Successfully fetched the transcript for the video with ID 'sGYS42SjRkg'"
}

When a video has no transcript, the row has "status": "error", an error_code, and a readable message. The codes are:

error_codeMeaning
transcripts_disabledThe video has no captions at all. Video details are still filled in.
transcript_unavailableA caption track is listed but YouTube returned it empty.
language_unavailableCaptions exist, but not in the requested language.
video_unavailable, private_video, members_only, age_restricted, login_required, live_stream_offlineThe video can't be watched without an account, or doesn't exist.
invalid_url, channel_not_foundThe input couldn't be matched to a video or channel.
blocked, rate_limited, timeout, network_error, server_error, http_error, unexpected_responseYouTube refused or failed on every retry. Running again usually works.

Notes on the numbers

  • Subscriber count is what YouTube displays, so it is rounded (for example 196K becomes 196000).
  • Comment count is exact when YouTube provides it. Otherwise it comes from the comments panel, which is exact below 1,000 and rounded above (2.4M becomes 2400000). It is null when YouTube shows no count.
  • Like count is null when the uploader hides likes.
  • geo_restrict is always null; the field is kept so that existing integrations don't break.

Channel mode

Channel mode reads the channel's Videos tab (long-form uploads; Shorts and live streams are not included), newest first, and stops when it reaches max_videos or videos older than the start date.

Proxies

YouTube blocks most cloud IP addresses, so the default proxy setting is Apify Residential. Each video uses roughly 100 KB of proxy traffic. You can switch to another proxy group or your own proxies under Advanced, but datacenter proxies are usually blocked.

Using it from code

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('adaptable_wheelhouse/youtube-transcript-scraper').call({
youtube_urls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
include_transcript_text: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

This actor reads only public data that anyone can see on youtube.com without logging in. Results may still contain personal data, which is protected by laws such as GDPR. Only collect personal data if you have a legitimate reason, and check with a lawyer if you are unsure.