YouTube Transcript Scraper
Pricing
$2.99 / 1,000 transcripts
YouTube Transcript Scraper
Get the spoken transcript of any YouTube video by URL, by channel, or by keyword search. No API key, no login. Falls back to any available language instead of failing when there is no English one, prefers human-written captions, and says why when a video has none. Full text plus timed segments.
Pricing
$2.99 / 1,000 transcripts
Rating
0.0
(0)
Developer
Quiet Harvest
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
22 minutes ago
Last modified
Categories
Share
Get the spoken transcript of any YouTube video — by URL, by channel, or by searching a keyword. No API key, no login, no cookies.
$2.99 per 1,000 transcripts. You are only charged for transcripts actually returned.
Why this one
Most transcript scrapers ask YouTube for English and give up when there isn't one. A Korean beauty video with a Korean transcript comes back empty, and you are left guessing whether the video had captions at all.
This Actor does two things differently.
It falls back instead of failing. If your preferred language is not available, you get whatever transcript the video does have, preferring a human-written one over an auto-generated one. Across 39 long-form videos in a mixed English/Korean sample, 39 returned a transcript.
It tells you why when there is nothing. Every row carries transcript_status. An empty transcript is never ambiguous:
transcript_status | What it means |
|---|---|
ok | Transcript returned |
disabled_by_uploader | The uploader switched captions off. Nobody can retrieve this one. |
no_transcript | The video has no caption track at all |
video_unavailable | Private, deleted, or age-restricted |
blocked | YouTube rate-limited the request |
error | Something else went wrong |
Three ways in
1. Specific videos
{"videoUrls": ["https://www.youtube.com/watch?v=OrElyY7MFVs","https://youtu.be/dQw4w9WgXcQ","https://www.youtube.com/shorts/58mOSOMn72g"]}
Watch links, Shorts links, youtu.be links and bare 11-character IDs all work.
2. A whole channel
{"channelUrls": ["@aliabdaal", "https://www.youtube.com/@veritasium"],"maxVideosPerSource": 25}
3. Everything on a topic
{"keywords": ["korean skincare", "glass skin"],"maxVideosPerSource": 20}
Searches YouTube and transcribes the results. Useful when you want the conversation on a subject rather than one creator.
Worked examples
Feed an LLM or RAG index — full text only, no timestamps
{"channelUrls": ["@lexfridman"],"maxVideosPerSource": 50,"includeSegments": false}
Dropping segments makes the dataset far smaller when you only need the words.
Build subtitles — keep the timings
{"videoUrls": ["https://www.youtube.com/watch?v=OrElyY7MFVs"],"includeSegments": true}
Each line comes back as {"start": 0.24, "duration": 3.84, "text": "..."}.
Non-English content
{"keywords": ["메이크업"],"languages": ["ko", "en"],"maxVideosPerSource": 30}
Long-form only, highest hit rate
{"keywords": ["web scraping tutorial"],"skipShorts": true,"maxVideosPerSource": 30}
Most Shorts have captions switched off by their uploader. Skipping them raises the share of videos that come back with text.
Research a competitor's whole channel
{"channelUrls": ["@competitor"],"maxVideosPerSource": 200,"includeSegments": false}
Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("reportable_broth/youtube-transcript-scraper").call(run_input={"keywords": ["korean skincare"],"languages": ["ko", "en"],"maxVideosPerSource": 20,})for r in client.dataset(run.default_dataset_id).iterate_items():if r["transcript_status"] == "ok":print(f'{r["transcript_language"]:>6} {len(r["transcript"]):>6} chars {r["title"]}')else:print(f' skipped ({r["transcript_status"]}): {r["title"]}')
On
apify-client3.x the object returned by.call()is a model, not a dict. Userun.default_dataset_id, notrun["defaultDatasetId"].
Output
| Field | Type | Notes |
|---|---|---|
video_id | string | |
url | string | Watch link |
title | string | |
channel | string or null | Channel name |
channel_id | string or null | |
channel_username | string or null | The @handle |
channel_thumbnail | string or null | Channel avatar |
subscriber_count | integer or null | Read from the video owner block; YouTube omits it on some page variants |
subscriber_count_text | string or null | As YouTube shows it, e.g. 6.69M subscribers |
thumbnail | string or null | Video thumbnail |
published_at | string or null | Exact ISO 8601 publish time |
published_ts | integer or null | The same, as a Unix timestamp |
duration_seconds | integer or null | |
view_count | integer or null | Exact |
like_count | integer or null | Exact |
comment_count_text | string or null | As YouTube shows it, e.g. 4.2K |
comment_count_approx | integer or null | That text as a number — rounded |
comment_count | integer or null | Exact. Only with exactCommentCount |
description | string or null | Full description |
hashtags | array | Parsed from the description |
description_links | array | Parsed from the description |
keywords | array | The uploader's tags |
is_short | boolean or null | |
is_live | boolean or null | |
available_languages | array | Every caption track the video has: code, name, is_generated |
transcript_status | string | See the table above |
transcript | string or null | Full text |
transcript_chars | integer | Length, handy for filtering |
transcript_segments | array | start, duration and text per line |
transcript_language | string or null | The language actually returned |
transcript_is_generated | boolean | Auto-generated, or human-written |
_source | string | url, channel or keyword |
_query | string | What produced this row |
Sample row
{"video_id": "OrElyY7MFVs","url": "https://www.youtube.com/watch?v=OrElyY7MFVs","title": "My Evidence-Based Skincare Routine","channel": "Ali Abdaal","transcript_status": "ok","transcript": "All right, so having the perfect skincare routine is actually pretty simple...","transcript_chars": 18705,"transcript_language": "en","transcript_is_generated": true,"transcript_segments": [{ "start": 0.0, "duration": 0.88, "text": "All right, so having the perfect" }],"_source": "url","_query": "OrElyY7MFVs"}
What to expect
Not every video has a transcript, and that is not a bug. Uploaders can switch captions off, and most Shorts have them off. In a 131-video sample across three keywords, 111 came back with a transcript; every one of the other 20 was disabled_by_uploader. With skipShorts on, a 39-video long-form sample returned 39.
You are only charged for transcripts actually returned. Rows with a non-ok status cost nothing.
Residential proxy is the default and worth keeping. YouTube rate-limits repeated requests from one IP, and a blocked request is retried on a fresh one.
Public content only. Private, unlisted and members-only videos are not accessible.
FAQ
Do I need a YouTube Data API key? No. No Google Cloud project, no quota, no login.
What if a video has no English transcript?
You get whatever transcript it has, and transcript_language tells you which. A human-written track is preferred over an auto-generated one when both exist.
Can I get subtitles in SRT or VTT? The timed segments contain everything an SRT or VTT needs — start, duration and text — so converting is a few lines in your own code.
Does it translate? No. You get the transcript in the language it exists in.
Why is a transcript empty?
Read transcript_status. disabled_by_uploader means the uploader turned captions off and no tool can retrieve it.
Our other Actors
- Threads Scraper — search Threads by keyword or pull a profile's posts, replies, reposts and media. No login.
- YouTube Monitor — watch keywords and channels for new videos only, with Shorts, exact publish times, like counts and built-in dedupe across runs.
Changelog
- 0.1.0 — First release. Videos, channels and keyword search; language fallback;
transcript_status.
Disclaimer
This Actor collects publicly available captions only. You are responsible for how you use what you collect, including compliance with YouTube's terms of service and applicable law.
Keywords: youtube transcript, youtube transcript scraper, youtube captions, youtube subtitles, transcript api, video transcript, youtube to text, extract youtube transcript, bulk transcripts, transcript extractor, youtube captions api, srt, vtt, whisper alternative, no api key.