YouTube Subtitles & Transcript Scraper API - Channels
Pricing
from $2.13 / 1,000 transcripts
YouTube Subtitles & Transcript Scraper API - Channels
Bulk YouTube transcript API. YouTube to text: get YouTube transcripts for videos, YouTube Shorts, playlists, channels: each YouTube video transcript, subtitles, captions as text, JSON, YouTube SRT, VTT, RAG chunks; YouTube translation; YouTube transcript MCP. YouTube channel, playlist transcripts.
Pricing
from $2.13 / 1,000 transcripts
Rating
4.0
(1)
Developer
Saulius AutomatesIT
Maintained by CommunityActor stats
1
Bookmarked
117
Total users
46
Monthly active users
4 days ago
Last modified
Share
Bulk YouTube transcript API: paste videos, Shorts, channels, playlists or search terms and get every transcript back as text, RAG chunks, SRT or VTT. $2.50 per 1,000 transcripts. Videos without captions cost nothing.
- Proven at scale. One customer ran 8,500 runs and 436,000+ videos through it in a single day.
- Whole channels and playlists in one input. A channel URL, playlist URL or search term expands to its videos automatically. Mix them freely with single video links.
- Pay only for delivered transcripts. No captions, private, deleted or blocked videos get a free diagnostic row, never a charge. Platform usage (compute, proxies) is included in the price.
- Ready for AI.
chunksgives paragraph-sized pieces with start and end times for RAG and embeddings;clean-textgives readable paragraphs for LLM prompts. Works from the API, Python, JavaScript, n8n, Make, Zapier and any MCP client (Claude, ChatGPT, Cursor). - Translate any transcript. Set
translateTo(en,es,de,pt-BR…) and a Spanish or Hindi video comes back in English, at the same price. - Filter by upload date.
publishedAfter: "7 days"on a channel limits results to recent videos. This is a date filter, not a record of previous runs: overlapping windows can return and charge for the same transcript again. - No YouTube API key, no login, no cookies.
Try it free: Apify's free plan includes $5 of usage credit every month, enough for about 2,000 transcripts, less the negligible Actor-start charge. Videos without captions incur no transcript charge.
Quick start
- Paste one or more YouTube links or search terms into Videos, channels, playlists, or searches.
- Pick a Transcript format (
textif unsure). - Click Start. Transcripts stream into the dataset as they are extracted. Export as JSON,
CSV, Excel, or download the
srt/vttcolumn as subtitle files.
{"videoUrls": ["https://www.youtube.com/@mkbhd"],"transcriptFormat": "clean-text","maxVideosPerSource": 50}
That returns the 50 newest uploads of the channel as paragraph text. Cost at the Free-plan price: at most $0.125.
What you can paste
| Input | Example | What happens |
|---|---|---|
| Video URL or ID | youtube.com/watch?v=dQw4w9WgXcQ, youtu.be/…, dQw4w9WgXcQ | One transcript |
| YouTube Shorts | youtube.com/shorts/… | One transcript |
| Live replay, embed | youtube.com/live/…, youtube.com/embed/… | One transcript |
| Channel | youtube.com/@handle, youtube.com/channel/UC… | The channel's uploads, newest first, up to maxVideosPerSource |
| Playlist | youtube.com/playlist?list=… | Every video in the playlist, up to maxVideosPerSource |
| Search term | machine learning tutorial | The top search results, up to maxVideosPerSource |
Pricing
$2.50 per 1,000 transcripts ($0.0025 each) on the Free plan. Paid Apify plans get the Store discount automatically: Bronze $2.375, Silver $2.25, Gold and above $2.125 per 1,000. Each run also has a $0.00005 start fee per GB of memory (about $0.00005 per run at the default 1 GB). Proxy and compute costs are included. That is the whole bill.
| Job | Transcripts delivered | Free plan | Business plan (Gold, -15%) |
|---|---|---|---|
| 100-video playlist, 92 have captions | 92 | $0.23 | $0.20 |
| 1,000-video channel backfill | ~1,000 | ~$2.50 | ~$2.13 |
| Daily check of 20 channels, 5 new videos each | 100 a day | ~$7.50 a month | ~$6.38 a month |
| 20,000-video research corpus | ~20,000 | ~$50.00 | ~$42.50 |
| 100,000 videos a month | ~100,000 | ~$250 | ~$212.50 |
Apify's Starter plan gets the Bronze discount, Scale gets Silver and Business gets Gold, applied automatically. The free plan's $5 monthly credit covers about 2,000 transcripts.
- Videos without captions cost $0, and so do private, deleted and blocked ones.
- Set Maximum total charge in the run options to hard-cap spending. The Actor stops cleanly at the cap and keeps everything it already delivered.
- For context, the two most-used YouTube transcript Actors on the Store charge $5 and $10 per 1,000 results (checked October 2026).
Translate YouTube transcripts
Set translateTo to a language code and every transcript comes back in that language:
{"videoUrls": ["https://www.youtube.com/@elrubiusOMG"],"translateTo": "en","maxVideosPerSource": 20}
- A real caption track in that language always wins. Otherwise you get YouTube's own machine translation of the best track, the same one the player's "Auto-translate" menu shows.
- Rows carry
translatedToandtranslatedFrom(for examplees), so you can tell translated text from original captions. - Same price per transcript. If YouTube refuses a translation (it rate limits them hard; the Actor
retries up to 20 times), you get the original-language transcript with
translationErrorset, never an empty row. - Works with every format:
text,clean-text,chunks,srtandvtt, so translated SRT subtitles are one field away.
Recent uploads: transcripts by upload date
publishedAfter and publishedBefore take a date (2026-10-01) or an age (7 days, 24 hours,
2 weeks, 1 month) and apply to channels and search terms:
{"videoUrls": ["https://www.youtube.com/@TED", "https://www.youtube.com/@veritasium"],"publishedAfter": "24 hours","transcriptFormat": "chunks"}
- Channels are listed newest first and stop at the first video older than the window, so older uploads are never fetched or charged.
- Searches use YouTube's own upload date filter, then the same check.
- YouTube lists only a rounded age ("1 month ago"); videos on the boundary are checked to the day.
Rows get
publishedTimeText. - A run that finds nothing new ends cleanly with "No videos in the date window" and costs only the start fee, so a daily schedule on 50 channels costs cents on quiet days.
- Single video links and playlists are not filtered.
- There is no cross-run deduplication. Repeating an input or using overlapping date windows can fetch and charge for the same video again. For strict deduplication, keep processed video IDs in your workflow and submit only unseen video links.
For a date range combine both: "publishedAfter": "2026-08-01", "publishedBefore": "2026-08-31".
Bulk and recurring workloads
The Actor is built for large, repeated jobs, not just one-off lookups:
- Throughput. 436,000+ videos processed for one customer in a day across 8,500 API runs. Results stream into the dataset while a run is still going.
- Predictable cost. One flat event with platform usage included, the plan discount applied automatically, and Maximum total charge per run as a hard ceiling.
- Nothing wasted. No-caption, private, deleted and blocked videos come back as free
failurerows, so a channel where 20% of videos lack captions costs 20% less. SetincludeFailurestofalseto drop those rows. - Safe to automate. The
SUMMARYrecord reports exactly what happened in every run, and a restarted run never charges twice for the same video.
Running a large or recurring workload (100,000+ videos a month)? Open an issue on the Issues tab with your volume and output format, and you will get help sizing runs and concurrency.
Output
One dataset item per video:
{"type": "transcript","videoId": "dQw4w9WgXcQ","url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ","title": "Rick Astley - Never Gonna Give You Up (Official Video)","channelName": "Rick Astley","channelId": "UCuAXFkgsw1L7xaCfnd5JJOw","lengthSeconds": 213,"viewCount": 1697651560,"language": "en","languageName": "English","isAutoGenerated": false,"transcriptFormat": "text","transcript": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪…","segmentCount": 61,"wordCount": 488,"availableLanguages": ["en", "en (auto)", "de-DE", "ja", "pt-BR", "es-419"],"sourceInput": "https://www.youtube.com/watch?v=dQw4w9WgXcQ","scrapedAt": "2026-08-11T21:35:20.991Z"}
Upload date, likes, comments and word-level timestamps
Two switches add fields to each row, at no extra charge:
includeVideoStats: trueaddspublishDate(2009-10-24),likeCount(19491698),commentCount(2400000) andcommentCountText(2.4M, as YouTube shows it). It reads the watch page once more per video; a field isnullwhen YouTube hides it (likes hidden, comments off).wordTimestamps: trueaddswords:[{ "text": "never", "start": 18.4, "end": 18.72 }, …], every word with its own start and end second, for karaoke style subtitles, cutting video at an exact word, or quoting the exact second. YouTube keeps per-word timing on auto-generated captions only, so manual captions give[]; setpreferAutoGenerated: trueto get word timing where a video has both.
Videos that can't produce a transcript get a type: "failure" row (free of charge) with an
error code such as NO_CAPTIONS, NO_MATCHING_LANGUAGE, or LOGIN_REQUIRED, so your pipeline
can handle them explicitly. A run report with per-outcome counts is saved under the SUMMARY key
of the run's key-value store.
Transcript formats
YouTube does not hand out prose. A caption track is a list of ~2-second display fragments, cut
mid-sentence, with sound cues ([Music], [Applause]) inline — and auto-generated (ASR) tracks
usually carry no punctuation at all. Pick the format that matches what you do next:
| Format | transcript contains | Use it for |
|---|---|---|
text | Caption fragments joined with spaces, exactly as YouTube sends them | Anything already doing its own cleanup |
clean-text | The same words, sound cues removed, split into paragraphs at pauses | Reading, summarising, prompting an LLM |
segments | [{ text, start, duration }] per caption fragment | Timing analysis, building your own subtitles |
chunks | [{ text, start, end, wordCount }] per paragraph | RAG, embeddings, timestamped citations |
srt / vtt | A ready-to-save subtitle file | Players, editors, upload back to YouTube |
clean-text and chunks share one cleanup pass: sound cues are dropped, and the words are
regrouped into paragraphs that break at any pause of 2 seconds or more in the audio, or at
chunkWords words (default 150) when the speaker never pauses. Each paragraph is capitalised and
given a closing full stop. chunks keeps the start/end timing of every paragraph, so a retrieval
hit can be linked straight back to youtube.com/watch?v=…&t=123s.
{"transcriptFormat": "chunks","transcript": [{ "text": "Hi I'm Matt I've worked at the RC now for 15 years as a patrolman today I'm going to talk you through going through a wheel change…", "start": 4.799, "end": 52.12, "wordCount": 155 },{ "text": "Off now as doing this when the vehicle's on the jack could cause the jack to dislodge…", "start": 50.12, "end": 97.759, "wordCount": 150 }],"chunkCount": 4}
What the cleanup does not do: it adds no punctuation inside a paragraph and corrects no
words. If YouTube's ASR wrote the RC for "the RAC", that is what you get — restoring punctuation
and fixing transcription errors needs a language model, which this Actor deliberately doesn't run
(it would cost far more than the transcript itself). Manual caption tracks are usually already
punctuated, and clean-text leaves that punctuation intact.
text and segments are unchanged from earlier builds — existing runs and integrations keep
their exact output.
Input
{"videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ","https://youtu.be/jNQXAC9IVRw","https://www.youtube.com/@mkbhd","https://www.youtube.com/playlist?list=PLFgquLnL59alCl_2TQvOiD5Vgm1hCaGSI","machine learning tutorial"],"languages": ["en"],"transcriptFormat": "text","maxVideosPerSource": 200}
Switching from another YouTube transcript Actor? Its input runs here as is: youtube_url, channel_url,
channel, videoUrl, urls, startUrls, max_videos, language, translate_to, targetLanguage,
start_date, end_date, searchKeywords (each keyword is searched on YouTube), maxPagesPerUrl (about 20 videos
a page), outputFormat (json, text, srt, vtt, captions, singleStringText), outputFormats, subType
and timestamps are all accepted and mapped to the fields below.
| Field | Default | Description |
|---|---|---|
videoUrls | — | Video URLs/IDs, channel URLs (@handle or /channel/UC…), playlist URLs, or search queries |
languages | ["en"] | Preferred transcript languages, in priority order |
transcriptFormat | text | text, clean-text, segments, chunks, srt, or vtt |
chunkWords | 150 | Target paragraph size for clean-text / chunks |
preferAutoGenerated | false | Prefer auto-generated (ASR) captions over manual ones |
fallbackToAnyLanguage | true | Use the best available track if no preferred language exists |
translateTo | — | Return every transcript in this language (en, es, pt-BR…), YouTube machine translation when no real track exists. Same price |
includeVideoDetails | false | Add description, tags, thumbnail URL and live flag to each row. No extra charge |
includeVideoStats | false | Add exact upload date, like count and comment count. One extra request per video, no extra charge |
wordTimestamps | false | Add words with each word's start and end second (auto-generated captions). No extra charge |
publishedAfter | — | Channels and searches: only videos uploaded on or after a date (2026-10-01) or within an age (7 days) |
publishedBefore | — | Channels and searches: only videos uploaded on or before a date or older than an age |
includeFailures | true | Emit uncharged diagnostic rows for videos without transcripts |
maxVideosPerSource | 200 | Cap per channel/playlist/search |
maxResults | 100000 | Global cap per run (spend guard) |
concurrency | 10 | Parallel video fetches (1–25) |
proxyStrategy | auto | auto ladder, or force datacenter-only / residential-only |
maxUnchargedRatio | 90 | Stop early if more than this % of the first 200+ videos return no transcript. Set 100 to disable |
maxResidentialAttempts | 0 | Cap on premium-proxy escalations per run. 0 = auto (25% of queued videos, min 500) |
Early stopping
Two safeguards end a run cleanly rather than working through a list that cannot pay its way.
Neither marks the run as failed, and both are reported in the SUMMARY record:
- No transcripts available — if more than
maxUnchargedRatio% of the first 200+ videos return no transcript, the run stops and says so. This almost always means the videos have no caption tracks. Normal jobs, including ones where many videos legitimately lack captions, are unaffected. - Premium proxy budget — YouTube bot-checks are retried on a residential proxy, which is much
more expensive. Once
maxResidentialAttemptsis spent the run continues on datacenter only.
SUMMARY reports stoppedAtUnchargedLimit, premiumProxyAttempts and premiumProxyBudget
alongside the existing counters.
Is there an official YouTube transcript API?
Not for other people's videos. The YouTube Data API's captions.download method "requires the user
to have permission to edit the video", needs OAuth with the youtube.force-ssl or
youtubepartner scope, and costs 200 quota units per call, so the default 10,000 units a day
allow 50 downloads (YouTube Data API reference).
| Option | Any public video | Works from a server | Cost |
|---|---|---|---|
YouTube Data API captions.download | No, only videos you can edit | Yes | Free, about 50 downloads a day on the default quota |
youtube-transcript-api (Python library) | Yes | Usually blocked on cloud IPs unless you add a residential proxy | Free, plus the proxy plan |
| This Actor | Yes, any public video with captions | Yes, proxies included | $2.50 per 1,000 transcripts; videos without captions free |
youtube-transcript-api blocked on AWS, GCP or a VPS? (RequestBlocked, IpBlocked)
The youtube-transcript-api Python library works on a laptop and then raises RequestBlocked or
IpBlocked once deployed, because YouTube blocks most IP ranges that belong to cloud providers.
The library's own README says so and recommends rotating residential proxies. This Actor does the
same lookup on Apify with proxy rotation built in, and segments returns the same
text, start and duration fields.
Before, with the library:
from youtube_transcript_api import YouTubeTranscriptApifetched = YouTubeTranscriptApi().fetch("dQw4w9WgXcQ", languages=["en"])for snippet in fetched:print(snippet.start, snippet.text)
After, with a drop-in function that fetches many videos in one run:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")def fetch_transcripts(video_ids, languages=("en",)):"""{video_id: [{"text", "start", "duration"}, ...]} for every video that has captions."""run = client.actor("sauliusautomatesit/youtube-transcript-scraper").call(run_input={"videoUrls": list(video_ids),"languages": list(languages),"transcriptFormat": "segments",})transcripts = {}for item in client.dataset(run.default_dataset_id).iterate_items():if item["type"] == "transcript":transcripts[item["videoId"]] = item["transcript"]else:print("no transcript:", item["videoId"], item["error"])return transcriptstranscripts = fetch_transcripts(["dQw4w9WgXcQ", "jNQXAC9IVRw"])for snippet in transcripts["dQw4w9WgXcQ"][:3]:print(snippet["start"], snippet["text"])
| youtube-transcript-api | This Actor |
|---|---|
fetch(video_id, languages=[...]) | videoUrls (IDs, links, channels, playlists) and languages |
snippet.text, .start, .duration | transcriptFormat: "segments": text, start, duration |
TextFormatter, SRTFormatter, WebVTTFormatter | transcriptFormat: text, clean-text, srt, vtt |
list(video_id) | availableLanguages on every row |
TranscriptsDisabled | free row with error: "NO_CAPTIONS" |
NoTranscriptFound | free row with error: "NO_MATCHING_LANGUAGE", or the best other track with fallbackToAnyLanguage |
RequestBlocked, IpBlocked | retried on a fresh proxy; a video still blocked is a free row, never a charge |
Tutorial: Python, AI agents and RAG
Four copy-paste recipes. Each one needs an Apify API token (Apify Console > Settings > API & Integrations); the free plan's monthly credit covers about 2,000 transcripts.
1. Python: every video of a channel in one call
$pip install apify-client
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("sauliusautomatesit/youtube-transcript-scraper").call(run_input={"videoUrls": ["https://www.youtube.com/@3blue1brown"],"maxVideosPerSource": 5,"transcriptFormat": "clean-text",})for item in client.dataset(run.default_dataset_id).iterate_items():if item["type"] == "transcript":print(item["title"], item["wordCount"], "words")else:print("skipped", item["videoId"], item["error"])
run.default_dataset_id is for apify-client 3.x; on 2.x write run["defaultDatasetId"].
The same code works with a playlist URL, a list of video links or a search term. To cap spend,
pass max_total_charge_usd=1 to .call() and the run stops cleanly at $1.
2. AI agents: one MCP URL, one tool
This URL gives any MCP client exactly one tool, this Actor, instead of a search over the whole Apify Store:
https://mcp.apify.com/?tools=sauliusautomatesit/youtube-transcript-scraper
Claude Code:
$claude mcp add --transport http youtube-transcripts "https://mcp.apify.com/?tools=sauliusautomatesit/youtube-transcript-scraper"
Cursor (~/.cursor/mcp.json), Claude Desktop, VS Code and other clients that take JSON:
{"mcpServers": {"youtube-transcripts": {"url": "https://mcp.apify.com/?tools=sauliusautomatesit/youtube-transcript-scraper","headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }}}}
Clients that support OAuth (Claude.ai custom connectors, ChatGPT) need only the URL and open an Apify sign-in on first use. Then ask things like:
- "Get the transcripts of the last 10 videos on @lexfridman and list every book mentioned, with the timestamp."
- "Pull the transcript of this video and turn it into a blog post outline."
The agent fills in videoUrls, maxVideosPerSource and transcriptFormat from the input schema.
Videos without captions come back as free failure rows, so the agent can say why instead of
guessing.
3. LangChain and CrewAI
pip install langchain-apifyexport APIFY_API_TOKEN=YOUR_APIFY_TOKEN
from langchain_apify import ApifyActorsToolyoutube = ApifyActorsTool("sauliusautomatesit/youtube-transcript-scraper")rows = youtube.invoke({"run_input": {"videoUrls": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"],"transcriptFormat": "chunks",}})
youtube is a normal LangChain tool, so it also goes straight into an agent's tool list.
4. RAG: timestamped chunks that cite the exact second
chunks returns paragraphs (broken at pauses of 2 seconds or more, or every chunkWords words),
each with its start time. Turn them into documents whose source link jumps to the moment:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("sauliusautomatesit/youtube-transcript-scraper").call(run_input={"videoUrls": ["https://www.youtube.com/@3blue1brown"],"maxVideosPerSource": 20,"transcriptFormat": "chunks","chunkWords": 150,})docs = []for item in client.dataset(run.default_dataset_id).iterate_items():if item["type"] != "transcript":continuefor i, chunk in enumerate(item["transcript"]):docs.append({"id": f"{item['videoId']}-{i}","text": chunk["text"],"metadata": {"title": item["title"],"channel": item["channelName"],"url": f"https://www.youtube.com/watch?v={item['videoId']}&t={int(chunk['start'])}s",},})print(len(docs), "chunks ready to embed")
Load docs into any vector store (Chroma, pgvector, Pinecone, Qdrant, LangChain or LlamaIndex
documents). When the retriever returns a chunk, metadata.url sends the reader to the exact
second. To keep a channel's index fresh, save the input as a Task with a daily schedule and
embed only video IDs you have not seen.
Other ways to call it
API (one call, results in the response)
curl -X POST "https://api.apify.com/v2/acts/sauliusautomatesit~youtube-transcript-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{ "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"], "transcriptFormat": "clean-text" }'
For large jobs, start the run asynchronously and read the dataset when it finishes; results stream into the dataset while the run is still going.
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('sauliusautomatesit/youtube-transcript-scraper').call({videoUrls: ['https://www.youtube.com/@mkbhd'],maxVideosPerSource: 10,transcriptFormat: 'srt',});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const item of items) {if (item.type === 'transcript') console.log(item.videoId, item.title, item.transcript.length, 'characters of SRT');else console.log('skipped', item.videoId, item.error);}
npm install apify-client first. The same input works with plain fetch against the API call above.
n8n, Make and Zapier
Use the Apify node or module, choose Run an Actor, enter
sauliusautomatesit/youtube-transcript-scraper, pass the input JSON, then read the dataset items
in the next step. transcript holds the text, type lets you filter out free failure rows.
Scheduled monitoring
Save your input as a Task with "publishedAfter": "24 hours" and give it a daily schedule in
Schedules on a list of channel URLs. Each run uses a rolling upload-date window; quiet
days cost only the start fee. Date boundaries and overlapping runs can return the same video again.
The Actor does not remember previous runs, so store processed video IDs in your workflow when you need strict deduplication.
For recurring queues of explicit video URLs, use the Python incremental transcript example. It remembers successful transcripts locally before submitting more requests. Keep the same state file between runs. The example does not discover channel uploads or deduplicate a channel expanded inside the Actor; failed or unprocessed videos remain eligible for retry.
Use cases
- AI and RAG pipelines. Turn channels into LLM-ready corpora with timestamped chunks.
- Content repurposing. Transcripts for blogs, newsletters, show notes and social clips.
- Media and brand monitoring. Schedule runs on channels and search terms.
- Research. Collect interview and lecture transcripts with timestamps for citation.
- Subtitles. Batch-download SRT/VTT files for re-upload, accessibility or translation.
Limitations
- Transcripts come from YouTube caption tracks (manual or auto-generated). Videos with captions
disabled can't be transcribed — they're reported as
NO_CAPTIONSand not charged. To transcribe the audio of videos without captions, try Media Transcriber (YouTube support there is best effort). - Live streams in progress and age-restricted videos are generally not extractable.
- Channel expansion returns the channel's regular uploads (newest first), up to
maxVideosPerSource.
FAQ
Does YouTube have an official transcript API? Not for other people's videos. The YouTube Data API only lets you download captions for videos you have permission to edit. This Actor reads the public caption tracks YouTube shows in its player, for any public video.
Why does youtube-transcript-api raise RequestBlocked on my server? YouTube blocks most cloud provider IPs. The section "youtube-transcript-api blocked on AWS, GCP or a VPS?" above shows how to swap the call for this Actor and keep your segment handling.
How do I get a YouTube transcript in Python? pip install apify-client and use the
fetch_transcripts function above, or tutorial recipe 1 for a whole channel.
How do I get the transcripts of a whole YouTube channel? Paste the channel URL
(youtube.com/@handle) and set maxVideosPerSource to the number of uploads you want. Playlists
and search terms work the same way.
How much does it cost to transcribe 10,000 YouTube videos? About $25 on the Free plan and $21.25 on Gold, minus every video without captions, which is free.
Do I need a YouTube API key or cookies? No. The Actor uses YouTube's public endpoints.
What languages are supported? Anything YouTube has captions for. Set languages to your
priority list; availableLanguages on every item shows what exists.
Can I translate a YouTube transcript to English (or any language)? Yes. Set translateTo to
en (or es, de, fr, pt-BR…). You get YouTube's machine translation when the video has no
track in that language, at the same price. See Translate YouTube transcripts.
How do I filter a channel to recent videos? Set publishedAfter to 7 days (or a
date). Older uploads are excluded, but overlapping scheduled runs can return and charge for the same videos again. See
Recent uploads.
Can I get timestamps? Yes. Segment-level timestamps (a few seconds each) via segments,
srt or vtt, or paragraph-level ones via chunks.
The transcript is one long block with no punctuation — can you fix that? Set
transcriptFormat to clean-text or chunks. That removes sound cues and breaks the text into
paragraphs at pauses in the audio. Punctuation within a sentence comes from YouTube: manual
caption tracks have it, auto-generated ones usually don't, and this Actor doesn't run a language
model to invent it. See Transcript formats.
What happens on a video that's private or deleted? A free failure row with the error code,
never a charge.
Related Actors
- Google Ads Transparency API: every Google and YouTube ad an advertiser runs, with the YouTube link of each video ad. Feed those links into this Actor to get the script of every competitor video ad.
- Telegram Channel Scraper: every post from public Telegram channels as clean rows, for the same research, monitoring and RAG pipelines.
- Google Trends API: search interest over time for the topics your videos cover, to pick what to transcribe or publish next.
- Bing Search API: live web search results for the same AI agents and RAG pipelines, now that Microsoft has retired its own Bing API.
- Bilibili API: videos, stats and danmaku from China's biggest video platform.
Support and reviews
Found a problem or missing a feature? Open an issue on this Actor's Issues tab; issues are answered within 24 hours. If this Actor saves you time, please leave a short review. Reviews are how other people find it.