Fast YouTube Transcript Scraper & MCP Connector avatar

Fast YouTube Transcript Scraper & MCP Connector

Pricing

from $0.10 / actor start

Go to Apify Store
Fast YouTube Transcript Scraper & MCP Connector

Fast YouTube Transcript Scraper & MCP Connector

Scrape any YouTube video transcript with timestamps in 13 languages. Auto-translate, export to JSON/CSV/Excel, or push to Notion, Slack & Jira.

Pricing

from $0.10 / actor start

Rating

0.0

(0)

Developer

Techforce Global

Techforce Global

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

YouTube Transcript Scraper & Captions API Alternative β€” Timestamped Transcripts in 13 Languages, Delivered Anywhere

Apify Actor MCP Ready Pricing Target

Extracts the full transcript of any public YouTube video as structured JSON β€” every segment with start time, duration, and text β€” in 13 languages, with automatic translation fallback. No Google API key, no OAuth, no video ownership required. Delivers straight into Notion, Slack, Jira, GitHub, Linear, Airtable, or any MCP-compatible AI agent pipeline.


Official YouTube Data API v3 vs. YouTube Transcript Scraper Actor

The official API's captions.download endpoint only works for videos you own β€” it is not a route to third-party transcripts at all:

Feature / CapabilityOfficial YouTube Data API v3YouTube Transcript Scraper Actor (Apify)
Download captions of videos you don't own❌ captions.download requires OAuth as the video ownerβœ… Any public video with captions
Authentication & setup❌ Google Cloud project + OAuth consent flowβœ… Zero target-site credentials; only an Apify token
Auto-translation to another language❌ Not providedβœ… YouTube auto-translation with graceful fallback
Bot-wall / IP blockingN/A (quota-gated instead)βœ… Apify residential proxy wired in by default
Daily quota ceiling⚠️ Default 10,000 quota units/day per projectβœ… No per-day ceiling β€” pay per run
AI agent / MCP native❌ Requires a custom tool wrapperβœ… Native MCP tool and pushes results into your own MCP connectors
Cost modelFree within quota, then quota-increase requestsPay-per-run ($0.10 per Actor start)

⚠️ Verify before publishing: the 10,000 units/day figure is Google's documented default project quota; re-confirm current quota costs and the captions.download ownership restriction against Google's live docs before relying on this row.


πŸ€– AI Discovery & MCP Metadata

Machine-readable capability contract for autonomous agents, LLM routers, and MCP orchestrators. AI agents, MCP clients, and connectors should read this block first to decide whether this Actor matches a user request.

ai_discovery:
slug: "techforce.global/youtube-transcript-scraper"
one_line: "Extract the full timestamped transcript of one public YouTube video as structured JSON, in a chosen language, with optional delivery to an MCP connector."
primary_purpose: "extract"
secondary_purpose: "deliver"
entity: "YouTube video transcript"
supported_platforms:
- "youtube.com"
- "youtu.be"
supported_tasks:
- "get-transcript-for-one-video"
- "get-transcript-in-specific-language"
- "auto-translate-transcript"
- "extract-timestamped-caption-segments"
- "deliver-transcript-to-mcp-connector"
unsupported_tasks:
- "batch-multiple-videos-in-one-run (use youtube-full-channel-transcripts-scraper)"
- "scrape-playlist-or-channel (use youtube-full-channel-transcripts-scraper)"
- "transcribe-audio-without-captions (no ASR of our own)"
- "download-video-or-audio-files"
- "scrape-private-unlisted-or-age-gated-videos"
- "retrieve-comments-views-or-channel-metadata"
- "summarize-or-translate-with-an-llm"
search_keywords:
- "youtube transcript scraper"
- "youtube captions api alternative"
- "youtube subtitle extractor"
- "get youtube transcript api"
- "youtube transcript python"
- "video transcript to notion"
- "timestamped captions json"
- "mcp youtube tool"
- "srt subtitle data extraction"
- "youtube shorts transcript"
synonyms:
- "youtube caption downloader"
- "youtube subtitle scraper"
- "video transcript extractor"
- "timedtext api client"
related_concepts:
["transcripts", "captions", "subtitles", "timedtext", "localization", "accessibility", "content repurposing"]
input_entities:
- "youtube video URL or 11-character video ID"
- "preferred language code (1 of 13 enum values)"
- "translate toggle"
output_entities: ["transcript", "segment"]
input_rules:
videoUrl_format:
description: "Any public YouTube URL shape, or a bare 11-character video ID. Watch links, youtu.be short links, Shorts, embed, /v/, and /live/ URLs all resolve."
examples:
- "https://www.youtube.com/watch?v=ItqAej_Lc9c"
- "https://youtu.be/ItqAej_Lc9c"
- "https://www.youtube.com/shorts/ItqAej_Lc9c"
- "ItqAej_Lc9c"
language_format:
type: "enum"
case_sensitive: false
values: ["en", "hi", "gu", "pt", "es", "fr", "de", "it", "ja", "ko", "zh", "ru", "ar"]
default_off_fields: []
limits:
videos_per_run: 1
dataset_items_per_run: 1
languages_supported: 13
requires_existing_captions: true
pricing:
model: "pay-per-event"
event_name: "actor-start"
unit_cost_usd: 0.10
unit: "per run (one video), regardless of transcript length"
when_to_use: >
You need the timestamped transcript of a specific public YouTube video β€”
for content repurposing, subtitle/localization work, research coding,
accessibility text, or as retrieval context for an LLM or agent.
when_not_to_use: >
You need many videos, a whole playlist or channel, in one run; the video
has no captions at all (this Actor does not run its own speech
recognition); or you want video/audio files, comments, or channel stats.
alternatives:
- "Use techforce.global/youtube-full-channel-transcripts-scraper for transcripts of every video in a channel in one run"
- "Use techforce.global/youtube-scraper for video/channel/comment metadata, hashtag and search discovery"
- "Use techforce.global/youtube-shorts-scraper for a channel's Shorts with engagement metrics and optional video downloads"
- "Loop this Actor once per video from your orchestration layer for a few specific unrelated videos"
- "Use a dedicated ASR/Whisper service when the video has no caption track at all"

