YouTube Transcript Scraper avatar

YouTube Transcript Scraper

Pricing

from $3.00 / 1,000 transcripts

Go to Apify Store
YouTube Transcript Scraper

YouTube Transcript Scraper

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.

Pricing

from $3.00 / 1,000 transcripts

Rating

0.0

(0)

Developer

apihq

apihq

Maintained by Community

Actor stats

0

Bookmarked

30

Total users

10

Monthly active users

9 days ago

Last modified

Share

Extract time-coded transcripts from any public YouTube video as clean JSON. No YouTube Data API key, no quota, no browser. Send one video ID or a batch of up to 50.

The contract is simple: a video with no captions returns success:false and costs nothing, and you only pay for transcripts actually delivered. $3 per 1,000 transcripts.

See one run

Input:

{
"videoIds": ["jNQXAC9IVRw", "00000000000"],
"language": "en",
"metadata": true
}

What comes back:

  • 1 success: true transcript for jNQXAC9IVRw ("Me at the zoo"), English track, with the video's title, author, duration, and thumbnail attached, billed
  • 1 success: false row, code: PLAYABILITY, for the unplayable ID, not billed
  • Run status: SUCCEEDED
  • Charged: 1 transcript

videoIds alone works too. The knobs above are optional: language requests a specific caption track, and metadata attaches the video's context so you get more than caption text. Omit language to use the default track picker. Good IDs return billed transcripts, videos with no fetchable captions return free success:false rows in the same dataset, and the run still succeeds so one bad ID never costs you a batch.

Why this Actor

  • You pay only for transcripts delivered. Videos with no fetchable transcript come back as success:false and never trigger a charge.
  • Every failure is machine-readable. Each carries a stable code (NO_CAPTIONS, PLAYABILITY, EMPTY_TRANSCRIPT, VALIDATION_FAILED, DEADLINE_EXCEEDED, PO_TOKEN_REQUIRED), so your pipeline branches on the error type without parsing English.
  • A 30-second deadline per video. If the upstream stalls you get a clean 504 with code: DEADLINE_EXCEEDED and no charge, not a 60-minute hang that drains your budget.
  • No YouTube Data API key or quota. The official Data API's captions endpoint is OAuth-gated and restricted for third-party download. This takes a plain video ID and returns JSON. (You still run it with your normal Apify account, like any Actor.)

Best for

AI and data workflows that turn videos into text: RAG pipelines and LLM training data, search indexing over spoken words, sentiment/topic/brand-safety analysis, and subtitle and accessibility tooling. The stable error codes and never-fail-a-run behavior matter most when transcripts feed an automated pipeline, where one caption-less video should never take down the batch. It works fine for one-off manual pulls too.

Input example

A single video with metadata included:

{
"videoId": "jNQXAC9IVRw",
"metadata": true
}

A batch of three videos in a specific language:

{
"videoIds": [
"jNQXAC9IVRw",
"dQw4w9WgXcQ",
"kJQP7kiw5Fk"
],
"language": "en",
"metadata": true
}

The Actor caps batch input at 50 video IDs per run. For larger workloads, launch parallel runs.

Output example

A successful extraction (the actual response for "Me at the zoo", the first ever YouTube upload):

{
"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",
"author_url": "https://www.youtube.com/channel/UC4QobU6STFB0P71PMvOGN5A",
"thumbnail_url": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg",
"channel_id": "UC4QobU6STFB0P71PMvOGN5A",
"duration_seconds": 19
}
}

A video with no fetchable transcript lands in the same dataset and is not charged:

