YouTube Transcripts & Captions Scraper (Subtitles at Scale)
Pricing
from $3.50 / 1,000 results
YouTube Transcripts & Captions Scraper (Subtitles at Scale)
Extract transcripts and captions from YouTube videos at scale. Returns full text, per-segment timing, and all available languages (manual + auto-generated). For RAG, sentiment analysis, video summarization, and agent workflows. No API key.
Pricing
from $3.50 / 1,000 results
Rating
0.0
(0)
Developer
Thirdwatch
Maintained by CommunityActor stats
0
Bookmarked
7
Total users
3
Monthly active users
40 minutes ago
Last modified
Categories
Share
Thirdwatch portfolio: 5K users across 88 public Actors, 2M+ records delivered, and >99% run success. Explore all Thirdwatch Actors.
Pull transcripts from any YouTube video — full text plus timestamps, every language track, no API key.
Pull transcripts and closed captions from any YouTube video, at scale, with no API key. Returns the full transcript text plus timestamped segments, all available caption languages, and whether the captions are human-written or auto-generated.
Built for RAG pipelines over video libraries, sentiment analysis, video summarization, accessibility workflows, and agentic tools that read video content.
What you get
A clean, structured transcript record per video. Choose a preferred language or let the actor fall back to whatever's available. Returns both the full joined transcript_text (ideal for vector stores) and a segments array with per-line timestamps (ideal for subtitle overlays and chapter generation).
Output fields
| Field | Description |
|---|---|
video_id | 11-character YouTube video ID |
video_url | Canonical watch URL |
language_code | Actual caption language returned (ISO 639-1) |
language_name | Human-readable language name |
is_auto_generated | true if auto-captions, false if human-written |
auto_translated | true if auto-translated into the requested language |
available_languages | Array of {code, name, is_auto_generated} for every track on the video |
transcript_text | Full transcript joined into one string |
segments | Array of {text, start, duration} per caption line |
segment_count | Number of caption lines |
total_duration_seconds | Total covered duration |
data_source | Origin tag |
used_residential_proxy | true only when the direct request was blocked and the paid fallback succeeded |
Failures are not written to the paid result dataset. They are available in the run's ERRORS key-value-store record with codes such as no_captions_available, private_video, region_locked, age_restricted_or_login_required, video_unavailable, no_player_response, transcript_fetch_failed, and empty_transcript.
Example output
{"video_id": "dQw4w9WgXcQ","video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ","language_code": "en","language_name": "English","is_auto_generated": false,"auto_translated": false,"available_languages": [{"code": "en", "name": "English", "is_auto_generated": false},{"code": "es", "name": "Spanish", "is_auto_generated": false},{"code": "en", "name": "English (auto-generated)", "is_auto_generated": true}],"transcript_text": "We're no strangers to love You know the rules and so do I ...","segment_count": 58,"total_duration_seconds": 212.48,"segments": [{"text": "We're no strangers to love", "start": 18.8, "duration": 7.0},{"text": "You know the rules and so do I", "start": 25.8, "duration": 3.5},{"text": "A full commitment's what I'm thinking of", "start": 29.3, "duration": 3.7}],"data_source": "youtube_timedtext"}
Example unbilled error diagnostic (no captions published)
{"failed_count": 1,"failed_videos": [{"video_id": "abc123XYZ_0","video_url": "https://www.youtube.com/watch?v=abc123XYZ_0","error": "no_captions_available","available_languages": [],"data_source": "youtube_innertube"}]}
Input parameters
| Parameter | Required | Description |
|---|---|---|
videoUrls | One of | YouTube URLs. Supports watch?v=, youtu.be/, shorts/, embed/. |
videoIds | One of | Raw 11-character video IDs. Either videoUrls or videoIds must be provided. |
languageCode | No | Preferred caption language. Default en. |
preferManual | No | Prefer human-written captions over auto-generated. Default true. |
includeTimestamps | No | Include the segments array. Default true. Turn off for smaller RAG payloads. |
includeAutoTranslate | No | Fall back to YouTube auto-translate if the requested language isn't available. Default false. |
useResidentialProxy | No | Allow residential retry after a direct IP-dependent failure. Direct HTTP is always tried first. Default true. |
maxResults | No | Cap on transcripts returned. Default 5, max 10000. |
Pricing
Only successfully delivered transcripts are billed. Ordinary direct-HTTP
transcripts start at $0.003 per video; subscriber tiers reduce that to
$0.0025, $0.002, and $0.0015. If YouTube blocks direct cloud egress and the
residential fallback succeeds, that transcript has one additional $0.004
proxy fallback event. Videos without captions and other failed inputs are
recorded under ERRORS and are not billed as results.
Use cases
- AI engineers (RAG): index thousands of talks, lectures, tutorials for semantic search.
transcript_textdrops straight into your vector store. - Content marketers: generate written blog posts, newsletters, and social clips from podcast and YouTube content at scale.
- Product & research teams: run sentiment analysis across competitor channels and track topic drift over time.
- Accessibility & compliance: build closed-caption corpora in bulk for ADA / WCAG compliance.
- Agent builders: plug into Claude / GPT / MCP workflows so an agent can "read" a YouTube URL.
- Language learners & translators: grab multilingual caption tracks side-by-side for study material.
- Video summarization tools: feed full transcripts into an LLM to generate chapter markers, key takeaways, and tl;drs.
Limitations
- Not all videos have transcripts — some uploaders disable captions entirely. Those videos are listed in the unbilled
ERRORSrecord withno_captions_available. - Auto-generated transcripts are lower quality — especially for music, accents, and technical content. Set
preferManual: true(default) to pick human-written tracks whenever available. - Age-restricted and private videos are blocked — they appear in the unbilled
ERRORSrecord rather than the paid result dataset. Region-locked videos behave the same way. - YouTube occasionally throttles heavy uninterrupted runs; the actor backs off automatically on rate limits.
Compared to alternatives
- Apify's pintostudio/youtube-transcript-scraper — similar scope at $0.01 per transcript; our direct path starts at $0.003 and keeps failed videos unbilled.
- youtube-transcript-api (Python library) — free to run yourself, but you handle the proxy, consent cookie, and retry logic. This actor is a hosted drop-in with built-in reliability.
- Official YouTube Data API — captions endpoint requires OAuth and channel ownership; not usable for third-party videos.
Pairs well with
- YouTube Scraper — pull video metadata (title, description, views, likes, channel) first, then feed the IDs here for transcripts.
- Google News Scraper — enrich news-video transcripts with source articles.
- Reddit Scraper — cross-reference discussion threads with the video's transcript.
FAQ
Does this work on YouTube Shorts?
Yes — youtube.com/shorts/{id} URLs work identically to regular videos.
Do I need an API key? No. The actor uses YouTube's public caption endpoints — no OAuth, no Google Cloud project.
Can I get transcripts for private videos?
No. Private videos return a private_video error. Only publicly published videos are supported.
Which languages are supported?
Every language a video has published captions for. Use languageCode to pick your preferred track, or enable includeAutoTranslate to cross-translate.
What happens if captions are disabled?
The video is omitted from paid results and recorded under ERRORS with error: "no_captions_available", so your pipeline can filter, retry, or skip it without paying for a transcript that was not delivered.
Can I feed this straight into a vector DB?
Yes — the transcript_text field is a single joined string designed for RAG ingestion. Turn off includeTimestamps to drop the segments array and shrink payloads further.
Built by Thirdwatch. Questions? Open an issue or reach out on the Apify Store listing.
Last verified: 2026-05