DEV Community

LMSlay
LMSlay

Posted on Edited on

youtube-transcript-api RequestBlocked on your server? What actually works in 2026

Disclosure: I build one of the hosted options mentioned below (TubeText Labs on Apify).

youtube-transcript-api works on your laptop and then fails on the server with RequestBlocked, IpBlocked or a misleading TranscriptsDisabled. Here's why, and the four fixes in order of effort.

Choose your YouTube transcript workflow

  • Cloud server blocked before you get a transcript? Start with the four fixes below. If you prefer a hosted fetching step, see the captions-only API example.
  • Building an incremental YouTube channel archive? Use the bounded channel configuration, then retain the complete original dataset export. Skipping previously delivered videos is not an archive or a guarantee that every upload was collected.
  • Your database or embedding job failed after delivery? Use the offline export-replay example rather than blindly fetching the same batch again. It preserves caption timestamps; its tests use synthetic data.
  • Connecting transcripts to n8n? Read the existing template and error-routing guide. Preserve the original dataset before formatting. The shipped YouTube template enables paid AI fallback; set aiFallback to false for captions-only use. Local routing checks are not live-service or production validation.

Why it breaks on servers

YouTube answers requests from datacenter IP ranges (AWS, GCP, Azure, DigitalOcean…) with "Sign in to confirm you're not a bot". The library turns that into RequestBlocked; HTTP 429 becomes IpBlocked. Even home IPs get rate-limited after a few dozen fast requests.

Fix 1 – upgrade and slow down

Use youtube-transcript-api 1.2.4+ and add backoff between requests. This is enough for a handful of videos from a home connection.

Fix 2 – run the fetch from a non-cloud IP

Move only the transcript step to a machine with a residential IP (your own box) and push results to your server. Free, but you maintain it.

Fix 3 – rotating residential proxies

The library supports proxy configs (e.g. WebshareProxyConfig). Rotate on every retry: retrying through the same blocked IP just fails slower.

Fix 4 – call a hosted transcript API

If you would rather not maintain the fetching infrastructure, use a hosted API. I maintain TubeText's YouTube Transcript Actor on Apify. It accepts video, Short, playlist and channel links.

For a captions-only request, make that choice explicit:

curl -X POST \
  "https://api.apify.com/v2/acts/tubetext~youtube-transcript-fast/run-sync-get-dataset-items?timeout=300" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": ["https://www.youtube.com/watch?v=aircAruvnKk"],
    "aiFallback": false,
    "includeTimestampedText": true,
    "includeSegments": true,
    "chunkWords": 300
  }'
Enter fullscreen mode Exit fullscreen mode

This is a configuration example, not a new benchmark. Keep your Apify token on the server, not in browser code.

Choose the missing-caption policy before running a batch

The current input schema enables AI fallback by default. The example above deliberately disables it. With AI off, a caption-less video can return no_transcript rather than trigger paid audio transcription.

If your application needs an attempt at transcribing missing captions, explicitly set aiFallback: true and choose maxAiMinutesPerVideo. The current default length limit is 15 minutes; longer videos are skipped by AI, not partially transcribed up to that limit. AI transcription is billed per started minute when a transcript is delivered. It is not the same billing unit as a caption transcript.

As checked on October 22, 2026, the Pricing tab lists $0.004 per Transcript event and $0.006 per AI transcription minute on the Free plan. Rates differ by plan. It also lists a $0.00005 Actor Start event. The README's mixed-batch example calculates caption transcripts and AI minutes separately; don't interpret the headline transcript price as an all-in price for every video. Check the current event table before estimating a batch, and set Maximum cost per run in the run options.

Keep source timestamps through the RAG pipeline

With chunkWords: 300, the Actor adds approximately 300-word chunks with start and end timestamps, preserving caption boundaries. This is word-based chunking, not a guarantee of a particular tokenizer's token count. includeSegments: true also returns caption segments containing start, duration and text.

In your own ingestion layer, keep the video ID, source URL, returned language and timestamps beside each embedded chunk. Use those fields to show users where an answer came from. Validate chunk length against your embedding model's limits before sending it onward. Chunking does not create embeddings or prove retrieval quality.

Bound channel and playlist ingestion

For a scheduled channel job, these documented input options are useful:

{
  "urls": ["https://www.youtube.com/@3blue1brown"],
  "maxVideosPerSource": 20,
  "channelSort": "newest",
  "skipAlreadyScraped": true,
  "aiFallback": false,
  "includeTimestampedText": true,
  "chunkWords": 300
}
Enter fullscreen mode Exit fullscreen mode

maxVideosPerSource bounds how many videos are selected from each channel or playlist. skipAlreadyScraped remembers delivered videos in the account's tubetext-seen-videos key-value store and skips them on later runs. It is not a substitute for idempotent writes in your own database. Store the delivered dataset before embedding so a failed embedding job can resume without fetching the video again.

For a replay-safe companion, see the offline caption-ingestion example. Keep the complete original dataset export and replay that export if downstream ingestion fails: the Actor remembering a video as delivered does not mean your database committed it. The Python example reads a local JSON export into SQLite, preserves segment timestamps, and makes no network requests, AI calls or Actor runs. Its tests use synthetic data, not live YouTube videos.

Treat output rows as results to validate

The README documents successful rows with status: "ok", plus outcomes such as no_transcript and too_long_for_ai. Inspect each row and its transcript before embedding it. Keep unsuccessful rows for diagnosis instead of indexing error text or silently treating missing content as success.

Use bounded retries in your application, and do not blindly resubmit a whole batch after a timeout. Check the run and its delivered dataset first. A hosted API moves the fetching work out of your server; it does not guarantee that every video is accessible. Private, members-only and age-restricted videos remain limitations, and auto-generated captions can contain recognition errors. Use only content you are permitted to process.

Which one to pick

  • A few videos, occasionally → Fix 1 or 2.
  • You already run proxies → Fix 3.
  • Production pipeline, n8n/Make, or you need captions and AI fallback → a hosted API.

Questions about a specific error? Drop it in the comments.

Top comments (0)