{
"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.

What you get

Every processed video produces one record. Successful extractions carry success: true with this shape:

FieldTypeWhat it is
successbooleantrue for a fetched transcript, false for a video with no fetchable transcript.
video_idstringThe 11-character YouTube video ID.
languagestringLanguage code of the selected caption track.
transcriptarrayTime-coded caption segments. Each has text, start, and duration.
is_auto_generatedbooleanTrue if the selected track is YouTube's ASR.
available_tracksarrayEvery caption track the video exposes, with language code and name.
metadataobjectVideo title, channel name, channel URL, thumbnail URL, channel ID, duration in seconds. Present when metadata: true (default).

Videos with no fetchable transcript come back with success: false, plus video_id, the machine-readable code, a human-readable error, the service request_id, and the HTTP status_code. They are not charged.

Pricing

Pay-per-result. Each successful transcript costs $0.003, which is $3.00 per 1,000 transcripts. The charge fires only when a transcript is delivered.

  • 1,000 delivered transcripts cost $3.
  • A batch of only caption-less or unplayable videos costs $0.

Apify subscriber discounts apply automatically: roughly $2.40 per 1,000 on the Scale plan and $1.80 per 1,000 on Business. Platform compute is included in the per-transcript price. Cap the maximum spend of a single run from Apify's Run Limits panel; the Actor honors the cap and reports how many videos completed.

What this Actor does not do

Honest scope, so you know before you run it:

  • One video at a time, or batches of up to 50 IDs. It does not crawl a whole channel or playlist. To collect the IDs first, use the YouTube Channel Scraper for long-form uploads or the YouTube Shorts Scraper for Shorts, then feed the IDs here.
  • It reads captions that already exist (manual or auto-generated). It does not transcribe audio, so a video with no caption track returns success:false with code: NO_CAPTIONS.
  • Public videos only. Private, members-only, and age-gated videos return success:false.

How to use this Actor

  1. Open the Actor in the Apify Console.
  2. Set videoId (single), videoIds (a list), or both. Values are merged and de-duplicated, and up to 50 unique IDs are processed per run. Optionally pass language (e.g. en, de, en-US) and metadata (defaults to true).
  3. Click Start. Each processed video produces one record: success: true with the transcript, or success: false with the reason. Only successes are charged.

The Actor is also callable from the Apify API and every official integration (Make, Zapier, n8n, Slack, webhooks). The API tab in the Console has ready-to-paste JavaScript, Python, and curl snippets.

Reliability

Hard 30-second deadline per video. If YouTube or the proxy network slows down, you get a 504 with code: DEADLINE_EXCEEDED for that video. You never wait minutes for a single result.

Empty transcripts are treated as failures. If YouTube returns a caption track that parses to zero segments, the record comes back as success: false with code: EMPTY_TRANSCRIPT and is not billed. You never pay for a blank transcript.

Stable error taxonomy. Every failure has a code your code can branch on, stable across releases: NO_CAPTIONS, PLAYABILITY, EMPTY_TRANSCRIPT, VALIDATION_FAILED, DEADLINE_EXCEEDED, PO_TOKEN_REQUIRED, CAPTIONS_TIMEOUT, NO_INPUT. Every error also carries a request_id for support correlation.

FAQ

Do I need a YouTube Data API key?

No. The Actor reads YouTube's public data directly and does not consume Google API quota.

Which videos work?

Public videos with caption tracks. Manual and auto-generated (ASR) captions both work. Private, age-gated, or members-only videos return success:false.

What if a video has no captions?

It comes back as a success: false record with code: NO_CAPTIONS. You are not charged.

Which languages are supported?

Every language the creator uploaded. Pass a language code (such as en, de, or 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. This Actor takes single video IDs or batches of up to 50. Collect a channel's video IDs first with the YouTube Channel Scraper for long-form uploads or the YouTube Shorts Scraper for Shorts, then feed them here.

Can I use this Actor from my own code?

Yes. Use the Apify API or one of the official SDKs (Node.js: apify-client, Python: apify-client). The Console shows ready-to-paste code samples on the API tab.

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. You still get every result in one place and branch on success and code, with a request_id for support correlation.

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.

Found a bug or want a feature?

Open an issue on this Actor's Issues tab and include the request_id from any error record you saw. We respond within one business day.