YouTube Channel Transcripts Scraper
Pricing
from $10.50 / 1,000 results
YouTube Channel Transcripts Scraper
Bulk YouTube channel transcript scraper. Extract subtitles/captions and video + channel metadata from all videos of a channel. Export or push to Notion, Slack & more.
Pricing
from $10.50 / 1,000 results
Rating
0.0
(0)
Developer
Techforce Global
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
2
Monthly active users
11 days ago
Last modified
Categories
Share
YouTube Channel Transcript Scraper
Point it at a channel, get every video's transcript. One dataset row per video — full plain text for embedding, or timestamped
{text, start, duration}segments for deep-linking, plus whichever of 19 optional metadata fields you switch on. No Google API key, no OAuth, no video ownership, no quota. Built for RAG corpora, content analysis and searchable video archives, with optional delivery into Notion, Slack, Linear, Jira, GitHub or Airtable over MCP.
🔐 Trust & compliance at a glance
| Credentials | None required. The Actor never needs a Google or YouTube account. The optional cookies field is stored as a secret input, and MCP delivery runs through the Apify MCP Proxy, so the Actor never sees your connector tokens. |
| Data scope | Public caption tracks and public metadata only. No private or members-only videos, and no comment text — only the comment count, and only if you toggle it on. |
| GDPR / UK GDPR / CCPA | A transcript is a person's speech, so it can be personal data about the speaker and anyone named aloud. The Compliance section sets out minimisation, retention and special-category handling in full. |
| Attribution safety | transcriptIsGenerated: true flags machine-written text — check it before quoting anyone verbatim. |
| Honest gaps | A video with no retrievable transcript still gets a row, carrying transcriptError. Nothing vanishes silently. |
Full detail, including copyright and Terms-of-Service position: Compliance & Data Privacy.
Official YouTube Data API v3 vs. YouTube Channel Transcript Scraper Actor
The official API's captions.download endpoint only works for videos you own, so there is no
sanctioned route to a third-party channel's transcripts at all:
| Feature / Capability | Official YouTube Data API v3 | YouTube Channel Transcript Scraper (Apify) |
|---|---|---|
| Transcripts for videos you don't own | ❌ captions.download requires OAuth as the video owner | ✅ Any public video with captions |
| A whole channel in one call | ❌ List uploads, then one caption call per video — all owner-gated | ✅ One run covers the channel, or its newest N |
| Authentication & setup | ❌ Google Cloud project + OAuth consent flow | ✅ Zero target-site credentials; only an Apify token |
| Timestamped segments | ⚠️ Owner-only, and format handling is yours | ✅ {text, start, duration} objects, ready to use |
| Tells you what you actually got | ❌ N/A | ✅ transcriptLanguage, transcriptIsGenerated, transcriptError per video |
| Daily quota ceiling | ⚠️ Per-project daily quota; exceeding it blocks you until reset | ✅ No per-day ceiling |
| Bot-wall / IP blocking | N/A (quota-gated instead) | ✅ Apify residential proxy wired in by default, plus optional cookies |
| AI agent / MCP native | ❌ Requires a custom tool wrapper | ✅ Native MCP tool and pushes results into your own MCP connectors |
The
captions.downloadownership restriction and quota costs are Google's to change — check Google's current docs if this comparison is load-bearing for your decision.
🤖 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-full-channel-transcripts-scraper"actor_id: "youtube-full-channel-transcripts-scraper"one_line: >Scrapes the transcript of every video on one or more YouTube channels - as plain text,timestamped segments, or both - alongside 19 optional video and channel metadata fields,each individually toggleable. No API key required. Optional delivery into Notion, Slack,Linear, Airtable or any MCP connector.primary_purpose: "extract"secondary_purpose: "deliver"entity: "YouTube video transcript"category: "video-transcripts / rag-ingestion / content-analysis / media-research"supported_platforms:- "youtube.com"- "youtu.be"supported_tasks:- "get-transcripts-for-every-video-on-a-channel"- "get-transcripts-for-the-newest-n-videos"- "get-timestamped-transcript-segments"- "build-a-rag-corpus-from-a-channel"- "compare-topics-across-several-channels"- "audit-transcript-language-and-quality"- "deliver-transcripts-to-mcp-connector"unsupported_tasks:- "scrape-comment-text (use youtube-scraper; only the comment COUNT is available)"- "search-terms-or-hashtags-as-input (use youtube-scraper)"- "download-video-or-audio-files (use youtube-shorts-scraper for Shorts media)"- "transcribe-audio-without-captions (no ASR of our own)"- "translate-transcripts"- "creator-analytics-watch-time-retention-revenue (not public)"- "scrape-private-unlisted-or-members-only-videos"search_keywords:# First entry is the H1 / meta-description target. The rest are deliberately broader for# agent-side semantic matching and are NOT a ranking strategy - see the skill's SEO notes.- "youtube channel transcript scraper"- "bulk youtube transcripts"- "all videos transcript download"- "youtube transcript api alternative"- "video corpus for rag"- "youtube subtitle extractor channel"- "timestamped captions json"- "content analysis youtube channel"- "video knowledge base ingestion"- "mcp youtube transcripts tool"synonyms:- "channel-wide caption downloader"- "youtube subtitle scraper"- "video transcript extractor"related_concepts:["transcripts", "captions", "RAG ingestion", "semantic search", "content analysis", "media research"]input_entities:- "channelUrls (required; array. @handle, /channel/ID, /c/name, /user/name, or a video URL)"- "maxVideos (per channel; 0 = ALL videos)"- "maxConcurrency (1-50 videos in parallel)"- "transcriptLanguages (priority order, falls back to any available)"- "includeTranscriptText / includeTranscriptSegments"- "proxyConfiguration (residential by default)"- "cookies (optional, secret, Netscape format)"- "19 include* toggles for metadata fields"output_entities_always:- "videoId"- "videoUrl"- "title"output_entities_transcript:- "transcript"- "transcriptSegments"- "transcriptLanguage"- "transcriptIsGenerated"- "transcriptError"output_entities_toggleable_video:- "channelName"- "channelId"- "dateText"- "relativeDateText"- "datePublished"- "viewCount"- "likes"- "comments"- "keywords"- "thumbnail"- "description"output_entities_toggleable_channel:- "channelHandle"- "subscriberCount"- "channelCreationDate"- "channelCountry"- "channelTotalViewCount"- "channelTotalVideoCount"language_fallback_is_silent: >CRITICAL: transcriptLanguages is a PREFERENCE list, not a filter. If no preferred languageexists the Actor returns any available transcript, including auto-generated. It does notfail or warn per video. Always read transcriptLanguage on each row before treating a corpusas monolingual.auto_generated_transcripts_are_flagged: >transcriptIsGenerated is true when YouTube machine-transcribed the audio. Auto-generatedtext carries recognition errors, no punctuation reliability and mangled proper nouns. Filteron it if transcript quality matters.transcript_error_presence_is_the_signal: >transcriptError appears ONLY when retrieval failed. Its absence means success. Videos withtranscripts disabled, or none in any language, produce a row with a null transcript and thisfield set - the row is still saved so the channel inventory stays complete.toggled_off_fields_are_absent_keys: >A field whose toggle is off is not written at all - it is an ABSENT KEY, not a null. Consumersmust use .get()/optional access rather than indexing.maxVideos_zero_means_all: >maxVideos 0 scrapes EVERY video on each channel. On a large channel that is thousands ofvideos, each needing a transcript fetch. Always pair 0 with a spend cap.request_cost_classes: >Three cost tiers, and they are NOT what the field names suggest. (1) Free, already in thechannel listing: channelName, channelId, viewCount, thumbnail. (2) One extra request PERVIDEO, triggered by enabling ANY of includeLikes, includeComments, includeKeywords,includeDescription, includeDateText or includeRelativeDateText - the single largest costlever after maxVideos; enabling all six costs the same as enabling one. (3) One extra fetchPER CHANNEL, shared by all six extended channel toggles together - enabling all six costs nomore than enabling one, and includeSubscriberCount is ON by default so that fetch alreadyhappens unless you turn all six off.date_published_caveat: >datePublished is derived from whatever the listing returned. The channel listing frequentlyomits the timestamp, so datePublished can be null unless a per-video fetch is triggered byone of the six toggles in cost tier 2.channels_are_sequential_videos_are_parallel: >Multiple channelUrls are processed one channel at a time; within a channel, videos run inparallel up to maxConcurrency.no_comments_here: >This Actor does NOT scrape comments. Use the sibling YouTube Scraper(techforce.global/youtube-scraper) for comment threads.compliance:credentials_required: "none - no Google/YouTube account needed; the optional cookies field is a secret input"data_scope: "public caption tracks and public metadata only"connector_token_handling: "MCP delivery runs through the Apify MCP Proxy; the Actor never sees your connector tokens"personal_data_note: "a transcript is a person's speech and can be personal data about the speaker and anyone named aloud - GDPR / UK GDPR / CCPA-CPRA obligations sit with the caller"attribution_flag: "transcriptIsGenerated true means the text is machine-written; do not attribute it as a verbatim quote"affiliation: "independent Actor; not affiliated with, endorsed by, or sponsored by YouTube or Google"known_limitations:not_every_video_has_a_transcript: "creators can disable them; some languages have none"auto_generated_quality: "machine transcripts contain errors, especially with names and jargon"no_translation: "returns what YouTube publishes, untranslated"no_comments: "comment threads are not collected - only the comment COUNT, and only if toggled"no_creator_analytics: "watch time, retention and revenue are not public"no_video_files: "transcripts and metadata only - nothing is downloaded"row_count_can_trail_video_count: "a video whose record fails to build is logged and skipped, so the dataset can hold fewer rows than the 'Found N video(s)' log line"snapshot_only: "view and like counts are true as of the run"pricing:model: "usage-based"billing_unit: "Apify platform usage consumed by the run"note: "Current rates are shown on the Actor's Apify Store page; the Console shows a live total mid-run. A hard per-run ceiling can be set with maxTotalChargeUsd."hard_ceiling_parameter: "maxTotalChargeUsd"when_to_use: >You want everything a channel has said, as data - a RAG corpus, a searchable archive, acontent-strategy analysis, or a multi-channel topic comparison.when_not_to_use: >You need comment threads, search or hashtag discovery, creator analytics, the video files, atranslated transcript, or a guaranteed transcript for every video regardless of whether thecreator enabled one.mcp_delivery:modes: ["summary", "chunked", "perSegment", "none"]default: "summary"delivery_is_per_video: >Delivery fires once per video as its record is saved, not once per run. chunked multipliesthat by the number of parts, and perSegment by the number of segments.all_mode_placeholders: ["{videoUrl}", "{videoId}", "{title}", "{channelName}", "{channelId}", "{datePublished}", "{viewCount}", "{subscriberCount}", "{language}", "{segmentCount}", "{transcript}", "{message}"]chunked_only_placeholders: ["{part}", "{partCount}"]per_segment_placeholders: ["{start}", "{dur}", "{duration}", "{text}"]per_segment_without_segments_falls_back: >perSegment needs includeTranscriptSegments enabled. Without segments it does NOT fail anddoes NOT go silent - it logs a warning and sends one summary call for that video instead.never_blocks_the_dataset: >Delivery runs after the record is saved. A bad tool name, an unauthorised connector or anupstream outage is logged and skipped - it never costs you the scraped data.alternatives:- "Use techforce.global/youtube-transcript-scraper for a single video's transcript"- "Use techforce.global/youtube-scraper for search, hashtags, video metadata and comment threads"- "Use techforce.global/youtube-shorts-scraper for a channel's Shorts with engagement and optional media download"- "Use a dedicated ASR/Whisper service when videos have no caption track at all"
{"@context": "https://schema.org","@type": "SoftwareApplication","name": "YouTube Full Channel Transcripts Scraper","alternateName": "YouTube Channel Transcript Scraper","applicationCategory": "DeveloperApplication","operatingSystem": "Cloud (Apify platform)","description": "Scrapes the transcript of every video on one or more YouTube channels — as a single plain-text string, as timestamped {text, start, duration} segments, or both — alongside 19 individually toggleable video and channel metadata fields, without a Google API key, OAuth, or video ownership. Resolves a channel from an @handle, /channel/ID, /c/, /user/ path or any video URL. Reports the language actually retrieved, whether the transcript was auto-generated, and a per-video error when none was available, so gaps are recorded rather than silently dropped. Public captions only, with GDPR/CCPA and speaker-identifiability guidance included. Residential proxy by default with optional cookie support, and optional delivery into Notion, Slack, Linear, Airtable or any MCP connector with chunking for long transcripts.","url": "https://apify.com/techforce.global/youtube-full-channel-transcripts-scraper","offers": {"@type": "Offer","priceCurrency": "USD","category": "Pay per platform usage","description": "Usage-based: billed for the compute time and resources a run consumes, not per row. Current rates are shown on the Actor's Apify Store page."}}
What this Actor does
💡 Need one video, not a channel? YouTube Transcript Scraper does a single video in one run, with 13-language auto-translation. For views, likes, comments, search and hashtags, use YouTube Scraper; for a channel's Shorts and their video files, use YouTube Shorts Scraper.
-
Resolves a channel from almost any URL you have.
@handle,/channel/ID,/c/name,/user/name— or even a single video URL, from which the channel is worked out for you. -
Covers the whole channel, or the newest N.
maxVideos: 0takes everything; anything else caps it, newest first. Several channels in one run:channelUrlsis an array. -
Returns the spoken content, two ways.
transcriptas one plain-text string for embedding and search;transcriptSegmentsas{text, start, duration}objects when you need to jump to a timestamp. Enable either, or both. -
Tells you how good each transcript is.
transcriptLanguagesays what you actually got,transcriptIsGeneratedsays whether a machine wrote it, andtranscriptErrorappears only when retrieval failed. Three fields that turn "here's a corpus" into "here's a corpus you can assess". -
Records the gaps instead of hiding them. A video whose transcript can't be retrieved still produces a row, so you get a complete channel inventory with the holes marked.
-
Lets you pay for exactly the metadata you want. 19 individual toggles across three distinct cost tiers — see Input Contract, because the cheap-looking ones aren't the cheap ones.
-
Handles the bot check. Residential proxy by default, a fresh proxy IP per video, plus an optional secret cookies field for channels a proxy alone can't reach.
-
Saves as it goes. Each video is written to the dataset as it finishes, so an aborted or timed-out run keeps everything collected up to that point.
-
Optionally delivers into your tools. Each video's transcript can go straight to Notion, Slack, Linear, Jira, GitHub or Airtable — with a chunked mode for transcripts too long for one page.
Which YouTube Actor do I want?
| You want… | Actor |
|---|---|
| Transcripts of every video on a channel | This Actor |
| One video's transcript, with auto-translation | YouTube Transcript Scraper |
| Long-form video metadata, search, hashtags, comment threads | YouTube Scraper |
| A channel's Shorts, with engagement and optional file download | YouTube Shorts Scraper |
None of them need a YouTube Data API key or a quota. They're complementary, not alternatives.
When to use it — and when not to
| Scenario | Fit |
|---|---|
| Every video's transcript from a channel | ✅ Strong — the core use case |
| Transcripts as plain text for RAG or search | ✅ Strong — includeTranscriptText |
| Timestamped segments for deep-linking | ✅ Strong — includeTranscriptSegments |
| Building a searchable archive of a creator's back catalogue | ✅ Strong — maxVideos: 0 plus a spend cap |
| Comparing topics across several channels | ✅ Strong — channelUrls is an array |
| Knowing whether a transcript is auto-generated | ✅ Strong — transcriptIsGenerated |
| A complete inventory including videos with no transcript | ✅ Strong — those rows carry transcriptError |
| Only the fields you actually want | ✅ Strong — 19 toggles |
| Transcripts pushed into Notion / Slack | ✅ Strong — MCP delivery, with chunking |
| A specific transcript language | ⚠️ Preference only — falls back silently, check transcriptLanguage |
| A precise publish date on every row | ⚠️ datePublished can be null unless a per-video fetch is triggered — see Input Contract |
| Comment threads | ❌ Count only — use the YouTube Scraper |
| Search terms or hashtags as input | ❌ Channels only — the sibling does search |
| Translated transcripts | ❌ Returns what YouTube publishes, untranslated — the single-video Actor does translation |
| A transcript for videos that have none | ❌ No speech recognition here — route to an ASR service |
| Downloading video or audio | ❌ Transcripts and metadata only |
| Private, unlisted or members-only videos | ❌ Public content only |
| Creator analytics — watch time, retention, revenue | ❌ Not public |
| Uploading, editing or posting | ❌ Read-only |
⚡ Execution Rules (Avoid Common Agent Failures)
-
channelUrlsis required and is an array. Any of@handle,/channel/ID,/c/name,/user/name, or a video URL works — a video URL resolves to its channel. Objects ([{"url": "…"}]) and bare strings (["…"]) are both accepted. -
transcriptLanguagesis a preference, not a filter. If none of your codes exist for a video, the Actor returns any available transcript, including auto-generated, and doesn't warn per video. ReadtranscriptLanguageon every row before treating the output as monolingual. Filter after the fact if you need strictly one language. -
maxVideos: 0means every video on each channel. On a large channel that's thousands of videos, each needing its own transcript fetch. Always pair0with a spend cap. Default is10. -
The expensive toggles are the video ones, not the channel ones. Enabling any of
includeLikes,includeComments,includeKeywords,includeDescription,includeDateTextorincludeRelativeDateTexttriggers one extra request per video. The six extended channel toggles share one fetch per channel between them. Enabling all six of either group costs no more than enabling one of it. -
datePublishedcan be null on the cheap path. It comes from whatever the channel listing returned, and the listing often omits the timestamp. If you need reliable dates, enable one of the six per-video toggles in rule 4 — the full fetch fills it in. -
A field you toggled off is an absent key, not null. Use
row.get("viewCount"), notrow["viewCount"]. -
transcriptError's presence is the failure signal. NotranscriptErrorkey means the transcript was retrieved. When it is present,transcriptis null and the field says why. -
Check
transcriptIsGeneratedbefore trusting the text. Auto-generated transcripts have recognition errors, unreliable punctuation and mangled proper nouns. For anything quality-sensitive, filter to human-authored, or expect to clean. -
Turning off both transcript toggles gives you metadata-only rows. No
transcript, notranscriptSegments, and notranscriptLanguage/transcriptIsGenerated/transcriptErrorkeys at all. -
Keep the residential proxy. The default is
{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}. Datacenter IPs get the bot check. If you passproxyConfigurationas empty or omit it in a hand-built input object, the run uses no proxy at all — pass it explicitly from API and MCP callers. Residential groups require a paid Apify plan. If you're still blocked, supplycookies. -
The row count can be lower than the video count. A video whose record can't be built is logged (
Failed to build record for <id>) and skipped. Compare the dataset size against theFound N video(s)log line rather than assuming they match. -
Channels run one at a time; videos run in parallel.
maxConcurrency(default10, range1–50) applies within a channel.8–12is the sensible band; drop to1–3if you're being blocked. -
Delivery fires per video, not once per run. Ten videos in
summarymode is ten connector calls;chunkedmultiplies that by the number of parts,perSegmentby the number of segments. -
deliveryModedefaults tosummary, notnone. For dataset-only runs, either leavemcpConnectorempty or setdeliveryMode: "none"explicitly. -
No comments here. This Actor returns the comment count (if toggled), never the comment text. That's the sibling Actor's job.
dependencies:- rule: "delivery requires mcpConnector AND mcpTool"on_violation: "delivery is skipped with a warning; every dataset row 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: "perSegment needs includeTranscriptSegments"on_violation: "logs a warning and sends ONE summary call for that video instead - not a silent no-op"- rule: "chunked mode exposes {part} and {partCount}"note: "put them in the page/message title or every part looks identical"authentication:actor_input: "none required; optional cookies field is a secret input"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.
Scraping parameters
| Parameter | Type | Required | Default | Allowed values / format | Example |
|---|---|---|---|---|---|
channelUrls | array | ✅ Yes | none (Console prefill only) | @handle, /channel/ID, /c/name, /user/name or a video URL. Objects or bare strings. | [{"url":"https://www.youtube.com/@handle"}] |
maxVideos | integer | ⬜ No | 10 | 0 = ALL videos per channel; otherwise the cap, newest first | 100 |
maxConcurrency | integer | ⬜ No | 10 | 1–50. 8–12 is the sweet spot | 8 |
transcriptLanguages | array<string> | ⬜ No | ["en"] | Priority order. Falls back to any available if none match | ["hi","en"] |
includeTranscriptText | boolean | ⬜ No | true | Transcript as one plain-text string | true |
includeTranscriptSegments | boolean | ⬜ No | false | Transcript as {text, start, duration} objects | true |
proxyConfiguration | object | ⬜ No | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} | Apify proxy editor object. Pass it explicitly from the API. | see below |
cookies | string (secret) | ⬜ No | — | Netscape cookies.txt from a logged-in session. Helps when a proxy alone isn't enough. | — |
Accepted channel input shapes
| Shape | Example |
|---|---|
| Handle | https://www.youtube.com/@handle |
| Channel ID path | https://www.youtube.com/channel/UCxxxxxxxxxxxxxxxxxxxxxx |
| Legacy custom path | https://www.youtube.com/c/name |
| Legacy user path | https://www.youtube.com/user/name |
| Any video URL from the channel | https://www.youtube.com/watch?v=dQw4w9WgXcQ |
| A tab URL | https://www.youtube.com/@handle/videos — tab suffixes are honoured as given |
Metadata toggles — and what each one actually costs
There are three cost tiers, and they are not what the field names suggest. Read this before switching things on.
Tier 1 — free. Already present in the channel listing; toggling them only changes what gets written.
| Toggle | Field | Default |
|---|---|---|
includeChannelName | channelName | ✅ on |
includeChannelId | channelId | ✅ on |
includeViewCount | viewCount | ✅ on |
includeThumbnail | thumbnail | off |
includeDatePublished | datePublished (ISO) | ✅ on — but see the caveat below |
Tier 2 — one extra request per video. Enabling any single one of these triggers a full
per-video metadata fetch; enabling all six costs the same as enabling one. This is the largest
cost lever after maxVideos.
| Toggle | Field | Default |
|---|---|---|
includeLikes | likes | off — often null, creators hide it |
includeComments | comments (the count) | off |
includeKeywords | keywords | off |
includeDescription | description | off |
includeDateText | dateText | off |
includeRelativeDateText | relativeDateText | off |
datePublishedcaveat. It is derived from whatever the listing returned, and the channel listing frequently omits the timestamp — so on a run with no Tier 2 toggle enabled,datePublishedcan come backnull. Enabling any Tier 2 toggle triggers the full fetch and fills it in.
Tier 3 — one extra fetch per channel, shared by all six. Enabling all six costs no more than
enabling one. includeSubscriberCount is on by default, so this fetch already happens unless
you turn all six off.
| Toggle | Field | Default |
|---|---|---|
includeSubscriberCount | subscriberCount | ✅ on — null if hidden |
includeChannelHandle | channelHandle | off |
includeChannelCreationDate | channelCreationDate | off |
includeChannelCountry | channelCountry | off |
includeChannelTotalViewCount | channelTotalViewCount | off |
includeChannelTotalVideoCount | channelTotalVideoCount | off |
Delivery (optional)
| Parameter | Type | Default | Description |
|---|---|---|---|
mcpConnector | string | "" | An MCP connector you have authorised on your Apify account — Notion, Slack, Linear, Jira, GitHub, Airtable, or any MCP-compatible connector. The Console offers a picker. Leave empty for dataset-only runs. |
deliveryMode | string (enum) | "summary" | summary (one call per video) · chunked (split a long transcript across calls/pages) · perSegment (one call per segment) · none. |
mcpTool | string | "" | Tool to call — e.g. create_page, send_message, create_issue. Required when a connector is set. Run once with a connector selected and the log lists the connector's available tools. |
mcpArguments | object | {} | Arguments for the tool. String leaves support {placeholder} tokens. |
mcpMessageTemplate | string | "" | Template rendered and exposed to mcpArguments as {message}. |
Placeholders by mode:
| Mode | Placeholders |
|---|---|
| all modes | {videoUrl} {videoId} {title} {channelName} {channelId} {datePublished} {viewCount} {subscriberCount} {language} {segmentCount} {transcript} {message} |
chunked | plus {part} {partCount} — {transcript} holds one part |
perSegment | plus {start} {dur} / {duration} {text} — needs includeTranscriptSegments; without it, one summary call is sent for that video and a warning is logged |
Unknown tokens render as an empty string rather than erroring. The delivered {transcript} is
repacked into paragraphs of roughly 1,800 characters and grouped into parts under roughly 72,000
characters, so services with per-block or timeout caps (Notion in particular) never reject the
call.
📤 Output Contract & Data Structure
Storage: Apify Dataset — one item per video, written as each video finishes.
Absent vs null: fields whose toggle is off are absent keys, not nulls.
Order: completion order, not chronological — videos run in parallel. Sort client-side.
Duplicates: none within a run. Across runs, dedupe on videoId.
Always present
| Field | Type | Nullable | Meaning |
|---|---|---|---|
videoId | string | No | YouTube's 11-character ID. The stable key for joining runs. |
videoUrl | string | No | Canonical watch URL. |
title | string | Yes | Video title. |
Transcript fields — present when either transcript toggle is on
| Field | Type | Nullable | Toggle / controlled by | Meaning |
|---|---|---|---|---|
transcript | string | Yes | includeTranscriptText | Full transcript as one string. Null when retrieval failed. |
transcriptSegments | array | Yes | includeTranscriptSegments | {text, start, duration} objects; start/duration are numbers, rounded to 3 decimals. [] on failure. |
transcriptLanguage | string | Yes | transcriptLanguages | What you actually got — may differ from your preference list. |
transcriptIsGenerated | boolean | Yes | — (source track) | true = machine-transcribed. Expect recognition errors. |
transcriptError | string | — | — (video state) | Present only on failure, and says why (e.g. No transcript available). Its absence means success. |
Toggleable video metadata
| Field | Type | Toggle | Cost tier |
|---|---|---|---|
channelName / channelId | string | on by default | Free |
viewCount | integer | on by default | Free |
thumbnail | string | off | Free |
datePublished | string (ISO) | on by default | Free — but often null without a Tier 2 toggle |
dateText / relativeDateText | string | off | Per video |
likes | integer | off — often null, creators hide it | Per video |
comments | integer | off — the count; text is not scraped | Per video |
keywords | array | off | Per video |
description | string | off | Per video |
Toggleable channel metadata
All six share one fetch per channel.
| Field | Type | Toggle |
|---|---|---|
subscriberCount | integer | on by default — null if hidden |
channelHandle | string | off |
channelCreationDate | string (ISO date, or the raw text if unparseable) | off |
channelCountry | string | off |
channelTotalViewCount | integer | off |
channelTotalVideoCount | integer | off |
Example output object (defaults, plus segments)
{"videoId": "aBcDeFgHiJk","videoUrl": "https://www.youtube.com/watch?v=aBcDeFgHiJk","title": "How We Rebuilt Our Ingestion Pipeline","transcript": "So the first thing we noticed was that our queue depth kept growing…","transcriptSegments": [{ "text": "So the first thing we noticed", "start": 0.32, "duration": 2.1 },{ "text": "was that our queue depth kept growing", "start": 2.42, "duration": 2.8 }],"transcriptLanguage": "en","transcriptIsGenerated": false,"channelName": "Practical Systems","channelId": "UC000000000000000000000","datePublished": "2026-06-14","viewCount": 48211,"subscriberCount": 128000}
A video whose transcript could not be retrieved:
{"videoId": "lMnOpQrStUv","videoUrl": "https://www.youtube.com/watch?v=lMnOpQrStUv","title": "Members-only Q&A","transcript": null,"transcriptLanguage": null,"transcriptIsGenerated": null,"transcriptError": "No transcript available","channelName": "Practical Systems","channelId": "UC000000000000000000000","datePublished": "2026-07-02","viewCount": 3102,"subscriberCount": 128000}
Values illustrate shape and formatting — the channel and videos are invented. Note that the failed row is still saved: you get a complete inventory of the channel, with
transcriptErrormarking the gaps rather than the video silently vanishing.
What a successful run looks like
- Status:
SUCCEEDED - Dataset: one item per video, including videos whose transcript failed
- Log: a startup line echoing
maxVideos, concurrency, languages, proxy and cookie state; then the resolved channel and video count; then a[n/total] Done: <videoId>line per video - Zero results is also a success. A bot-block, a channel with no public videos, or an
unresolvable URL all return an empty dataset with
SUCCEEDED. Check the log. - Rows with
transcriptErrorare not failures of the run — they're an honest record that the video has no retrievable transcript. - Fewer rows than the "Found N" line means some records failed to build; those are logged individually.
Dataset views
| View | Shows |
|---|---|
| Transcripts | Title, video link, channel, date, views, subscribers and the transcript text |
| Transcript Health | Language, auto-generated flag and error per video — check this before trusting a corpus |
| Video Metadata | Engagement and publishing columns without the transcript text |
| Channel Metadata | Channel-level columns repeated per row |
▶️ Invocation & Integration
Lifecycle: Discover → Understand → Configure → Execute → Retrieve → Validate. Authenticate every
call with Authorization: Bearer <APIFY_TOKEN>.
Apify Console
Open the Actor page → Input tab → paste a channel URL → set Maximum videos → leave the proxy at its residential default → (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-full-channel-transcripts-scraper"
Then ask your agent for "transcripts of the last 20 videos from this channel".
Python (apify-client)
import osfrom apify_client import ApifyClientclient = ApifyClient(os.getenv("APIFY_TOKEN"))run = client.actor("techforce.global/youtube-full-channel-transcripts-scraper").call(run_input={"channelUrls": [{"url": "https://www.youtube.com/@handle"}],"maxVideos": 50,"transcriptLanguages": ["en"],"includeTranscriptText": True,"deliveryMode": "none","proxyConfiguration": {"useApifyProxy": True,"apifyProxyGroups": ["RESIDENTIAL"],},})rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())# Assess the corpus BEFORE using it.ok = [r for r in rows if not r.get("transcriptError")]failed = [r for r in rows if r.get("transcriptError")]generated = [r for r in ok if r.get("transcriptIsGenerated")]langs = {r.get("transcriptLanguage") for r in ok}print(f"{len(ok)}/{len(rows)} transcripts | {len(generated)} auto-generated | languages: {langs}")if len(langs) > 1:print(" ⚠ mixed languages — the preference list fell back on some videos")for r in failed[:5]:print(f" no transcript: {r['title']!r} — {r['transcriptError']}")# Toggled-off fields are ABSENT keys — always use .get().print("dates present:", sum(1 for r in rows if r.get("datePublished")))
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-full-channel-transcripts-scraper').call({channelUrls: [{ url: 'https://www.youtube.com/@handle' }],maxVideos: 100,includeTranscriptSegments: true, // timestamps for deep-linkingincludeTranscriptText: true,deliveryMode: 'none',proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ['RESIDENTIAL'] },});const { items } = await client.dataset(run.defaultDatasetId).listItems();// Build deep links to the moment a term is mentioned.const TERM = 'kubernetes';for (const row of items) {for (const seg of row.transcriptSegments ?? []) {if (seg.text.toLowerCase().includes(TERM)) {console.log(`${row.title} → ${row.videoUrl}&t=${Math.floor(seg.start)}s`);}}}
cURL — synchronous (waits, returns the dataset)
curl -X POST \-H 'Content-Type: application/json' \-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \-d '{"channelUrls": [{ "url": "https://www.youtube.com/@handle" }],"maxVideos": 10,"deliveryMode": "none","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}' \'https://api.apify.com/v2/acts/techforce.global~youtube-full-channel-transcripts-scraper/run-sync-get-dataset-items'
cURL — asynchronous with a spend cap (required for maxVideos: 0)
# 1. Start execution with a hard spend limitcurl -X POST -H 'Content-Type: application/json' \-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \-d '{"channelUrls": [{ "url": "https://www.youtube.com/@handle" }],"maxVideos": 0,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}' \'https://api.apify.com/v2/acts/techforce.global~youtube-full-channel-transcripts-scraper/runs?maxTotalChargeUsd=10'# 2. Pollcurl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \'https://api.apify.com/v2/actor-runs/<runId>'# 3. Retrieve when SUCCEEDEDcurl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \'https://api.apify.com/v2/datasets/<DATASET_ID>/items?clean=true&format=json'
maxVideos: 0 scrapes the entire channel. maxTotalChargeUsd is the only hard ceiling —
never run 0 without it.
Minimal RAG-ingestion configuration
{"channelUrls": [{ "url": "https://www.youtube.com/@handle" }],"maxVideos": 0,"includeTranscriptText": true,"includeTranscriptSegments": false,"includeChannelName": true,"includeDatePublished": true,"includeViewCount": false,"includeSubscriberCount": false,"deliveryMode": "none","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Transcript, title, channel and date — the four things a retrieval index actually needs. Every
Tier 2 and Tier 3 toggle off, so there is no extra request per video and none per channel.
Note that with no Tier 2 toggle on, datePublished may be null; if the date is essential to your
index, accept one extra request per video by enabling includeDateText. Pair with a spend cap.
Timestamped segments for clip-finding
{"channelUrls": [{ "url": "https://www.youtube.com/@handle" }],"maxVideos": 100,"includeTranscriptText": false,"includeTranscriptSegments": true,"deliveryMode": "none","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Segments only, no duplicated plain text — a smaller dataset when you're searching for moments rather than embedding whole documents.
Several channels at once
{"channelUrls": [{ "url": "https://www.youtube.com/@channelA" },{ "url": "https://www.youtube.com/@channelB" },{ "url": "https://www.youtube.com/@channelC" }],"maxVideos": 50,"includeChannelName": true,"deliveryMode": "none","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Channels are processed one after another; videos within each run in parallel. Every row carries
channelName and channelId, so the combined dataset stays separable.
With MCP delivery — one Notion page per transcript part
{"channelUrls": [{ "url": "https://www.youtube.com/@handle" }],"maxVideos": 20,"includeTranscriptText": true,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] },"mcpConnector": "<your-authorized-notion-connector>","mcpTool": "create_page","deliveryMode": "chunked","mcpArguments": {"parent": { "page_id": "<YOUR_NOTION_PAGE_ID>" },"title": "{title} (part {part}/{partCount})","content": "{videoUrl} — {language}, {segmentCount} segments\n\n{transcript}"}}
chunked is the right default for transcripts — a long video's text will not fit in one Notion
page. Avoid perSegment unless you want a record per line: it is one call per segment, per video.
Scheduling for a growing archive
Put a fixed input on a schedule with a modest
maxVideos. New uploads appear at the top of a channel's video list, so each run picks them up;
de-duplicate against your store on videoId.
⚠️ Autonomous Agent Error Handling & Resolution Matrix
Read this first: almost nothing about the content fails the run. A channel that won't
resolve, a video with transcripts disabled, and a record that can't be built are all logged and
skipped while the run continues to SUCCEEDED. An agent that checks run status alone will read an
empty or short dataset as success-with-data — check the row count and each row's
transcriptError.
The CONDITION labels below are documentation handles for observable states. This Actor does not
write an error code into the dataset; detect conditions from the run status, the log or the rows.
| Condition | What you observe | Underlying cause | Deterministic agent action |
|---|---|---|---|
MISSING_CHANNEL_URLS | Run rejected at input validation | channelUrls absent — it is required in the schema | Modify Input: supply at least one URL. |
EMPTY_CHANNEL_URLS | SUCCEEDED, empty dataset; log: No channel URLs provided in input. Exiting. | The array was present but contained nothing usable | Modify Input: pass at least one non-empty URL. |
CHANNEL_UNRESOLVED | SUCCEEDED; log: Failed to list videos for <url> and that channel contributes no rows | URL isn't a resolvable channel, or the listing was blocked | Modify Input: use @handle or /channel/ID, or paste any video URL from the channel. Then retry with the residential proxy. |
PARTIAL_CHANNEL_FAILURE | Multi-channel run with rows from some channels only | One channel's listing failed; the loop continued | Expected, partial. Re-run just the failed channel. |
BOT_CHECK_BLOCKED | Empty or thin dataset; sign-in-to-confirm errors in the log | Datacenter IP, no proxy passed, or proxy alone insufficient | Modify Input: RESIDENTIAL group, then add cookies. Lower maxConcurrency to 3. |
NO_PROXY_APPLIED | Log startup line shows proxy=disabled | proxyConfiguration omitted or empty in a hand-built input | Modify Input: pass the proxy object explicitly. |
TRANSCRIPT_ERROR_ROWS | Rows with transcriptError, null transcript | Creator disabled transcripts, or none in any language | Expected, not a failure. The row is a record of the gap. Route to ASR if you must have text. |
WRONG_LANGUAGE | transcriptLanguage isn't what you asked for | Preference list didn't match; silent fallback | Filter output on transcriptLanguage, or accept the fallback. |
AUTO_GENERATED_QUALITY | Transcript text has errors, odd punctuation | transcriptIsGenerated: true | Filter on that flag, or clean downstream. |
ROW_COUNT_BELOW_VIDEO_COUNT | Dataset smaller than the Found N video(s) line; log: Failed to build record for <id> | Individual records failed to assemble | Expected, partial. Re-run those IDs if they matter. |
MISSING_FIELD_KEYERROR | Consumer crashes on a missing key | That toggle was off — key is absent, not null | Fix consumer: use .get(). Or enable the toggle. |
NULL_DATE_PUBLISHED | datePublished null across rows | No per-video fetch was triggered, and the listing omitted the timestamp | Modify Input: enable a Tier 2 toggle (e.g. includeDateText) — costs one request per video. |
NULL_LIKES | likes null despite the toggle | Creator hides likes | Expected. Null ≠ zero. |
NULL_SUBSCRIBER_COUNT | subscriberCount null | Channel hides it, or the channel fetch failed — log: Could not fetch extended channel metadata | Expected. Retry once if the log shows a fetch failure. |
RUN_MUCH_LONGER_THAN_EXPECTED | Run still going well past estimate | maxVideos: 0 on a large channel, or many channels | Abort and re-run with a real maxVideos, or wait with a spend cap in place. Rows already saved are kept. |
RATE_LIMITED_BY_YOUTUBE | Increasing failures partway through | maxConcurrency too high | Modify Input: drop to 3–8 and retry. |
PERSEGMENT_FELL_BACK | One summary call per video instead of per-segment calls; log: perSegment delivery requested for <id> but no timestamped segments are available | includeTranscriptSegments is off | Modify Input: enable it, or switch to chunked. Not a failure. |
CONNECTOR_RATE_LIMITED | Connector errors partway through | Delivery is per video — perSegment or chunked multiplies the calls | Modify Input: switch to summary, or lower maxVideos. |
CONNECTOR_TOOL_MISSING | Log: A connector is selected but no tool name was provided | mcpTool empty | Modify Input: set mcpTool. Dataset already saved. |
CONNECTOR_TOOL_NOT_FOUND | Log: Tool 'x' is not available on this connector. Available tools: … | mcpTool name is wrong | Modify Input: copy an exact name from that log line. Dataset unaffected. |
CONNECTOR_UNREACHABLE | Log: Could not reach the connector: … | Connector not authorised, or the run isn't on the Apify platform | Authorise it in Apify, or set deliveryMode: "none". Data already saved. |
MCP_PROXY_MISSING | Log: APIFY_MCP_PROXY_URL is not set | Running locally with apify run | Reconfigure: apify push and run on the platform. |
PROXY_UNAVAILABLE | Log shows the proxy could not be set up | Residential groups require a paid Apify plan | Prompt user: upgrade the plan; expect bot-wall failures until then. |
AUTH_INVALID | HTTP 401 | Missing or malformed APIFY_TOKEN | Abort & prompt user: request a valid API token. |
RATE_LIMITED | HTTP 429 | Apify API rate / concurrency limits | Retry: exponential backoff (2s, 4s, 8s). |
SYNC_TIMEOUT | HTTP 408 on the sync endpoint | Run exceeded the synchronous ceiling | Reconfigure: switch to async POST /runs + polling. |
Provenance of this table: every log line, status and dataset condition above is taken from this Actor's own source and verified against it. The three HTTP rows (
401,408,429) describe the Apify API transport layer, not this Actor — confirm them against the Apify API reference before wiring them into automated retry logic.
🗣️ Natural Language → Actor Mapping
| A user says… | Intent | Constructed Actor input |
|---|---|---|
| "Get transcripts from this channel" | Core | {"channelUrls":[{"url":"<url>"}],"maxVideos":10} |
| "Every video this channel ever posted" | Full archive | {"channelUrls":[{"url":"<url>"}],"maxVideos":0} + spend cap |
| "Last 100 videos with transcripts" | Recent slice | {"channelUrls":[{"url":"<url>"}],"maxVideos":100} |
| "I need timestamps so I can link to the moment" | Segments | {"channelUrls":[{"url":"<url>"}],"includeTranscriptSegments":true} |
| "Build a searchable index of their content" | RAG ingestion | Minimal config above, maxVideos: 0 |
| "Transcripts in Hindi if available" | Language preference | {"transcriptLanguages":["hi","en"]} — then check transcriptLanguage |
| "Only human-written transcripts" | Quality filter | Scrape, then filter transcriptIsGenerated == false |
| "Which of their videos have no transcript?" | Gap audit | Scrape, then filter rows that have transcriptError |
| "Compare three channels' topics" | Multi-channel | {"channelUrls":[{"url":"A"},{"url":"B"},{"url":"C"}],"maxVideos":50} |
| "Transcripts plus likes and descriptions" | Rich metadata | Enable includeLikes + includeDescription — one extra request per video |
| "Full channel stats too" | Extended metadata | Enable the Tier 3 channel toggles — one shared fetch per channel |
| "Just a quick sample" | Cheap probe | {"channelUrls":[{"url":"<url>"}],"maxVideos":3} |
| "It returned nothing" | Blocked | RESIDENTIAL proxy, add cookies, maxConcurrency: 3 |
| "Put each transcript in Notion" | Scrape + deliver | Above, plus mcpConnector, mcpTool, deliveryMode: "chunked" |
| "Just this one video's transcript" | Single video | ➡️ Route to YouTube Transcript Scraper |
| "What are people saying in the comments?" | Comment text | ➡️ Route to YouTube Scraper |
| "Download their videos" | Media | ➡️ Route to YouTube Shorts Scraper for Shorts; long-form files are out of scope |
Should NOT route here: comment threads (→ YouTube Scraper) · search terms or hashtags as input · a single video (→ Transcript Scraper) · creator analytics — watch time, retention, revenue, demographics · downloading video or audio files · translated transcripts · transcripts for videos where the creator disabled them · private, unlisted or members-only videos · uploading or any write operation.
🧭 Agent Execution & Routing Logic
Does the user want what was SAID in YouTube videos?├── NO → not this Actor.│ comment threads → YouTube Scraper│ search / hashtag input → YouTube Scraper│ a channel's Shorts/files → YouTube Shorts Scraper│ watch time / revenue → creator's own account only│└── YES│├── One video, or a channel?│ ├── one video → YouTube Transcript Scraper (also does translation)│ └── channel → this Actor│├── channelUrls — REQUIRED, an ARRAY.│ @handle / /channel/ID / /c/ / /user/ / any video URL from the channel│ several channels? → put them all in the array (processed sequentially)│├── ALWAYS pass proxyConfiguration explicitly at RESIDENTIAL│ └── still blocked? → add `cookies`, and drop maxConcurrency to 3│├── What transcript shape?│ ├── embedding / search → includeTranscriptText (default on)│ ├── deep-links / clips → includeTranscriptSegments (default OFF)│ └── both → enable both│├── How many videos?│ ├── a probe → 3│ ├── a slice → 10-100│ └── the archive → 0 + ALWAYS a spend cap (can be thousands)│├── Which metadata? (THREE cost tiers — check before toggling)│ ├── free → channelName, channelId, viewCount, thumbnail│ ├── per VIDEO → likes, comments, keywords, description, dateText,│ │ relativeDateText (any one triggers the fetch; all six cost the same)│ └── per CHANNEL → the six channel toggles share ONE fetch│ └── need none of them? turn subscriberCount OFF too — it is on by default│├── Language matters?│ └── set transcriptLanguages, then FILTER on transcriptLanguage afterwards│ (the list is a preference — fallback is silent)│└── Should transcripts land in another app?├── yes → mcpConnector + mcpTool + {message} in mcpArguments│ transcripts are LONG → chunked (recommended)│ one message each → summary│ record per line → perSegment (needs segments on; huge call count)└── no → deliveryMode "none", or leave mcpConnector empty[Execute Actor]├──► SUCCEEDED, rows == videos found → assess Transcript Health, then consume├──► SUCCEEDED, rows < videos found → some records failed to build; read the log└──► SUCCEEDED, 0 rows → channel unresolved / blocked / no public videos
💰 Cost Control & Pricing Transparency
Billing model: usage-based. This Actor bills for platform usage — the compute time and resources a run consumes — not per row. Current rates are on the Actor's Apify Store page, and the Console shows the live total while a run is in progress.
| Choice | Effect on cost |
|---|---|
maxVideos | The main driver. Each video is at least a transcript fetch. 0 is unbounded. |
| Number of channels | Multiplies everything, and channels run sequentially. |
| Tier 2 toggles | The second-biggest lever: one extra request per video. Enabling one costs the same as enabling all six. |
| Tier 3 (channel) toggles | One shared fetch per channel. Negligible for one channel, real for fifty. On by default via includeSubscriberCount. |
| Tier 1 toggles | Free. The data is already fetched; toggling only changes what's written. |
maxConcurrency | Higher finishes sooner if you aren't rate-limited. Being limited makes it slower. |
includeTranscriptSegments | Negligible extra fetch cost, but a much larger dataset. |
| Being blocked | Costs run time and returns nothing. A datacenter proxy is the most expensive setting on this page. |
Worked examples — relative run shape
Multiply by your account's usage rate from the Store page to get a currency figure.
| Scenario | Videos | Requests per video | Relative cost | Notes |
|---|---|---|---|---|
| Probe — 3 videos, defaults | 3 | 1 transcript | Baseline | Plus one channel fetch (subscriber count). |
| RAG slice — 100 videos, all Tier 2/3 off | 100 | 1 transcript | ≈ 33 × baseline | The cheapest shape per video. |
Same 100 videos, includeDescription on | 100 | 1 transcript + 1 metadata | ≈ 2 × the row above | One Tier 2 toggle doubles per-video requests. |
| Same 100 videos, all six Tier 2 toggles on | 100 | 1 transcript + 1 metadata | Same as the row above | Six toggles, one fetch — no extra cost. |
| 100 videos with all Tier 3 channel toggles | 100 | unchanged | ≈ RAG slice + one channel fetch | Channel toggles are shared and cheap. |
| Segments instead of text | 100 | unchanged | ≈ RAG slice, larger dataset | Storage grows, requests don't. |
| Three channels × 50 videos | 150 | 1 transcript | ≈ 50 × baseline | Plus three channel fetches. |
Whole channel, maxVideos: 0 | all of them | 1 transcript | Scales linearly, unbounded | Never without maxTotalChargeUsd. |
| Blocked run (datacenter IP) | 0 useful | — | Wasted run time, zero rows | The worst value on this page. |
Keeping runs predictable:
- First run: one channel,
maxVideos: 3. Confirm transcripts are coming back and in the language you expect. - Check the Transcript Health view before scaling. If most rows are auto-generated or in the wrong language, scaling multiplies a corpus you may not want.
- Decide the Tier 2 question up front. Either you need per-video metadata and pay one extra request per video, or you don't and you shouldn't enable any of the six.
- Turn off Tier 3 entirely if you don't need channel stats — including
includeSubscriberCount, which is on by default. maxVideos: 0only with a spend cap. A prolific channel is thousands of transcript fetches.- Prefer scheduled incremental runs over one giant archive run — a modest
maxVideoson a schedule, de-duplicated onvideoId, is cheaper and more resilient than one long run.
🛠️ Troubleshooting
Most problems are transcript availability, proxy, or toggle semantics — not scraper bugs. Work through this table top to bottom; the first three rows account for the large majority of support tickets.
| # | Symptom you see | Most likely cause | Fix |
|---|---|---|---|
| 1 | SUCCEEDED but the dataset is empty | The channel didn't resolve, has no public videos, or the listing was bot-blocked | Read the log — Failed to list videos for <url> names it. Use an @handle or /channel/ID, and keep the residential proxy on. |
| 2 | Thin or empty results that used to work | Bot check — datacenter IP, or no proxy passed at all | Confirm the startup log says proxy=enabled. Pass {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} explicitly, then add cookies. |
| 3 | Many rows have transcriptError | Those creators disabled transcripts, or no track exists in any language | Expected. This Actor reads captions; it does not transcribe audio. Check the Transcript Health view for the overall ratio. |
| 4 | Transcripts came back in the wrong language | transcriptLanguages is a preference — the fallback is silent | Read transcriptLanguage per row and filter. There is no strict-language mode. |
| 5 | Text reads like speech-to-text with no punctuation | The source track is YouTube's auto-generated caption | Check transcriptIsGenerated: true. Filter it out, or clean downstream. |
| 6 | KeyError / undefined on a field | That toggle was off — the key is absent, not null | Use .get() / optional access, or enable the toggle. |
| 7 | datePublished is null everywhere | No per-video fetch was triggered, and the listing omitted the timestamp | Enable a Tier 2 toggle such as includeDateText — it costs one extra request per video. |
| 8 | likes is null despite enabling it | The creator hides the like count | Expected. Null ≠ zero. |
| 9 | subscriberCount is null | The channel hides it, or the channel fetch failed (Could not fetch extended channel metadata) | Retry once; if it persists, the channel hides the number. |
| 10 | Fewer rows than the Found N video(s) line | Some records failed to build — logged as Failed to build record for <id> | Partial, not fatal. Re-run those IDs if they matter. |
| 11 | The run is far slower than expected | maxVideos: 0, several channels, or a Tier 2 toggle doubling per-video requests | Cap maxVideos, or accept the cost. Rows saved so far are kept if you abort. |
| 12 | Failures increase partway through a big run | YouTube is rate-limiting the concurrency | Drop maxConcurrency to 3–8 and re-run. |
| 13 | Rows aren't in upload order | Videos are processed in parallel and saved as they finish | Sort by datePublished client-side (enable a Tier 2 toggle so the date is populated). |
| 14 | Only one channel produced rows in a multi-channel run | One channel's listing failed; the loop moved on | Re-run just that channel with a full URL and the residential proxy. |
| 15 | You wanted the comments, not the count | Only comments (the count) is available | Use the YouTube Scraper for comment threads. |
| 16 | You expected translated text | The Actor returns YouTube's published captions untranslated | Use the single-video Transcript Scraper for auto-translation, or translate downstream. |
| 17 | perSegment produced one message per video instead of per segment | includeTranscriptSegments was off — the Actor warns and falls back to a summary call | Enable segments, or switch to chunked if that was what you wanted. |
| 18 | Slack / Notion / Linear received nothing | Delivery needs both mcpConnector and mcpTool; otherwise it is skipped with a warning | Set both. Every dataset row is still saved — your data is never lost. |
| 19 | Log: Tool 'x' is not available on this connector | Wrong tool name for that connector | Copy an exact name from the Available tools: list in the same log line. |
| 20 | Connector fired, but the message body is empty | mcpArguments did not reference {message} | Map {message} in mcpArguments and populate mcpMessageTemplate. |
| 21 | Notion rejects or truncates a long transcript | Single-call payload exceeded block/timeout caps | Use deliveryMode: "chunked" and put {part}/{partCount} in the page title. |
| 22 | Every Notion page looks identical | {part}/{partCount} missing from the title template | Add them: "{title} (part {part}/{partCount})". |
| 23 | Far more connector calls than expected | Delivery is per video, and chunked/perSegment multiply it | Use summary, or lower maxVideos. |
| 24 | Delivery fired when you only wanted a dataset | deliveryMode defaults to summary, not none | Set deliveryMode: "none" or leave mcpConnector empty. |
| 25 | Log: APIFY_MCP_PROXY_URL is not set | You ran locally with apify run; connectors only resolve on the platform | Deploy with apify push and run on the platform. |
| 26 | HTTP 401 / 403 | Missing, expired, or malformed APIFY_TOKEN | Regenerate in Apify Console → Settings → API & Integrations, send as Authorization: Bearer <token>. |
| 27 | HTTP 429 | Apify account concurrency / rate limits — not YouTube blocking | Retry with exponential backoff (2s → 4s → 8s). |
| 28 | HTTP 408 on run-sync-get-dataset-items | The synchronous endpoint has a hard time ceiling | Switch to async: POST /runs → poll /actor-runs/<runId> → fetch dataset. |
Diagnostic checklist before opening an issue
- Open one of the channel's videos in a browser and check the transcript panel (⋯ → Show transcript). If YouTube shows nothing there, that video has no captions and no scraper can produce them.
- Confirm the proxy. The startup log line says
proxy=enabledorproxy=disabled. Residential group, paid plan active. - Baseline run: one channel URL,
maxVideos: 3, defaults everywhere else,deliveryMode: "none". - Read the Transcript Health view — language, auto-generated flag and error per video, in one table.
- Compare the dataset row count with the
Found N video(s)log line. - Try
cookiesfrom a throwaway logged-in session if the bot check persists.
If the issue survives all six steps, open an Issues ticket on the Actor page (or email support) with the run ID, the channel 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 and public metadata. 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 a third-party channel it is not an option at all — which is the main reason this Actor exists.
Do I need a paid Apify plan?
For reliable runs, yes: the default residential proxy group requires a paid plan, and YouTube serves datacenter IPs a "Sign in to confirm you're not a bot" wall.
When do I need the cookies field?
Only when a residential proxy alone doesn't clear the bot check. Paste a Netscape cookies.txt export from a logged-in session; it is stored as a secret input. Use a throwaway account rather than your primary one — supplying cookies puts that account in scope.
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-full-channel-transcripts-scraper"
Input & scope
What channel URL formats are accepted?
@handle, /channel/ID, /c/name, /user/name, a tab URL like /videos, or any single video URL from the channel — the channel is resolved from it for you.
Can I scrape several channels in one run?
Yes — channelUrls is an array. Channels are processed one after another; videos within each channel run in parallel up to maxConcurrency.
How do I get every video on a channel?
Set maxVideos: 0, which is uncapped per channel. On a prolific channel that is thousands of transcript fetches, so always pair it with maxTotalChargeUsd.
Can I choose the transcript language?
You can express a preference with transcriptLanguages, in priority order. It is not a filter: if no preferred language exists, the Actor returns any available transcript — including auto-generated — without warning per video. Always read transcriptLanguage on each row.
Can it translate transcripts?
No. It returns what YouTube publishes, untranslated. The single-video Transcript Scraper does auto-translation across 13 languages.
Output & fields
Why is a field missing from my rows?
Because its toggle is off. A toggled-off field is an absent key, not a null — use .get() or optional access rather than indexing.
Which toggles cost extra requests?
Three tiers. channelName, channelId, viewCount and thumbnail are free. likes, comments, keywords, description, dateText and relativeDateText trigger one extra request per video — enabling one costs the same as enabling all six. The six extended channel toggles share one fetch per channel between them.
Why is datePublished null?
It is derived from whatever the channel listing returned, and the listing frequently omits the timestamp. Enabling any per-video toggle (for example includeDateText) triggers the full fetch and fills the date in — at the cost of one extra request per video.
What does transcriptError mean?
That this video's transcript could not be retrieved — the creator disabled captions, or none exist in any language. The row is still saved, with transcript null, so your channel inventory stays complete. Its absence means the transcript succeeded.
How do I know if a transcript is auto-generated?
transcriptIsGenerated: true. Machine transcripts carry recognition errors, unreliable punctuation and mangled proper nouns — filter on the flag before quoting or before treating the text as high quality.
Why are there fewer rows than the log's video count?
A video whose record couldn't be assembled is logged as Failed to build record for <id> and skipped. The run still succeeds; compare the dataset size against the Found N video(s) line and re-run those videos if they matter.
Can I get the comments themselves?
No — only the comment count, and only if you enable includeComments. Comment threads are the personal-data-heavy part of YouTube and are deliberately out of scope. Use the YouTube Scraper if you need them.
Can it download the video or audio files?
No. Transcripts and metadata only. For a channel's Shorts as MP4 or audio, use the YouTube Shorts Scraper.
Delivery
What is the MCP connector for?
It pushes each video's transcript straight into a tool you have already authorized on your Apify account — Notion, Slack, Linear, Jira, GitHub, 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?
chunked for transcripts, because a long video's text will not fit in one page or message. summary for short videos, perSegment only when you genuinely want a record per line, none for dataset-only runs. Remember delivery fires per video.
What happens if I pick perSegment without segments?
It does not fail and does not go silent: the Actor logs a warning and sends one summary call for that video instead. Enable includeTranscriptSegments to get real per-segment delivery.
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 is saved as normal.
Limits & pricing
What does it cost?
Usage-based: you pay for the platform usage a run consumes, not per row. The drivers are maxVideos, the number of channels, and whether any per-video metadata toggle is on. Current rates are on the Actor's Apify Store page, and the Console shows a live total while a run is in progress.
How do I stop a run from overspending?
Pass maxTotalChargeUsd on the run endpoint — it is the only hard ceiling — and never run maxVideos: 0 without it. Cache by videoId so scheduled re-runs don't re-fetch what you already have.
🔍 Companion machine-readable files
| File | What it defines |
|---|---|
| .actor/input_schema.json | Every input and toggle, with types, defaults and bounds |
| .actor/dataset_schema.json | All 25 possible output fields, which toggle each needs, and the four Console views |
| .actor/output_schema.json | Where the run's output is exposed |
| .actor/actor.json | Actor identity and storage wiring |
my_actor/main.py | Channel loop, concurrency, toggle resolution and record assembly |
my_actor/connector.py | MCP connector session handling, transcript packing and {placeholder} rendering |
If this page and the schema files disagree, the schema files win. They are what the platform validates against at run time; this page is documentation and can lag a release.
🔗 Related Actors by Techforce Global
Other YouTube Actors
This Actor is the channel-scale transcript specialist: one channel in, every video's words out. Use these siblings when the job is different.
| Actor | Best for | Why pick it over this one |
|---|---|---|
| YouTube Transcript Scraper | One video's timestamped transcript, in 13 languages with auto-translation | You have a single URL, or you need the transcript translated — this Actor returns captions untranslated. |
| YouTube Scraper: Videos, Channels & Comments | Video, channel and comment metadata from search queries, channel URLs, video URLs or hashtags | You need views, likes, comment threads, or discovery by search and hashtag — none of which this Actor's transcripts give you. |
| YouTube Shorts Scraper | A channel's Shorts with engagement metrics and optional MP4/audio download | You're working through short-form output, or you need the media files themselves. |
Pick by intent: a channel's words → this Actor · one video's words → Transcript Scraper · numbers, comments and discovery → YouTube Scraper · Shorts and their files → Shorts Scraper.
Enrichment & downstream pipeline
| Actor | Use it for |
|---|---|
| Advanced Website Crawling Actor | Crawl the creator's site, blog or show notes for clean HTML/Markdown/text in the same corpus |
| Pinterest Scraper | Pins from searches, boards, profiles and pin URLs |
| All Jobs Scraper | Job listings aggregated across many boards |
Suggested pipeline patterns
🔎 Video knowledge base
This Actor with maxVideos: 0 for the backfill → the
single-video Transcript Scraper
for each new upload → store by videoId → index the transcript text for semantic search across
everything the channel has 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.
✍️ Content repurposing at scale This Actor → transcript text into your LLM of choice → blog drafts, threads, newsletters → publish through a Notion or Slack connector.
🌍 Multi-channel topic mapping
Several channelUrls in one run → cluster transcript text per channel → compare what each
creator actually covers rather than what their titles claim.
🤖 Agent retrieval tool Register the Actor as an MCP tool so an agent can pull a channel's corpus on demand and answer questions with links and timestamps.
Browse all Actors by Techforce Global at scraper.techforce.global.
🔐 Compliance & Data Privacy
Trademark & affiliation. 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.
-
Public content only. Everything returned is visible to any signed-out visitor. No private or members-only videos, and no bypassing of authentication.
-
No comment text in the output. Transcripts are the video's spoken content; metadata is content and channel statistics. Comment threads — the part of YouTube that is personal data — are not collected by this Actor. That makes it materially lower-risk than its comment-scraping sibling.
-
But a transcript is speech, and speakers are people. A transcript of an interview or a vlog contains an identifiable person's words, and can contain third parties' names, health details or opinions spoken aloud. Under GDPR / UK GDPR and CCPA/CPRA that content can be personal data about the speaker and about anyone discussed. Treat a transcript corpus as you would any document set containing personal information: a retention policy, access control, and no re-publication of individuals' statements out of context.
-
Special-category content cannot be filtered in advance. Health, politics, religion and sexuality come up in spoken content, and you cannot know which transcripts contain it until after retrieval. Keep retention short and access controlled.
-
Transcripts are copyrighted material. The spoken words of a video are the creator's expression, and YouTube's auto-generated captions are derived from it. Internal research, search and analysis sit on far safer ground than republishing transcripts as your own content or presenting them as an alternative to watching the video.
-
Using transcripts to train a model is a distinct act with distinct risk. Scraping for analysis and ingesting into a training corpus are not the same thing legally, and the licensing position for the latter is contested. If that's your plan, get advice rather than relying on "it was public".
-
Auto-generated transcripts contain errors — don't attribute them as verbatim quotes.
transcriptIsGenerated: truemeans a machine wrote it. Mis-transcribed names and negations can invert meaning. Quoting a machine transcript as something a person said is a misattribution risk, and potentially a defamation one. Check the flag before quoting. -
YouTube's Terms of Service prohibit automated access, including circumventing access restrictions. This Actor does not remove that risk — it is a risk you accept by running it. Supplying
cookiesfrom your own logged-in session also puts your account in scope; use a throwaway account rather than your primary one if you go that route. -
Attribution over mirroring.
videoUrlis on every row. Link back rather than presenting a transcript archive as a substitute for the source, and credit the channel.
🆘 Support & Custom Pipeline Engineering
Need automated multi-city scheduled feeds, webhook enrichment, or enterprise data warehouse syncs?
- Email: bhavin.shah@techforceglobal.com
- Custom Enterprise Integrations: Book a 15-Minute Technical Consultation
- Maintained by: Techforce Global — Specialists in High-Performance Web Scrapers and Agentic Workflows.
🏷️ Structured data for search & AI discovery
Two blocks: SoftwareApplication describing the Actor, and FAQPage wrapping the FAQ above so those answers are eligible for rich results. The FAQPage entries are generated from the visible FAQ and match it question-for-question.
{"@context": "https://schema.org","@type": "SoftwareApplication","name": "YouTube Full Channel Transcripts Scraper","alternateName": "YouTube Channel Transcript Scraper","applicationCategory": "DeveloperApplication","applicationSubCategory": "Web Scraping / Video Transcripts & RAG Ingestion","operatingSystem": "Cloud (Apify platform)","description": "Scrapes the transcript of every video on one or more YouTube channels — as a single plain-text string, as timestamped {text, start, duration} segments, or both — alongside 19 individually toggleable video and channel metadata fields, without a Google API key, OAuth, or video ownership. Resolves a channel from an @handle, /channel/ID, /c/, /user/ path or any video URL. Reports the language actually retrieved, whether the transcript was auto-generated, and a per-video error when none was available, so gaps are recorded rather than silently dropped. Public captions only, with GDPR/CCPA and speaker-identifiability guidance included. Residential proxy by default with optional cookie support, and optional delivery into Notion, Slack, Linear, Airtable or any MCP connector with chunking for long transcripts.","url": "https://apify.com/techforce.global/youtube-full-channel-transcripts-scraper","author": {"@type": "Organization","name": "Techforce Global","url": "https://www.techforceglobal.com"},"provider": {"@type": "Organization","name": "Apify","url": "https://apify.com"},"offers": {"@type": "Offer","priceCurrency": "USD","category": "Pay per platform usage","description": "Usage-based: billed for the compute time and resources a run consumes, not per row. Current rates are shown on the Actor's Apify Store page.","url": "https://apify.com/techforce.global/youtube-full-channel-transcripts-scraper"},"featureList": ["Transcript for every video on a channel, or the newest N","Several channels in a single run","Plain-text transcript for embedding and search","Timestamped segments for deep-linking to a moment","Reports the language actually retrieved, not just the one requested","Flags auto-generated transcripts so quality can be assessed","Per-video error field so gaps are recorded rather than silently dropped","19 individually toggleable metadata fields across three cost tiers","Channel resolved from a handle, ID, legacy path or any video URL","Residential proxy by default, rotated per video, plus optional secret cookie input","Configurable parallelism from 1 to 50 videos at once","Rows saved as they are scraped, so aborted runs keep their partial data","Optional MCP delivery with chunking for long transcripts","Four Console dataset views including a transcript-health view"],"isAccessibleForFree": false,"softwareRequirements": "Apify account and API token; a paid plan for residential proxies","keywords": "YouTube channel transcript scraper, bulk YouTube transcripts, video transcripts, RAG ingestion, subtitle extraction, timestamped segments, content analysis, video search index, media research, MCP connector"}
{"@context": "https://schema.org","@type": "FAQPage","mainEntity": [{"@type": "Question","name": "Do I need a YouTube or Google account, API key, or OAuth app?","acceptedAnswer": {"@type": "Answer","text": "No. The Actor reads publicly available caption tracks and public metadata. You need an Apify account and API token; you need no Google credentials whatsoever."}},{"@type": "Question","name": "Is this the official YouTube API?","acceptedAnswer": {"@type": "Answer","text": "No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by YouTube or Google."}},{"@type": "Question","name": "Why can't I just use the official YouTube Data API?","acceptedAnswer": {"@type": "Answer","text": "captions.download only works for videos you own, via OAuth. For a third-party channel it is not an option at all — which is the main reason this Actor exists."}},{"@type": "Question","name": "Do I need a paid Apify plan?","acceptedAnswer": {"@type": "Answer","text": "For reliable runs, yes: the default residential proxy group requires a paid plan, and YouTube serves datacenter IPs a \"Sign in to confirm you're not a bot\" wall."}},{"@type": "Question","name": "When do I need the cookies field?","acceptedAnswer": {"@type": "Answer","text": "Only when a residential proxy alone doesn't clear the bot check. Paste a Netscape cookies.txt export from a logged-in session; it is stored as a secret input. Use a throwaway account rather than your primary one — supplying cookies puts that account in scope."}},{"@type": "Question","name": "Can I plug it into Claude, Cursor, or a LangChain agent?","acceptedAnswer": {"@type": "Answer","text": "Yes — it is a native MCP tool: claude mcp add --transport http apify \"https://mcp.apify.com?tools=techforce.global/youtube-full-channel-transcripts-scraper\""}},{"@type": "Question","name": "What channel URL formats are accepted?","acceptedAnswer": {"@type": "Answer","text": "@handle, /channel/ID, /c/name, /user/name, a tab URL like /videos, or any single video URL from the channel — the channel is resolved from it for you."}},{"@type": "Question","name": "Can I scrape several channels in one run?","acceptedAnswer": {"@type": "Answer","text": "Yes — channelUrls is an array. Channels are processed one after another; videos within each channel run in parallel up to maxConcurrency."}},{"@type": "Question","name": "How do I get every video on a channel?","acceptedAnswer": {"@type": "Answer","text": "Set maxVideos: 0, which is uncapped per channel. On a prolific channel that is thousands of transcript fetches, so always pair it with maxTotalChargeUsd."}},{"@type": "Question","name": "Can I choose the transcript language?","acceptedAnswer": {"@type": "Answer","text": "You can express a preference with transcriptLanguages, in priority order. It is not a filter: if no preferred language exists, the Actor returns any available transcript — including auto-generated — without warning per video. Always read transcriptLanguage on each row."}},{"@type": "Question","name": "Can it translate transcripts?","acceptedAnswer": {"@type": "Answer","text": "No. It returns what YouTube publishes, untranslated. The single-video YouTube Transcript Scraper does auto-translation across 13 languages."}},{"@type": "Question","name": "Why is a field missing from my rows?","acceptedAnswer": {"@type": "Answer","text": "Because its toggle is off. A toggled-off field is an absent key, not a null — use .get() or optional access rather than indexing."}},{"@type": "Question","name": "Which toggles cost extra requests?","acceptedAnswer": {"@type": "Answer","text": "Three tiers. channelName, channelId, viewCount and thumbnail are free. likes, comments, keywords, description, dateText and relativeDateText trigger one extra request per video — enabling one costs the same as enabling all six. The six extended channel toggles share one fetch per channel between them."}},{"@type": "Question","name": "Why is datePublished null?","acceptedAnswer": {"@type": "Answer","text": "It is derived from whatever the channel listing returned, and the listing frequently omits the timestamp. Enabling any per-video toggle (for example includeDateText) triggers the full fetch and fills the date in — at the cost of one extra request per video."}},{"@type": "Question","name": "What does transcriptError mean?","acceptedAnswer": {"@type": "Answer","text": "That this video's transcript could not be retrieved — the creator disabled captions, or none exist in any language. The row is still saved, with transcript null, so your channel inventory stays complete. Its absence means the transcript succeeded."}},{"@type": "Question","name": "How do I know if a transcript is auto-generated?","acceptedAnswer": {"@type": "Answer","text": "transcriptIsGenerated: true. Machine transcripts carry recognition errors, unreliable punctuation and mangled proper nouns — filter on the flag before quoting or before treating the text as high quality."}},{"@type": "Question","name": "Why are there fewer rows than the log's video count?","acceptedAnswer": {"@type": "Answer","text": "A video whose record couldn't be assembled is logged as Failed to build record for <id> and skipped. The run still succeeds; compare the dataset size against the Found N video(s) line and re-run those videos if they matter."}},{"@type": "Question","name": "Can I get the comments themselves?","acceptedAnswer": {"@type": "Answer","text": "No — only the comment count, and only if you enable includeComments. Comment threads are the personal-data-heavy part of YouTube and are deliberately out of scope. Use the YouTube Scraper if you need them."}},{"@type": "Question","name": "Can it download the video or audio files?","acceptedAnswer": {"@type": "Answer","text": "No. Transcripts and metadata only. For a channel's Shorts as MP4 or audio, use the YouTube Shorts Scraper."}},{"@type": "Question","name": "What is the MCP connector for?","acceptedAnswer": {"@type": "Answer","text": "It pushes each video's transcript straight into a tool you have already authorized on your Apify account — Notion, Slack, Linear, Jira, GitHub, 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."}},{"@type": "Question","name": "Which delivery mode should I use?","acceptedAnswer": {"@type": "Answer","text": "chunked for transcripts, because a long video's text will not fit in one page or message. summary for short videos, perSegment only when you genuinely want a record per line, none for dataset-only runs. Remember delivery fires per video."}},{"@type": "Question","name": "What happens if I pick perSegment without segments?","acceptedAnswer": {"@type": "Answer","text": "It does not fail and does not go silent: the Actor logs a warning and sends one summary call for that video instead. Enable includeTranscriptSegments to get real per-segment delivery."}},{"@type": "Question","name": "Does delivery work when running locally?","acceptedAnswer": {"@type": "Answer","text": "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 is saved as normal."}},{"@type": "Question","name": "What does it cost?","acceptedAnswer": {"@type": "Answer","text": "Usage-based: you pay for the platform usage a run consumes, not per row. The drivers are maxVideos, the number of channels, and whether any per-video metadata toggle is on. Current rates are on the Actor's Apify Store page, and the Console shows a live total while a run is in progress."}},{"@type": "Question","name": "How do I stop a run from overspending?","acceptedAnswer": {"@type": "Answer","text": "Pass maxTotalChargeUsd on the run endpoint — it is the only hard ceiling — and never run maxVideos: 0 without it. Cache by videoId so scheduled re-runs don't re-fetch what you already have."}}]}