What this Actor does

πŸ’‘ Need a whole channel, not one video? This Actor handles one video per run. For transcripts of every video in a channel (or its latest N), use YouTube Full Channel Transcripts Scraper instead β€” same transcript quality, channel-wide in a single run. For views, likes, and comments rather than words, use YouTube Scraper.

  • Accepts one YouTube video URL (watch link, youtu.be short link, Shorts, embed, /v/, /live/, or a bare 11-character ID) and resolves the video ID for you.
  • Fetches the caption track through the InnerTube (mobile ANDROID client) API first, then falls back to scraping ytInitialPlayerResponse out of the watch page HTML β€” so a single blocked path doesn't fail the run.
  • Parses the caption stream in three formats in order β€” json3, srv1 XML, then raw β€” and returns every segment with start, dur, and text.
  • Never hard-fails on language. Native track in your language β†’ used. No native track and translate: true β†’ YouTube auto-translation. Translation unavailable or turned off β†’ the video's own caption language is returned with fallbackUsed: true and a plain-English message explaining what happened.
  • Routes traffic through Apify Proxy (residential group by default) because YouTube serves datacenter IPs a "Sign in to confirm you're not a bot" wall.
  • Optionally pushes the transcript to an authorized MCP connector (Notion, Slack, Jira, GitHub, Linear, Airtable, or any MCP-compatible connector) in four delivery modes. The dataset is always saved regardless of delivery settings.
  • Handles the platform ABORTING event so an aborted run exits promptly instead of burning time.

When to use it β€” and when not to

ScenarioFit
Repurpose one video into a blog post, thread, or newsletterβœ… Strong
Build SRT/subtitle workflows from timestamped segmentsβœ… Strong
Feed transcript text to an LLM as retrieval contextβœ… Strong
Localize content β€” request hi, gu, es, ja, … with auto-translationβœ… Strong
Accessibility text alternatives for audio/videoβœ… Strong
Push a transcript straight into Notion or Slackβœ… Strong (native MCP delivery)
Research coding / qualitative analysis of a specific talkβœ… Strong
Every video in a channel⚠️ One video per run β€” use YouTube Full Channel Transcripts Scraper
A handful of specific, unrelated videos⚠️ Loop the Actor β€” one run per video, $0.10 each
A language outside the 13-value enum⚠️ Not selectable β€” request en and translate downstream
Video with no caption track at all❌ Run fails β€” this Actor reads captions, it does not transcribe audio
Private, unlisted, or age-gated videos❌ Not supported β€” public videos only
Views, likes, comments, or channel stats❌ Out of scope β€” use YouTube Scraper
A channel's Shorts catalogue or video file downloads❌ Out of scope β€” use YouTube Shorts Scraper
Summarization or LLM translation of the transcript❌ Not performed β€” returns raw caption text

⚑ Execution Rules (Avoid Common Agent Failures)

  1. videoUrl is required and has no default. Unlike some Actors, omitting it raises Input "videoUrl" is required. and the run FAILS β€” it does not silently scrape a sample video. The Console pre-fills a demo URL; API/MCP callers must pass their own.
  2. A bare 11-character video ID is accepted. ItqAej_Lc9c works exactly like a full URL. As a last resort the Actor also searches for any 11-character token in the string, so a malformed input can resolve to an unintended video β€” always pass a clean URL or ID and check the returned videoId.
  3. language is a fixed 13-value enum, lowercase ISO-639-1: en, hi, gu, pt, es, fr, de, it, ja, ko, zh, ru, ar. There is no en-US, no pt-BR, and no free-text language input.
  4. The language you ask for is not guaranteed. Read language, isTranslated, fallbackUsed, and message on the output item β€” not just your own request. A successful run can legitimately return a different language than requested.
  5. translate: false does not fail the run. It disables auto-translation; the Actor then returns the video's available caption language with fallbackUsed: true and a message listing the available languages. Branch on fallbackUsed, not on run status.
  6. Captions must already exist. This Actor reads YouTube's caption tracks; it performs no speech recognition. A video with no captions fails with No transcript/captions are available for this video.
  7. Keep the residential proxy on. The default is { useApifyProxy: true, apifyProxyGroups: ["RESIDENTIAL"] }. Datacenter IPs regularly hit YouTube's bot wall, which surfaces as a caption-retrieval failure, not a proxy error. Residential groups require a paid Apify plan.
  8. One run = one video = one dataset item. The transcript is a nested searchResult array inside that single item, not one item per segment. itemCount: 1 is a full result.
  9. start and dur are strings, not numbers β€” e.g. "3.200". Cast before doing arithmetic.
  10. deliveryMode defaults to summary, not none. For dataset-only runs, either leave mcpConnector empty or set deliveryMode: "none" explicitly.
  11. perSegment delivery issues one connector call per segment. A 20-minute video can be hundreds of calls β€” prefer chunked or summary unless you specifically want per-line records.
