YouTube Transcript Scraper
Pricing
from $1.60 / 1,000 result items
YouTube Transcript Scraper
YouTube transcript scraper with no API key and no login. Get the full transcript, subtitles and timed caption segments for any video, channel or search, with human captions preferred over auto-generated ones. Monitor mode returns transcripts of new uploads on a channel.
Pricing
from $1.60 / 1,000 result items
Rating
0.0
(0)
Developer
Viktor Dubnytskiy
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
13 hours ago
Last modified
Categories
Share
Get the subtitle text of YouTube videos as one flat row per video — the full transcript, the caption type (human-written or auto-generated) and the timed segments behind it. Feed it single videos, whole channels or a keyword search. No API key, no login, no video downloads.
Try it: the prefilled example returns 2 rows in about 10 seconds and costs about $0.004. Results cost $2 per 1,000.
What you get
Real rows from the example dataset (transcript text truncated here):
| video | source | captions | words / segments |
|---|---|---|---|
| Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster) | videoUrls | en, human-written | 487 / 61 (213s) |
| Apify Agent Skills Makes It Easy To Scrape Websites! | searches: "apify tutorial" | en, auto-generated | 2588 / 359 (863s) |
| How to scrape anything with Apify and Make #aiautomation #nocode | searches: "apify tutorial" | en, auto-generated | 111 / 17 (40s) |
segments on the first row: [{"start": 1.36, "duration": 1.68, "text": "[♪♪♪]"}, …]; availableLanguages ["en", "de-DE", "ja", "pt-BR", "es-419"].
Full row: id / videoId, url, title, channelId, channelName, durationSec, language, languageName, isAutoGenerated, availableLanguages, segments (start, duration, text — seconds), text (all segments joined), wordCount, segmentCount, source (url / channel / search), query, scrapedAt.
Use cases
- Monitor a channel's new uploads, weekly — put a competitor's or your own channel handle into monitor mode; each scheduled run returns transcripts only for videos published since the last check, ready for a newsletter or content calendar without re-pulling the whole channel.
- Scheduled research or SEO feed on a keyword — run a search keyword on a weekly schedule in monitor mode to catch new videos ranking for that term as they appear, instead of re-scraping the same result page from scratch each time.
- One-off transcript pull for a single video — grab the transcript and timed segments for one video right now, no schedule needed.
Try it in 10 seconds
One-off — hit Start/Try it, the input already works: two example videos preloaded in videoUrls, languages: ["en"], maxItems: 20, nothing required. Swap in your own URLs, a channels handle or a searches keyword and run again.
Monitor mode — save the input as a Task, then set:
{"mode": "monitor","monitorStateId": "nasa-channel-watch","channels": ["@NASA"],"webhookUrl": "https://your-endpoint.example.com/hook","telegramBotToken": "","telegramChatId": ""}
and put it on a schedule (Apify → Schedules → cron 0 8 * * 1 for weekly). Each monitor run charges one monitor-check event ($0.006) and returns only transcripts that are new or changed since the previous run, each billed as one change event ($0.002) — a run with nothing new charges only the check.
How it works
- Video URLs / channels / searches are resolved into a list of video ids.
- For each video the caption track list is fetched and one track is chosen by your
languagesorder, human-written before auto-generated (preferManual), withfallbackAnyLanguageas the last resort. - The chosen track is downloaded as timed text and split into
segments;textis those segments joined. - YouTube shows a "sign in to confirm you're not a bot" wall to some exits, so the actor starts without a proxy and escalates one rung at a time (
tier: auto).
Input
| Field | Meaning | Default |
|---|---|---|
videoUrls | Watch URLs, youtu.be / /shorts/ links, or bare 11-char ids | two example videos |
channels | @handle, channel URL or UC… id — latest videos are transcribed | empty |
searches | Keywords; the videos of the first result page are transcribed | empty |
languages | Preference order of caption languages, e.g. ["en","de"] | ["en"] |
preferManual | Human-written track before the auto-generated one | true |
includeAutoGenerated | Allow YouTube's speech-recognition track | true |
fallbackAnyLanguage | Take any track when none of your languages exists | false |
maxVideosPerChannel | Latest videos taken from each channel | 50 |
includeShorts | List the Shorts tab instead of Videos | false |
tier | Proxy rung: auto, none, datacenter, residential | auto |
maxItems | Stop after this many transcripts | 20 |
mode | scrape or monitor (only new/changed since last run) | scrape |
monitorStateId, webhookUrl, telegramBotToken, telegramChatId | Monitor-mode state key and alert targets | empty |
Pricing
| Event | Price |
|---|---|
| result | $0.002 per transcript ($2 per 1,000) |
| monitor-check | $0.006 per monitor run |
| change | $0.002 per new/changed transcript |
Videos without a usable caption track are not pushed and not charged. They are counted in the ADAPTER_STATS record of the run's key-value store (noCaptions, unplayable, loginWalls, listingWalls, escalations, tierUsed), next to the standard RUN_SUMMARY record — so an empty run tells you whether the videos simply had no captions or whether YouTube refused the requests.
Why this actor
- No API key, no login, no cookies — nothing to register and nothing to keep alive.
- Timed
segmentscome with every row, not just a wall of text, so you can cite or seek back into the video. - Human-written captions before auto-generated,
isAutoGeneratedtells you which kind you got — most competitors don't distinguish the two in the output. - A video with no usable captions is never pushed and never charged, so a batch of mixed videos costs only what it produced.
- The run tells you why it was empty:
ADAPTER_STATSseparates "no captions" from "YouTube wall" from "video unplayable". - Monitor mode watches a channel or a search keyword on a schedule and returns only what's new, so a weekly check costs one
monitor-checkplus the transcripts that actually changed — not a full re-pull. - Starts with no proxy and escalates only when YouTube actually walls the exit, so most runs carry no proxy cost.
Limits
- Auto-generated tracks are speech recognition: no punctuation to speak of, occasional wrong words, and word timings grouped into short lines.
isAutoGeneratedtells you which kind you got. - No machine translation: you get the tracks the video actually publishes, never a translated one.
- Videos with captions disabled, private, removed or age-restricted videos return nothing (and cost nothing).
- YouTube shows a "sign in to confirm you're not a bot" wall to some exit IPs. The actor starts without a proxy and escalates to datacenter and then residential proxy when it sees the wall; residential traffic is billed by Apify on top of the per-result price.
- Member-only and unlisted videos are not supported.
FAQ
Does it need a YouTube API key or a login? No. There is no key field and no cookie field. Captions are read from the public player payload.
What happens to videos that have no subtitles? They are skipped: no row, no charge. The count lands in noCaptions inside the ADAPTER_STATS record of the run's key-value store.
Can I get a transcript in a language the video does not publish? No. The actor never machine-translates. Ask for your languages in languages, and set fallbackAnyLanguage to true if you would rather have the video's own language than nothing.
How do I get alerted only when a channel posts something new? Save the input as a Task with channels set, mode: "monitor" and a monitorStateId, put it on a weekly schedule, and add a webhookUrl or Telegram target — see "Try it in 10 seconds" above.
Changelog
- 0.1: initial release — transcripts from video URLs, channels and search; language preference, manual/auto track choice, timed segments.
If this actor saved you time, a short review on its Store page genuinely helps other people find it. Found a bug or need a field that is missing? Open a ticket on the Issues tab.