YouTube Transcript Scraper - Text, SRT & VTT
Pricing
from $2.40 / 1,000 results
YouTube Transcript Scraper - Text, SRT & VTT
Export available YouTube captions as text, timestamped segments, SRT, VTT or JSON. Choose preferred languages or require manual captions. Returns caption counts and an optional video title. Source access and translation availability vary.
Pricing
from $2.40 / 1,000 results
Rating
0.0
(0)
Developer
Ben
Maintained by CommunityActor stats
0
Bookmarked
148
Total users
3
Monthly active users
4 hours ago
Last modified
Categories
Share
YouTube Transcript Scraper: text, SRT and VTT captions
Extract caption tracks available on a YouTube video, select a language and export readable text or subtitles. Each successful row keeps the original timestamped segments alongside your chosen output format. The Actor uses existing captions; it does not transcribe audio or create captions for a video that has none.
Open the tested video example, or paste your own video URLs into the input form. No separate API key is required. Availability depends on the video's caption tracks and current source access.
Price: Free-plan result events cost $3 per 1,000 returned video rows, plus the start event. Unavailable-caption rows are also charged results. Start with one known video and check transcript_available before scaling.
Quick start
Start with one video and inspect the returned language and transcript_available before processing a batch:
{"videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],"preferredLanguages": ["en"],"includeAutoGenerated": false,"outputFormat": "srt","includeVideoMetadata": false,"maxVideos": 1}
The SRT content is in formatted_transcript. segments remains a structured array with text, start and duration, so you can use the same row for subtitle export and text analysis. The dataset's Formatted captions view shows the selected format; Transcript overview shows video identity, language and counts.
Choose a caption track
| Input | Behavior |
|---|---|
videoUrls | YouTube URLs or 11-character video IDs. Duplicate IDs are processed once. Invalid input fails before fetching videos. |
preferredLanguages | Language codes in priority order, such as ["en-US", "en", "de"]. Manual captions take precedence within a language. An empty list accepts any available language. |
includeAutoGenerated | true allows generated caption tracks; false accepts only manual tracks. Default: true. |
translateTo | Translate the selected track if YouTube offers the requested language. Empty preserves the original language. |
outputFormat | text, timestamped, srt, vtt or json. Default: text. |
includeVideoMetadata | Fetch the title through public oEmbed. false skips that request and returns a null title. This option does not fetch view counts or video duration. |
maxVideos | Cap the number of distinct videos. The form defaults to three; 0 removes the item cap, subject to the run's timeout and spending limit. |
An unavailable preferred language is reported explicitly. The Actor does not silently substitute a language outside the list. To permit any language, use preferredLanguages: [].
Translation limitation, September 10, 2026: both French-translation cloud checks encountered a source access block, while original English caption exports returned data. Translation selection passes offline checks, but translated-track delivery remains unverified. Start with original captions for production workflows.
Accepted URL forms include watch?v=, youtu.be/, embed/, shorts/ and live/. Existing API aliases videos, startUrls and languages remain accepted; use the documented form fields for new integrations.
Output fields
| Field | Meaning |
|---|---|
video_id, video_url | Normalized YouTube identity and canonical URL. |
title | Video title when metadata is enabled and available; otherwise null. |
transcript_available | Whether a usable caption track was returned for the selected options. |
language, source_language | Returned language and original caption-track language. |
is_generated | Whether the original caption track was autogenerated. |
is_translated | Whether the selected track was translated into a different language. |
segments | Caption text with start times and durations in seconds. |
segment_count, word_count | Counts for the returned captions. |
full_text | Caption text joined with spaces. The legacy includeFullText: false option omits this duplicate text. |
output_format, formatted_transcript | Requested format and its string content. JSON output is a serialized segment array. |
scraped_at | UTC collection timestamp. |
error, error_type | Explanation when the requested captions or translation are unavailable. |
This abbreviated segment comes from the September 9, 2026 example run; timings are in seconds:
{"video_id": "dQw4w9WgXcQ","language": "en","is_generated": false,"transcript_available": true,"segments": [{"text": "[♪♪♪]", "start": 1.36, "duration": 1.68}],"segment_count": 61,"word_count": 487}
Only the first segment is shown; the counts describe the complete dated transcript. Caption tracks can change after collection.
Save subtitle files
Choose srt or vtt, download the dataset as results.json, then run this standard-library Python example in your virtual environment:
import jsonimport refrom pathlib import Pathfor row in json.loads(Path("results.json").read_text()):if not row.get("transcript_available"):continuevideo_id = row["video_id"]output_format = row["output_format"]if not re.fullmatch(r"[A-Za-z0-9_-]{11}", video_id) or output_format not in ("srt", "vtt"):raise ValueError("Expected a video ID and SRT/VTT output")Path(f"{video_id}.{output_format}").write_text(row["formatted_transcript"], encoding="utf-8")
The other formats support different workflows: text keeps one caption per line, timestamped prefixes each line with its start time in seconds, and json preserves the segment objects. This is caption extraction, so the Actor does not summarize, translate through another provider or generate embeddings.
Costs and failure handling
The Free-tier result event is $0.003 per returned video row, with a $0.00005 start event per GB of allocated memory, minimum one. Plan discounts apply. Unavailable-caption rows are still returned results and incur that result event; inspect the selected options before scaling a batch. Check the Pricing tab for current terms and set a maximum run charge.
Known missing-video, missing-caption, unmatched-language and unsupported-translation conditions return transcript_available: false with an error type. Access, network, parsing and storage failures fail the run instead of being labeled “no captions.” A failed batch may already contain completed rows; preserve them and inspect the run status before retrying. Invalid input does not trigger a substitute demo video.
Common questions
Can it create captions for a video with none? No. It downloads available caption tracks. Speech recognition requires a separate transcription tool and appropriate rights to the audio.
Does turning off autogenerated captions also forbid translation? No. It selects a manual source track; translateTo can still request an offered translation. is_generated describes the source track, while is_translated describes the returned text.
Can it return a different language if my preference is missing? Only if you listed that language or supplied an empty preference list. A translation must also be offered by YouTube for the selected track.
Why is the title null? Metadata may be disabled or its oEmbed request may be unavailable. Caption availability and metadata availability are separate.
Can I automate this? Use the saved Task, Apify API or an n8n/Make workflow. Keep a list of successfully processed video IDs downstream if you want to avoid processing them again; this Actor does not maintain a cross-run deduplication database.
Use caption data only where you have the necessary rights and follow YouTube's terms. The Actor does not retrieve private or unavailable tracks.
Related tools
- YouTube Channel RSS Scraper for recent videos in public channel feeds.
- YouTube Video Metadata for a separate video-metadata workflow.