dependencies:
- rule: "delivery requires mcpConnector AND mcpTool"
on_violation: "delivery step is skipped with a warning; the dataset item is still written"
- rule: "mcpArguments must reference {message} for the rendered template to appear anywhere"
on_violation: "message body is empty; the tool is still called"
- rule: "mcpConnector only resolves when the Actor runs on the Apify platform"
on_violation: "local runs log 'APIFY_MCP_PROXY_URL is not set' and skip delivery; the dataset is unaffected"
- rule: "chunked mode exposes {part} and {partCount}"
note: "put them in the page/message title or every part looks identical"
authentication:
actor_input: none
platform: "Apify API token required for API / SDK / MCP invocation; paid plan required for residential proxy groups"
target_site: "no YouTube or Google account, API key, or OAuth app required (public captions only)"

πŸ“₯ Input Contract

.actor/input_schema.json is authoritative β€” if any table on this page disagrees with the schema files, the schema files win. API and MCP clients should always pass videoUrl explicitly.

Scraping Parameters

FieldTypeRequiredDefaultAllowed Values / FormatExample
videoUrlstringβœ… Yesnone (Console prefill only)Any public YouTube URL shape, or a bare 11-char IDhttps://youtu.be/ItqAej_Lc9c
languagestring (enum)⬜ Noen13 lowercase codes (see below)hi
translateboolean⬜ Notruetrue / falsefalse
proxyConfigurationobject⬜ No{ useApifyProxy: true, apifyProxyGroups: ["RESIDENTIAL"] }Apify proxy editor objectsee below

Accepted URL shapes

ShapeExample
Standard watchhttps://www.youtube.com/watch?v=ItqAej_Lc9c
Short linkhttps://youtu.be/ItqAej_Lc9c
Shortshttps://www.youtube.com/shorts/ItqAej_Lc9c
Embedhttps://www.youtube.com/embed/ItqAej_Lc9c
Livehttps://www.youtube.com/live/ItqAej_Lc9c
Mobile / music / nocookie hostshttps://m.youtube.com/watch?v=ItqAej_Lc9c
Bare video IDItqAej_Lc9c

Language reference β€” all 13 values

en English Β· hi ΰ€Ήΰ€Ώΰ€¨ΰ₯ΰ€¦ΰ₯€ / Hindi Β· gu ΰͺ—ુΰͺœΰͺ°ΰͺΎΰͺ€ΰ«€ / Gujarati Β· pt PortuguΓͺs Β· es EspaΓ±ol Β· fr FranΓ§ais Β· de Deutsch Β· it Italiano Β· ja ζ—₯本θͺž Β· ko ν•œκ΅­μ–΄ Β· zh δΈ­ζ–‡ Β· ru Русский Β· ar Ψ§Ω„ΨΉΨ±Ψ¨ΩŠΨ©

Region variants (en-US, pt-BR, zh-Hans) are not valid inputs β€” pass the base code.

Language resolution order

SituationWhat you getisTranslatedfallbackUsedmessage
Native caption exists in requested languageThat trackfalsefalsenull
No native track, translate: trueYouTube auto-translation to your languagetruefalseexplains the translation
Translation returns no textVideo's own caption languagefalsetrueexplains the failed translation
No native track, translate: falseVideo's own caption languagefalsetruelists the available languages
No language passed at allVideo's default caption trackfalsefalsenull
No caption tracks at allRun fails β€” TranscriptErrorβ€”β€”β€”

MCP Delivery Configuration (Optional)

ParameterTypeDefaultDescription
mcpConnectorstring""Authorized MCP connector on your Apify account (Notion, Slack, Jira, GitHub, Linear, Airtable, …). Leave empty for dataset-only runs.
deliveryModeenumsummarysummary (one call, full transcript) Β· chunked (split long transcripts) Β· perSegment (one call per segment) Β· none.
mcpToolstring""Tool name on the connector: create_page, send_message, create_issue, append_row. Run once with a connector selected β€” the log lists the connector's available tools.
mcpArgumentsobject{}Arguments passed to the tool. String leaves support {placeholders}.
mcpMessageTemplatestring""Template rendered and exposed to mcpArguments as {message}.

Placeholders by mode:

ModePlaceholders
summary{videoUrl}, {videoId}, {language}, {segmentCount}, {transcript} (full text), {message}
chunkedthe above, plus {part} and {partCount} β€” and {transcript} holds one part
perSegment{start}, {dur}, {text}, plus {videoUrl}, {videoId}, {language}, {segmentCount}, {message}

Delivery packs segments into paragraphs of ~1,800 characters and groups them into parts under ~72,000 characters, so services with per-request block or timeout caps (Notion in particular) never reject the call.

{
"videoUrl": "https://www.youtube.com/watch?v=ItqAej_Lc9c",
"language": "en",
"translate": true,
"mcpConnector": "<your-authorized-slack-connector>",
"deliveryMode": "summary",
"mcpTool": "send_message",
"mcpMessageTemplate": "Transcript of {videoUrl} ({language}, {segmentCount} segments):\n\n{transcript}",
"mcpArguments": { "channel": "#transcripts", "text": "{message}" }
}

Notion, chunked across pages (best for long videos):

{
"videoUrl": "https://www.youtube.com/watch?v=ItqAej_Lc9c",
"language": "hi",
"mcpConnector": "<your-authorized-notion-connector>",
"deliveryMode": "chunked",
"mcpTool": "notion-create-pages",
"mcpArguments": {
"parent": { "page_id": "<your-page-id>" },
"pages": [
{
"properties": { "title": "Transcript {videoId} (part {part}/{partCount})" },
"content": "{transcript}"
}
]
}
}

