apihq/youtube-transcript-scraper · YouTube
YouTube Transcript Scraper
Scrape YouTube transcripts, captions, and subtitles as timestamped JSON. One video or a batch of 50. No YouTube Data API key or quota, no browser.
$0.0030/transcript · failed items $0.0000 — on your existing Apify account, a one-item first run costs under a cent.
What does YouTube Transcript Scraper do?
Scrape YouTube transcripts, captions, and subtitles as clean timestamped JSON. No YouTube Data API key or quota, no browser. One video or batch up to 50. Returns caption segments plus video metadata and languages. Pay only for successful transcripts at $3 per 1,000; failed videos never charge.
Use it where videos become text: RAG pipelines, LLM training data, search indexes over spoken words, sentiment analysis, subtitle tooling. The stable error codes matter most when transcripts feed an automated pipeline and one captionless video must not take down the batch.
It reads one video at a time, in batches of up to 50 IDs. It does not crawl a whole channel or playlist. Collect the IDs first with the YouTube Channel Scraper or YouTube Shorts Scraper, then feed them here.
2,500+ Actor runs recorded by Apify in the 30 days ending 2026-07-20; 3,400+ all-time.
Example run
{ "videoIds": ["jNQXAC9IVRw", "00000000000"] }outcome
- 1 success: true transcript for jNQXAC9IVRw ("Me at the zoo") — billed
- 1 success: false row, code: PLAYABILITY, for the unplayable ID — not billed
- Run status: SUCCEEDED
- Charged: 1 transcript = $0.003
Good input returns billed rows. Bad input returns free error rows in the same dataset, and the run still succeeds.
Why pipelines pick it
You pay only for transcripts delivered
A video with no fetchable transcript returns success:false and costs nothing. A batch of only captionless videos costs $0.
Every failure is machine-readable
Each failure carries a stable code such as NO_CAPTIONS or PLAYABILITY. Your pipeline branches on the code instead of parsing error text.
A hard 30-second deadline per video
If the upstream stalls, the actor writes an unbilled success: false row with code DEADLINE_EXCEEDED (status_code 504) and continues the batch, instead of hanging for an hour.
No YouTube Data API key or quota
The official Data API gates caption downloads behind the video owner's OAuth. This actor takes a plain video ID and returns JSON.
Best for: Use it where videos become text: RAG pipelines, LLM training data, search indexes over spoken words, sentiment analysis, subtitle tooling. The stable error codes matter most when transcripts feed an automated pipeline and one captionless video must not take down the batch.
Input & output
{
"videoIds": [
"jNQXAC9IVRw",
"dQw4w9WgXcQ",
"kJQP7kiw5Fk"
],
"language": "en",
"metadata": true
}{
"success": true,
"video_id": "jNQXAC9IVRw",
"language": "en",
"transcript": [
{ "text": "All right, so here we are, in front of the elephants", "start": 1.2, "duration": 2.16 },
{ "text": "the cool thing about these guys is that they have really really really long trunks", "start": 5.318, "duration": 7.298 },
{ "text": "and that's pretty much all there is to say", "start": 16.881, "duration": 2 }
],
"is_auto_generated": false,
"available_tracks": [
{ "language_code": "en", "language_name": "English", "is_auto_generated": false },
{ "language_code": "de", "language_name": "German", "is_auto_generated": false }
],
"metadata": {
"title": "Me at the zoo",
"author_name": "jawed",
"channel_id": "UC4QobU6STFB0P71PMvOGN5A",
"duration_seconds": 19
}
}{
"success": false,
"video_id": "00000000000",
"code": "PLAYABILITY",
"error": "Video 00000000000 is not playable: This video is unavailable",
"request_id": "req_911f37d2e55644ff9d9e4a3f",
"status_code": 403
}Branch on the success field to split hits from misses. Quote the request_id in any support issue and we can trace the exact request.
output fields
| field | type | what it is |
|---|---|---|
| success | boolean | true for a fetched transcript (billed), false for a video with no fetchable transcript (free). |
| video_id | string | The 11-character YouTube video ID. |
| language | string | Language code of the selected caption track. |
| transcript | array | Time-coded caption segments. Each has text, start, and duration. |
| is_auto_generated | boolean | True if the selected track is YouTube's ASR. |
| available_tracks | array | Every caption track the video exposes, with language code and name. |
| metadata | object | Video title, channel name and URL, thumbnail, channel ID, duration in seconds. Present when metadata: true (default). |
Error codes, stable across releases
Every failure record carries one of these machine-readable codes. None of them are ever charged.
| code | billed | meaning |
|---|---|---|
| NO_CAPTIONS | $0.0000 | The video has no caption track at all. |
| PLAYABILITY | $0.0000 | The video is private, deleted, age-gated, or otherwise not playable. |
| EMPTY_TRANSCRIPT | $0.0000 | The caption track parsed to zero segments. Treated as a failure, so you never pay for a blank transcript. |
| VALIDATION_FAILED | $0.0000 | The input was not a valid 11-character video ID. |
| DEADLINE_EXCEEDED | $0.0000 | The 30-second per-video deadline was hit. Returned as an unbilled row with status_code 504. |
| PO_TOKEN_REQUIRED | $0.0000 | YouTube demanded a proof-of-origin token for this request. |
| CAPTIONS_TIMEOUT | $0.0000 | The caption fetch itself timed out. |
| NO_INPUT | $0.0000 | No video IDs were provided. |
What a run costs
The charge fires only when a result is delivered, and platform compute is included in the per-result price. To cap the spend of a run, set a limit in Apify's Run Limits panel. The actor stops at the cap and reports how far it got.
What this actor doesn't do
- It reads one video at a time, in batches of up to 50 IDs. It does not crawl a whole channel or playlist. Collect the IDs first with the YouTube Channel Scraper or YouTube Shorts Scraper, then feed them here.
- It reads caption tracks that already exist, manual or auto-generated. It does not transcribe audio. A video with no captions returns success:false with code NO_CAPTIONS.
- It reads public videos only. Private, members-only, and age-gated videos return success:false.
Frequently asked questions
- Do I need a YouTube Data API key?
- No. The Actor reads YouTube's public data directly and does not consume Google API quota.
- What happens if a video has no captions?
- It comes back as a success:false record with code NO_CAPTIONS in the same dataset. You are not charged for it.
- Which languages are supported?
- Every language the creator uploaded. Pass a language code (en, de, en-US) to pick a track; omit it and the Actor prefers manual English, then auto-generated English, then the first available track.
- Can I get transcripts for a whole channel?
- Not directly. Collect the channel's video IDs first with the YouTube Channel Scraper (long-form) or YouTube Shorts Scraper (Shorts), then feed them here in batches of 50.
- How does billing know a video failed?
- Billing fires on an explicit per-transcript charge event, not on dataset writes. The Actor only fires it when a transcript is delivered, so success:false records sit in your dataset for free.
- What happens if YouTube rate-limits the request?
- The request retries with exponential backoff. If it still cannot fetch within the 30-second deadline, the video comes back as success:false with code DEADLINE_EXCEEDED. You are not charged.
Guides for this API
- How to get YouTube transcripts in Node.js: apify-client with real error handling updated 2026-07-15
- Get YouTube transcripts in Make: one HTTP module, with error filtering updated 2026-07-20
- Get YouTube transcripts in Zapier: two working setups and their limits updated 2026-07-15
- YouTube captions.download returns 403: the permission wall, explained updated 2026-07-17
- youtube-transcript-api RequestBlocked / IpBlocked: why it happens and the real fixes updated 2026-07-15
- Get YouTube transcripts in n8n: a no-code workflow with error branching updated 2026-07-11
- How to get YouTube video transcripts in Python: three ways, with real error handling updated 2026-07-11
- Why the YouTube Data API won't give you transcripts (and what actually works) updated 2026-07-11
Automation templates
- YouTube videos → transcript text n8n workflowA 50-video batch costs about $0.15 (50 × $0.003 plus a $0.00005 start fee) — videos that can't deliver a transcript are $0.
- YouTube channel → transcript corpus n8n workflowA 50-video channel costs at most $0.18 — $0.025 to list it and $0.15 for the transcripts; captionless videos are $0.
- Keyword search → transcript corpus n8n workflow20 videos per keyword cost at most $0.07 — $0.004 for the search results and $0.06 for the transcripts; misses are $0.
- YouTube videos → transcript rows (Make) Make blueprintA 50-video batch costs about $0.15 (50 × $0.003 plus a $0.00005 start fee) — videos that can't deliver a transcript are $0.
- YouTube transcripts batch (GitHub Actions) GitHub Actions workflowA 50-video batch costs about $0.15 (50 × $0.003 plus a $0.00005 start fee) — videos that can't deliver a transcript are $0.
Comparisons
Pairs with
YouTube Channel Scraper
Export a YouTube channel's videos to JSON from a URL, @handle, or channel ID. One record per video with title, views, duration, and thumbnail.
YouTube Comments Scraper
Export a YouTube video's comments and replies to JSON from a URL or video ID. One record per comment with author, likes, replies, and timestamp.
Run it on the Apify account you already have
Paste one input into the actor's console and check the dataset it returns. A one-item first run costs under a cent — no new subscription, pay only for delivered results.
Get one transcript