Export public YouTube captions as transcript text and optional timestamped segments. Supply video URLs or IDs, request a caption language, and download JSON or CSV for research, summaries, search indexes, and RAG.
This Actor retrieves existing public captions and may request a YouTube-provided translation when supported. It does not transcribe audio with AI when captions are missing or run its own translation model.
Quick start
Paste one public video URL, keep maxVideos small, and inspect captionsAvailable, error, and transcriptText before using the output.
{
"videoUrls": [
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
],
"language": "en",
"includeTimestamps": true,
"includeMetadata": true,
"maxVideos": 1
}
Example output
Illustrative shortened success record; the caption text below is not taken from the linked video. Optional metadata is omitted in this example.
{
"videoId": "dQw4w9WgXcQ",
"videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"language": "en",
"isAutoGenerated": false,
"transcriptText": "Illustrative caption text.",
"segments": [
{
"start": 0,
"duration": 2.1,
"text": "Illustrative caption text."
}
],
"captionsAvailable": true
}
What does it return?
One result row identifies each processed video. Successful results can include combined caption text, segment text, timing in seconds, the selected language, and available title/channel metadata. Unavailable captions or failed videos produce diagnostic rows; other videos in the batch can still complete.
Who is it for?
- Research teams: search and compare public talks, lectures, and interviews.
- Content teams: review webinar or demo captions and prepare source-linked summaries.
- RAG builders: chunk transcript text and retain video URLs and timestamps.
- Media reviewers: check language availability and caption quality before downstream use.
Input settings
| Setting | JSON key | Type / default | What it does |
|---|---|---|---|
| YouTube video URLs | videoUrls |
array / not set | Public YouTube watch, shorts, live, embed, or youtu.be URLs to extract transcripts from. |
| Video IDs | videoIds |
array / [] |
Optional raw 11-character YouTube video IDs. Use this instead of URLs if you already have IDs. |
| Preferred caption language | language |
string / "en" |
Preferred caption language, such as en, es, de, or fr. The Actor may request a YouTube-provided translation when supported, then fall back to another available track. Check the returned language. |
| Include timestamps | includeTimestamps |
boolean / true |
Include start and duration values for every transcript segment. |
| Include video metadata | includeMetadata |
boolean / true |
Include title, channel name, duration, and thumbnail URL when YouTube exposes them publicly. |
| Maximum videos | maxVideos |
integer / 5 |
Maximum number of videos to process in this run. Keep this low for the first test run. Minimum 1; maximum 500. |
| Proxy configuration | proxyConfiguration |
object / {"useApifyProxy":true,"apifyProxyGroups":["RESIDENTIAL"]} |
Optional proxy configuration for blocked requests. The input default selects Apify Residential Proxy; the current Actor tries direct access first and uses the configured proxy as fallback. Check your run cost before scaling. |
URL and language behavior
Accepted inputs include watch, Shorts, live, embed, and youtu.be URLs. Put raw 11-character IDs in videoIds. Neither input mode discovers all videos on a channel.
The Actor first looks for the requested language or a related language variant. When supported, it may request a YouTube-provided caption translation. If that request fails or is unavailable, another public track can be selected; always check the returned language. With includeTimestamps: false, segments still contain text but timing fields are omitted. Metadata fields may be omitted when disabled or unavailable.
Tips and limits
- Check availability: private, deleted, members-only, region-restricted, or captionless videos may not yield transcript text.
- Check accuracy: automated captions can contain recognition errors; verify quotes against the original video.
- Control batch size: use
maxVideosto cap work, especially when proxy fallback is needed. - Handle partial results: inspect
erroreven when the run completes; do not index an error row as a transcript. - Respect content rights: public accessibility does not grant redistribution or model-training rights. Use captions only where your processing is permitted.
API usage
Use your Apify API token through the APIFY_TOKEN environment variable. Node.js and Python examples wait for the run and read its first dataset page; paginate the dataset for larger exports.
Node.js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/youtube-transcript-scraper').call({
"videoUrls": [
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
],
"language": "en",
"includeTimestamps": true,
"includeMetadata": true,
"maxVideos": 1
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Python
import json
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = json.loads('''{
"videoUrls": [
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
],
"language": "en",
"includeTimestamps": true,
"includeMetadata": true,
"maxVideos": 1
}''')
run = client.actor("fetch_cat/youtube-transcript-scraper").call(run_input=run_input)
print(client.dataset(run["defaultDatasetId"]).list_items().items)
cURL
Save the quickstart JSON as input.json. This request starts a run asynchronously; use its returned run ID to check completion and its defaultDatasetId to retrieve results.
curl -X POST "https://api.apify.com/v2/acts/fetch_cat~youtube-transcript-scraper/runs" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @input.json
MCP and AI agents
Use the official Apify MCP server, not a separate custom server. The focused URL below selects this Actor. Authenticate with Apify when your client prompts you; configuration syntax and OAuth support depend on the client.
Claude Code
claude mcp add --transport http apify "https://mcp.apify.com?tools=fetch_cat/youtube-transcript-scraper"
HTTP-capable MCP client configuration
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=fetch_cat/youtube-transcript-scraper"
}
}
}
Example prompt: "Extract captions from these two public YouTube URLs. Summarize successful transcripts with timestamped source references and list unavailable videos separately."
Use the same input keys as the input table. Review the returned source URLs and any error or availability fields before using results in an automated summary.
Common workflows
- Knowledge-base updates: submit newly published video URLs, then send successful transcripts to your document or vector store.
- Scheduled reviews: schedule a fixed input list with Apify and compare exports downstream; channel discovery is a separate step.
- Timestamped summaries: ask your downstream model to cite the video URL and segment start time for each claim.
Support
If a run fails or output looks wrong, open an issue from the Actor page. Include the Apify run ID or run URL, non-sensitive input JSON, expected output, actual output, and one reproducible public URL (or the exact search input). Do not share tokens, cookies, passwords, or private data.