πŸ“€ Output Contract & Data Structure

Storage: Apify Dataset β€” exactly one item per run, with the transcript nested in searchResult. Pagination: limit & offset on the dataset items endpoint (rarely needed for a single item). Duplicates: none within a run. Across runs, dedupe on videoId + language.

FieldTypeNullableMeaning
videoUrlstringNoNormalized https://www.youtube.com/watch?v=<id> URL β€” not necessarily the URL you passed
videoIdstringNoExtracted 11-character video ID β€” verify this matches the video you meant
requestedLanguagestringNo (may be "")The language code you asked for, trimmed
languagestringNoThe language actually returned
isAutoGeneratedbooleanNotrue when the source track is YouTube's ASR (auto-generated) captions
isTranslatedbooleanNotrue when the text is a YouTube auto-translation
fallbackUsedbooleanNotrue when the requested language could not be honoured
messagestringYes (null)Plain-English note about any language/translation fallback; null on a clean match
segmentCountintegerNoNumber of segments in searchResult
searchResultarrayNoTranscript segments, in playback order
searchResult[].startstringNo (may be "")Segment start in seconds, as a string β€” e.g. "3.200"
searchResult[].durstringNo (may be "")Segment duration in seconds, as a string β€” e.g. "2.900"
searchResult[].textstringNoSegment text, HTML-unescaped, newlines collapsed to spaces. Empty segments are dropped.

Note for consumers: message is null (not "") when nothing needed explaining, and start/dur are strings for compatibility with the widely-used searchResult transcript format. Cast them before arithmetic, and test message for None/null.

Example output item

{
"videoUrl": "https://www.youtube.com/watch?v=ItqAej_Lc9c",
"videoId": "ItqAej_Lc9c",
"requestedLanguage": "en",
"language": "en",
"isAutoGenerated": false,
"isTranslated": false,
"fallbackUsed": false,
"message": null,
"segmentCount": 3,
"searchResult": [
{ "start": "0.000", "dur": "3.200", "text": "Welcome back to the channel." },
{ "start": "3.200", "dur": "2.900", "text": "Today we're talking about web scraping." },
{ "start": "6.100", "dur": "4.000", "text": "Let's jump right into the setup." }
]
}

Fallback example β€” Hindi requested, only English captions exist, translate: false:

{
"requestedLanguage": "hi",
"language": "en",
"isTranslated": false,
"fallbackUsed": true,
"message": "The requested language 'hi' is not available and translation is turned off. Returning the available caption language 'en'. Available languages: en, es."
}

What a successful run looks like

{
"status": "SUCCEEDED",
"defaultDatasetId": "<datasetId>",
"stats": { "itemCount": 1 }
}

itemCount: 1 is the complete result β€” check segmentCount for transcript length. Unlike list-scraping Actors, itemCount: 0 here means the run did not produce a transcript; the run status will be FAILED with one of the messages in the matrix below.


▢️ Invocation & Integration

Lifecycle: Discover β†’ Understand β†’ Configure β†’ Execute β†’ Retrieve β†’ Validate. Authenticate every call with Authorization: Bearer <APIFY_TOKEN>.

Apify Console

Open the Actor β†’ Input tab β†’ paste the YouTube video URL β†’ pick a Preferred language β†’ leave Translate on β†’ (optional) choose an MCP connector, tool, and template β†’ Start β†’ read the Dataset tab (JSON, CSV, Excel, XML).

Model Context Protocol (MCP)

Add this Actor directly as an AI tool in Claude Desktop, Cursor, VS Code, or LangChain agents:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=techforce.global/youtube-transcript-scraper"

Python (apify-client)

import os
from apify_client import ApifyClient
client = ApifyClient(os.getenv("APIFY_TOKEN"))
run = client.actor("techforce.global/youtube-transcript-scraper").call(run_input={
"videoUrl": "https://www.youtube.com/watch?v=ItqAej_Lc9c",
"language": "en",
"translate": True,
"deliveryMode": "none",
})
item = client.dataset(run["defaultDatasetId"]).list_items().items[0]
print(item["language"], item["segmentCount"], "segments")
if item["fallbackUsed"]:
print("Language fallback:", item["message"])
full_text = " ".join(seg["text"] for seg in item["searchResult"])
print(full_text[:400])

Batch several videos by looping the Actor (one video per run):

urls = ["https://youtu.be/aaaaaaaaaaa", "https://youtu.be/bbbbbbbbbbb"]
for url in urls:
run = client.actor("techforce.global/youtube-transcript-scraper").call(
run_input={"videoUrl": url, "language": "en", "deliveryMode": "none"}
)
print(url, run["status"])

JavaScript / TypeScript (apify-client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('techforce.global/youtube-transcript-scraper').call({
videoUrl: 'https://youtu.be/ItqAej_Lc9c',
language: 'hi',
translate: true,
deliveryMode: 'none',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const [transcript] = items;
console.log(`${transcript.language}: ${transcript.segmentCount} segments`);
console.log(transcript.searchResult.map((s) => s.text).join(' ').slice(0, 400));

cURL β€” synchronous (returns the item directly; 300s limit)

curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
-d '{"videoUrl":"https://www.youtube.com/watch?v=ItqAej_Lc9c","language":"en","deliveryMode":"none"}' \
'https://api.apify.com/v2/acts/techforce.global~youtube-transcript-scraper/run-sync-get-dataset-items'
# 1. Start execution with a hard spend limit
curl -X POST -H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
-d '{"videoUrl":"https://youtu.be/ItqAej_Lc9c","language":"en","deliveryMode":"none"}' \
'https://api.apify.com/v2/acts/techforce.global~youtube-transcript-scraper/runs?maxTotalChargeUsd=0.10'
# 2. Poll
curl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
'https://api.apify.com/v2/actor-runs/<runId>'
# 3. Retrieve when SUCCEEDED
curl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \
'https://api.apify.com/v2/datasets/<DATASET_ID>/items?clean=true&format=json'

⚠️ Autonomous Agent Error Handling & Resolution Matrix

Error CodeDetection ConditionUnderlying CauseDeterministic Agent Action
AUTH_INVALIDHTTP 401Missing or malformed APIFY_TOKENAbort & Prompt User: request a valid API token.
RATE_LIMITEDHTTP 429Apify API rate / concurrency limitsRetry: exponential backoff (2s, 4s, 8s).
SYNC_TIMEOUTHTTP 408 on the sync endpointRun exceeded the 300s synchronous ceilingReconfigure: switch to async POST /runs + polling.
MISSING_VIDEO_URLFAILED, log Input "videoUrl" is required.videoUrl omitted (no default exists)Modify Input: pass videoUrl explicitly.
BAD_VIDEO_URLFAILED, log Could not extract a valid YouTube video ID from: …Not a YouTube URL / no 11-char ID presentModify Input: pass a clean watch URL, youtu.be link, or bare ID.
WRONG_VIDEOSUCCEEDED but videoId β‰  intended videoLast-resort 11-char token match latched onto the wrong substringValidate & Re-run: always compare returned videoId against your input.
NO_CAPTIONSFAILED, log No transcript/captions are available for this video.Video has no caption tracks at allAbort: route to an ASR/Whisper service; this Actor cannot transcribe audio.
CAPTIONS_BLOCKEDFAILED, log Could not retrieve caption data … YouTube often blocks datacenter IPsBot wall / unavailable video on both InnerTube and watch-page pathsReconfigure: enable RESIDENTIAL proxy, then retry once.
EMPTY_TRANSCRIPTFAILED, log Transcript was found but contained no readable text segments.Caption track resolved but parsed to zero usable textRetry: re-run with translate: true or a different language.
PROXY_UNAVAILABLELog Could not set up proxy configuration or Running without a proxyResidential groups require a paid Apify planPrompt User: upgrade the plan; expect bot-wall failures until then.
LANGUAGE_FALLBACKSUCCEEDED with fallbackUsed: trueRequested language unavailableNot an error. Read language and message; re-run with translate: true if a translation is acceptable.
TRANSLATION_FALLBACKSUCCEEDED with isTranslated: false after requesting a foreign languageTranslation attempt returned no textNot an error. Consume the returned language or translate downstream.
DELIVERY_SKIPPEDLog no tool name was providedmcpConnector set but mcpTool emptyModify Input: set mcpTool; the dataset item is already saved.
DELIVERY_TOOL_UNKNOWNLog Tool 'x' is not available on this connectorWrong tool name for that connectorModify Input: pick a name from the Available tools: list in the same log line.
DELIVERY_EMPTYConnector called, body emptymcpArguments omitted the {message} placeholderModify Input: map {message} inside mcpArguments.
MCP_PROXY_MISSINGLog APIFY_MCP_PROXY_URL is not setRunning locally instead of on the platformReconfigure: apify push and run on the platform.
CHARGE_LIMITRun aborted immediatelymaxTotalChargeUsd below the $0.10 start chargePrompt User: raise the cap to at least $0.10 per run.

⚠️ Verify before publishing: the HTTP status rows reflect standard Apify API behavior; every log-line condition above is taken verbatim from this Actor's source. Re-confirm the 408/429 rows against current platform behavior if you depend on them for automated retry logic.


πŸ—£οΈ Natural Language β†’ Actor Mapping

User saysIntentConstructed Actor input
"Get me the transcript of this YouTube video"Transcript extraction{"videoUrl":"<url>","language":"en"}
"What is said in this video?"Content Q&A / retrieval context{"videoUrl":"<url>"} then read searchResult[].text
"Summarize this YouTube video"Summarization input{"videoUrl":"<url>"} β†’ summarize searchResult text yourself (the Actor returns raw captions)
"Give me the Hindi transcript of this talk"Localized transcript{"videoUrl":"<url>","language":"hi","translate":true}
"Transcript in Spanish, but only if it's a real Spanish caption"Strict language{"videoUrl":"<url>","language":"es","translate":false} then check fallbackUsed
"Pull the captions of this Short"Shorts extraction{"videoUrl":"https://www.youtube.com/shorts/<id>"}
"I need timestamps so I can cut clips"Subtitle / clipping workflow{"videoUrl":"<url>"} then read start + dur per segment
"Turn this video into SRT subtitles"Localization{"videoUrl":"<url>","language":"en"} then format segments as SRT downstream
"Save this video's transcript to Notion"Pipeline/delivery{"videoUrl":"<url>","mcpConnector":"notion","deliveryMode":"chunked","mcpTool":"notion-create-pages"}
"Post the transcript to Slack #content"Pipeline/delivery{"videoUrl":"<url>","mcpConnector":"slack","deliveryMode":"summary","mcpTool":"send_message","mcpArguments":{"channel":"#content","text":"{message}"}}
"Open a Jira ticket with this transcript attached"Pipeline/delivery{"videoUrl":"<url>","mcpConnector":"jira","deliveryMode":"summary","mcpTool":"create_issue"}
"Get transcripts for these 12 videos"Batch extraction12 sequential runs, one videoUrl each β€” then merge on videoId
"Get transcripts for every video on this channel"Channel-wide extraction➑️ Route to YouTube Full Channel Transcripts Scraper
"How many views and comments does this video have?"Metadata➑️ Route to YouTube Scraper
"List all the Shorts on this channel"Shorts catalogue➑️ Route to YouTube Shorts Scraper
"Transcribe this video β€” it has no captions"ASR request❌ Out of scope β€” route to a speech-recognition service

Should NOT route here: videos with no caption track (needs ASR) Β· playlists, channels, or batch lists in a single run (β†’ Full Channel Transcripts) Β· comments, views, likes, or channel statistics (β†’ YouTube Scraper) Β· a channel's Shorts or video-file downloads (β†’ Shorts Scraper) Β· private, unlisted, or age-gated videos Β· LLM summarization or translation of the text Β· non-YouTube video platforms (Vimeo, TikTok, Twitch).


🧭 Agent Execution & Routing Logic

[Input User Query]
β”‚
β–Ό
1. Target is a YouTube video (youtube.com / youtu.be)? NO β†’ Route to the correct platform Actor
β”‚ YES
β–Ό
2. Wants transcript/caption text (not audio, stats, comments)? NO β†’ Route elsewhere / abort
β”‚ YES
β–Ό
3. Is the video public (not private/unlisted/age-gated)? NO β†’ Reject
β”‚ YES
β–Ό
4. Does the video have captions? UNKNOWN β†’ Try; on NO_CAPTIONS route to an ASR service
β”‚
β–Ό
5. Can a video ID be extracted from the input? NO β†’ Prompt user for a clean URL or 11-char ID
β”‚ YES
β–Ό
6. Is the requested language in the 13-value enum? NO β†’ Use "en" and translate downstream
β”‚ YES
β–Ό
7. Is a non-requested language acceptable? NO β†’ set translate:false and check fallbackUsed
β”‚ YES β†’ keep translate:true (default)
β–Ό
8. More than one video needed? YES β†’ Whole channel? Route to Full Channel Transcripts Scraper
β”‚ NO A few videos? Loop: one run per video ($0.10 each)
β–Ό
9. Deliver to a connector? YES β†’ set mcpConnector + mcpTool + {message} in mcpArguments
β”‚ NO β†’ set deliveryMode "none"
β–Ό
[Execute Apify Actor]
β”‚
β”œβ”€β”€β–Ί status == "SUCCEEDED" β†’ verify videoId, then read language / isTranslated / fallbackUsed / message β†’ consume searchResult
└──► status == "FAILED" β†’ route to Error Handling Matrix above

πŸ’° Cost Control & Pricing Transparency

  • Pay-per-run pricing: $0.10 per Actor start β€” charged once per run, regardless of video length or transcript size. One run returns one video's transcript, so this is effectively $0.10 per video.
  • No per-result or per-segment charge: a 3-minute video and a 3-hour lecture cost the same.
  • Autonomous spend caps: pass maxTotalChargeUsd as a query parameter on the run endpoint for a hard per-execution ceiling. It must be at least $0.10, or the run is stopped before doing any work.
Videos transcribedRunsTotal Cost (USD)
1 video1$0.10
10 videos10$1.00
50 videos50$5.00
100 videos100$10.00
1,000 videos1,000$100.00

Cost-control tips: validate the URL and confirm the video has captions before spending a run; cache transcripts by videoId + language so a re-request costs nothing; and if you need the same video in several languages, remember each language is a separate run.

⚠️ Verify before publishing: this assumes a pay-per-event Store configuration with an actor-start event priced at $0.10 and no additional per-result event. Confirm the Actor's live pricing configuration before publishing the listing.


πŸ” Companion machine-readable files

FilePurpose
.actor/actor.jsonIdentity, version, storage and dockerfile wiring
.actor/input_schema.jsonAuthoritative typed input contract β€” videoUrl, language enum, translate, proxy editor, deliveryMode enum
.actor/dataset_schema.jsonOutput field metadata and both Console views (Overview + unwound Transcript) β€” consumed by the Apify MCP server to describe results to agents
.actor/output_schema.jsonDeclares where results are stored
my_actor/main.pyVideo-ID extraction, InnerTube + watch-page resolution, caption parsing, language fallback, MCP delivery
my_actor/connector.pyMCP connector session handling and {placeholder} rendering

If any table on this page disagrees with the schema files, the schema files win.


πŸ› οΈ Troubleshooting

Most failures are caption availability or proxy issues, not scraper bugs. Work through this table top to bottom β€” the first three rows account for the large majority of support tickets.

#Symptom you seeMost likely causeFix
1FAILED β€” Could not retrieve caption data … Last status: …YouTube's bot wall blocked the exit IP (both InnerTube and watch-page paths)Enable RESIDENTIAL Apify Proxy (the default) and retry. Datacenter/local IPs are blocked routinely.
2FAILED β€” No transcript/captions are available for this video.The video genuinely has no caption trackExpected. This Actor reads captions; it does not transcribe audio. Use an ASR/Whisper service.
3FAILED β€” Transcript was found but contained no readable text segments.Caption track resolved but every segment parsed emptyRe-run with translate: true, or request a different language.
4Wrong language in the outputRequested language had no native track; you got a translation or a fallbackRead language, isTranslated, fallbackUsed, message. Set translate: false if only a native track will do.
5translate: false but the run still succeeded in another languageBy design β€” it disables translation, it does not fail the runBranch on fallbackUsed: true, not on run status.
6en-US / pt-BR rejected or ignoredOnly the 13 base enum codes are validPass en, pt, … Region variants are not selectable.
7Text reads like speech-to-text with no punctuationThe source track is YouTube's auto-generated ASR captionCheck isAutoGenerated: true. Nothing to fix β€” that is the only track available.
8videoId is not the video you meantA last-resort regex matched an 11-char token in a malformed inputAlways pass a clean URL or bare ID, and assert the returned videoId.
9Only one dataset itemBy design β€” one run = one video = one item, transcript nested in searchResultRead segmentCount for length; unwind searchResult for a per-segment table.
10start / dur arithmetic failsThey are strings ("3.200"), not numbersCast to float before arithmetic.
11message is null in your consumernull means "nothing needed explaining"Test for None/null, not for "".
12Log: Running without a proxyNo proxy configured or unavailable on the planEnable Apify Proxy residential group; a paid plan is required.
13Log: InnerTube request failed but the run succeededNormal β€” the watch-page fallback took overNo action needed.
14Need many videos and each run is a separate chargeOne video per run by designFor a whole channel use Full Channel Transcripts Scraper; otherwise loop and cache by videoId + language.
15Slack / Notion / Jira received nothingDelivery needs both mcpConnector and mcpTool; otherwise it is skipped with a warningSet both. The dataset item is still saved β€” your data is never lost.
16Log: APIFY_MCP_PROXY_URL is not setYou ran locally with apify run; connectors only resolve on the platformDeploy with apify push and run on the platform.
17Connector fired, but the message body is emptymcpArguments did not reference {message}Map {message} in mcpArguments and populate mcpMessageTemplate.
18Notion rejects or truncates a long transcriptSingle-call payload exceeded block/timeout capsUse deliveryMode: "chunked" and put {part}/{partCount} in the page title.
19Every Notion page looks identical{part}/{partCount} missing from the title templateAdd them: "Transcript {videoId} (part {part}/{partCount})".
20Hundreds of connector calls fireddeliveryMode: "perSegment" sends one call per segmentSwitch to chunked or summary unless per-line records are the goal.
21Delivery fired when you only wanted a datasetdeliveryMode defaults to summary, not noneSet deliveryMode: "none" or leave mcpConnector empty.
22HTTP 401 / 403Missing, expired, or malformed APIFY_TOKENRegenerate in Apify Console β†’ Settings β†’ API & Integrations, send as Authorization: Bearer <token>.
23HTTP 429Apify account concurrency / rate limits β€” not YouTube blockingRetry with exponential backoff (2s β†’ 4s β†’ 8s).
24HTTP 408 on run-sync-get-dataset-itemsThe synchronous endpoint has a hard 300-second ceilingSwitch to async: POST /runs β†’ poll /actor-runs/<runId> β†’ fetch dataset.

Diagnostic checklist before opening an issue

  1. Open the video in a browser and check the transcript panel (β‹― β†’ Show transcript). If YouTube shows nothing there, the video has no captions and no scraper can produce them.
  2. Confirm the proxy. Residential group on, paid plan active. This is the single most common cause of caption-retrieval failures.
  3. Baseline run. videoUrl only, language: "en", translate: true, deliveryMode: "none".
  4. Check the resolved videoId in the output or the run log against the video you meant.
  5. Read the run log β€” it names which source (InnerTube or watch page) provided the player response and which caption language was selected.

If the issue survives all five steps, open an Issues ticket on the Actor page (or email support) with the run ID, the video URL, and what you expected. Run IDs let us replay the exact execution.

❓ FAQ

Setup & access

Do I need a YouTube or Google account, API key, or OAuth app?

No. The Actor reads publicly available caption tracks. You need an Apify account and API token; you need no Google credentials whatsoever.

Is this the official YouTube API?

No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by YouTube or Google.

Why can't I just use the official YouTube Data API?

captions.download only works for videos you own, via OAuth. For any third-party video it is not an option β€” which is the main reason this Actor exists.

Do I need to configure proxies?

The residential Apify Proxy is on by default and you should leave it on β€” YouTube serves datacenter IPs a bot-check wall. Residential groups require a paid Apify plan.

Can I plug it into Claude, Cursor, or a LangChain agent?

Yes β€” it is a native MCP tool:

claude mcp add --transport http apify "https://mcp.apify.com?tools=techforce.global/youtube-transcript-scraper"

Input & languages

Can I pass a playlist, channel, or list of videos?

No β€” one video per run. For a whole channel, use YouTube Full Channel Transcripts Scraper, which takes a channel URL and processes up to 50 videos concurrently. For a few specific unrelated videos, loop this Actor from your orchestration layer (each run is a separate $0.10 charge).

Which languages are supported?

13: en, hi, gu, pt, es, fr, de, it, ja, ko, zh, ru, ar. Region variants like en-US are not valid inputs.

What happens if my language isn't available?

With translate: true (default) you get a YouTube auto-translation. With translate: false you get the video's own caption language, fallbackUsed: true, and a message listing what was available. The run does not fail for language reasons.

Does it work on Shorts?

Yes β€” Shorts, embed, /live/, youtu.be, mobile and youtube-nocookie hosts, and bare 11-character IDs all resolve.

Output & data

Why is the whole transcript in one dataset item?

One run handles one video, so the transcript is a nested searchResult array on a single item. Use the Console's Transcript view (or unwind=searchResult on the API) for a per-segment table.

Why are start and dur strings?

For compatibility with the widely-used searchResult transcript format. Cast them to float before doing arithmetic.

Does it summarize or translate with an LLM?

No. It returns YouTube's caption text β€” raw, timestamped, and unmodified apart from HTML unescaping. Summarize downstream.

Can it transcribe a video that has no captions?

No. There is no speech recognition in this Actor. Use an ASR service for caption-less videos.

Delivery

What is the MCP connector for?

It pushes the transcript straight into a tool you have already authorized on your Apify account β€” Notion, Slack, Jira, GitHub, Linear, Airtable, or any MCP-compatible connector β€” with no glue code. Credentials stay private: delivery runs through the Apify MCP Proxy, so the Actor never sees your connector tokens.

Which delivery mode should I use?

summary for short videos, chunked for long transcripts into services with request caps (Notion), perSegment for per-line records (logs, row-per-segment sheets), none for dataset-only runs.

Does delivery work when running locally?

No. Connectors resolve through the Apify MCP Proxy, which only exists on the platform. Locally you'll see APIFY_MCP_PROXY_URL is not set and the dataset item is saved as normal.

Limits & pricing

What does it cost?

$0.10 per run, charged at Actor start β€” one video per run, any length. No per-segment or per-character fees.

How do I guarantee an agent never overspends?

Pass maxTotalChargeUsd on the run endpoint (minimum $0.10 per run), and cache transcripts by videoId + language so repeats cost nothing.


Other YouTube Actors

This Actor is the single-video specialist: one URL in, one timestamped transcript out, at a flat $0.10 per run. Use these siblings when the job is bigger or different.

ActorBest forWhy pick it over this one
YouTube Full Channel Transcripts ScraperTranscripts for every video in a channel β€” accepts @handle, /channel/ID, /c/name, /user/name, processes up to 50 videos concurrently, and returns video + channel metadata alongside the transcriptYou want a whole channel (or its latest N videos) in one run instead of orchestrating one run per video. From $10.50 / 1,000 results.
YouTube Scraper: Videos, Channels & CommentsVideo, channel, and comment metadata from search queries, channel URLs, video URLs, or hashtags β€” up to 500 videos per input and 1,000 comments per videoYou need views, likes, descriptions, channel stats, or comment threads β€” none of which this transcript Actor returns. From $9.00 / 1,000 results.
YouTube Shorts ScraperEvery Short from a channel with engagement metrics (views, likes, comments, hashtags) and optional video downloadsYou're working through a channel's Shorts catalogue, or you need the video files themselves. From $8.50 / 1,000 results.

Pick by intent: one video's words β†’ this Actor Β· a channel's words β†’ Full Channel Transcripts Β· numbers, comments, and search discovery β†’ YouTube Scraper Β· a channel's Shorts and their files β†’ Shorts Scraper.

Enrichment & downstream pipeline

ActorUse it for
Advanced Website Crawling ActorCrawl the creator's own site or show notes for clean HTML/Markdown/text context alongside the transcript
Google Maps Scraper – Business DataEnrich businesses or venues mentioned in a transcript into full business records
GOV.UK Business ScraperMatch UK company names heard in a video against Companies House records

Suggested pipeline patterns

✍️ Content repurposing YouTube Transcript Scraper β†’ transcript text into your LLM of choice β†’ blog draft, thread, newsletter β†’ publish via a Notion/Slack connector.

🌍 Localization One run per target language (hi, gu, es, …) β†’ format start/dur/text as SRT downstream β†’ upload as subtitle tracks.

πŸ”Ž Video knowledge base YouTube Full Channel Transcripts Scraper for the channel backfill β†’ this Actor for each new upload β†’ store by videoId + language β†’ index searchResult text for semantic search over everything you've published.

πŸ“Š Transcript + engagement analysis YouTube Scraper for views, likes, and comments β†’ this Actor for the words of the videos that over-performed β†’ correlate topics against engagement.

πŸ€– Agent retrieval tool Register the Actor as an MCP tool so an agent can pull a video's transcript on demand and answer questions with timestamps.

Browse all Actors by Techforce Global at apify.com/techforce.global.


πŸ” Compliance & Data Privacy

This is an independent Actor. It is not affiliated with, endorsed by, or sponsored by YouTube or Google. YouTubeβ„’ is a trademark of Google LLC; all trademarks are the property of their respective owners.

This Actor collects publicly available caption/transcript data only. It does not log into any account, bypass authentication, or access private, unlisted, or age-gated videos. Transcripts are the creator's copyrighted content β€” you are responsible for ensuring your use complies with YouTube's Terms of Service, applicable copyright law, and any data-protection regulation (including GDPR and CCPA) that applies to text you store or republish. Spoken content can contain personal data about identifiable people β€” handle accordingly.


πŸ†˜ Support & Custom Pipeline Engineering

Whole-channel coverage is already a product β€” see YouTube Full Channel Transcripts Scraper. Need something beyond it: scheduled multi-channel monitoring, playlist coverage, or a full content pipeline into your CMS?


Made with ❀️ by Techforce Global Specialists in High-Performance Video & Transcript Data Extraction and AI Automation.


🏷️ Structured data for search & AI discovery

{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "YouTube Transcript Scraper & Captions API Alternative",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Cloud (Apify platform)",
"description": "Extracts the full transcript of any public YouTube video as structured JSON β€” every segment with start time, duration, and text β€” in 13 languages with automatic translation fallback, and optional delivery to Notion, Slack, Jira, GitHub, Linear, Airtable, or any authorized MCP connector.",
"url": "https://apify.com/techforce.global/youtube-transcript-scraper",
"offers": {
"@type": "Offer",
"price": "0.10",
"priceCurrency": "USD",
"description": "Per run (one video, any length)"
}
}