DEV Community

Gautham Krishna
Gautham Krishna

Posted on Fully Autonomous

youtube-transcript-api RequestBlocked and IpBlocked on cloud servers, and what actually fixes it

If you've used youtube-transcript-api you've probably seen this. It works on your laptop. You deploy it to AWS or a VPS or some serverless thing, and every call dies with RequestBlocked or IpBlocked.

I've hit this a lot while building transcript scrapers. This week I reran it from scratch to get real numbers instead of forum guesses.

Why it works locally and fails on a server

YouTube decides per IP. The library's own README says it plainly: "YouTube has started blocking most IPs that are known to belong to cloud providers (like AWS, Google Cloud Platform, Azure, etc.)". A home connection looks like a person watching videos. A datacenter range doesn't.

The two errors mean slightly different things. I read the source of version 1.2.4 to check:

Error What YouTube did
RequestBlocked The player API said LOGIN_REQUIRED with its bot-detection reason, the "Sign in to confirm you're not a bot" wall
IpBlocked YouTube answered HTTP 429, or sent a reCAPTCHA page instead of the video page

IpBlocked is a subclass of RequestBlocked, so except RequestBlocked catches both.

Reproducing it

Here's the smallest script that shows the problem:

from youtube_transcript_api import YouTubeTranscriptApi

ytt_api = YouTubeTranscriptApi()
transcript = ytt_api.fetch("jNQXAC9IVRw")
for snippet in transcript[:3]:
    print(snippet.start, snippet.text)
Enter fullscreen mode Exit fullscreen mode

From my home connection:

1.2 All right, so here we are, in front of the
elephants
5.318 the cool thing about these guys is that they
have really...
7.974 really really long trunks
Enter fullscreen mode Exit fullscreen mode

I didn't spin up an EC2 box for this. I sent the same script through datacenter proxy IPs instead. They aren't AWS, but they're datacenter ranges, same as AWS. I also tried residential proxy IPs, and my home connection again. 10 tries each, on 5 different videos, with a new IP per try on the proxies:

Where the request came from Worked
My home connection 10 of 10
10 datacenter IPs 6 of 10, the other 4 raised RequestBlocked
10 residential IPs 9 of 10, 1 raised IpBlocked

Honestly I expected the datacenter IPs to do worse. But failing 4 times out of 10 is useless for a job nobody is watching. And even residential IPs aren't perfect, which matters for the fix below.

Fix 1: run it from your own machine

If you have a few hundred videos and no deadline, just run it at home. Go slowly. The same README warns that a home IP gets blocked too if you send too many requests.

Fix 2: a rotating residential proxy

That's the README's own answer. The library ships WebshareProxyConfig for Webshare, and GenericProxyConfig for any other provider. Heads up, the Webshare links in that README are referral links, which the author says openly.

Here's the snag I hit. GenericProxyConfig doesn't retry. Its retries_when_blocked is 0, and it keeps the connection alive, so with a rotating proxy you can keep landing on the same blocked IP. Only WebshareProxyConfig retries, 10 times by default. With any other provider, retry yourself and build a new client each time:

import os
from youtube_transcript_api import YouTubeTranscriptApi, RequestBlocked
from youtube_transcript_api.proxies import GenericProxyConfig

PROXY_URL = os.environ["PROXY_URL"]  # rotating residential proxy: http://user:pass@host:port


def fetch(video_id, tries=3):
    for attempt in range(tries):
        # a new client opens a new connection, so a rotating proxy gives it a new IP
        ytt_api = YouTubeTranscriptApi(
            proxy_config=GenericProxyConfig(http_url=PROXY_URL, https_url=PROXY_URL)
        )
        try:
            return ytt_api.fetch(video_id)
        except RequestBlocked:  # IpBlocked is a subclass, so this catches both
            if attempt == tries - 1:
                raise


print(fetch("jNQXAC9IVRw")[0].text)
Enter fullscreen mode Exit fullscreen mode
All right, so here we are, in front of the
elephants
Enter fullscreen mode Exit fullscreen mode

Residential proxies bill by traffic, so check what each video costs you. The library loads the full watch page before it asks for captions. For the three videos I checked, that page was 310 to 370 KB compressed.

Fix 3: yt-dlp

yt-dlp can grab just the subtitles, without the video:

yt-dlp --skip-download --write-subs --write-auto-subs --sub-langs en --sub-format vtt -o "%(id)s.%(ext)s" "https://www.youtube.com/watch?v=jNQXAC9IVRw"
Enter fullscreen mode Exit fullscreen mode
WEBVTT
Kind: captions
Language: en

00:00:01.200 --> 00:00:03.360
All right, so here we are, in front of the
elephants
Enter fullscreen mode Exit fullscreen mode

From home it took 3 seconds with version 2026.08.19. Through 5 datacenter IPs, 3 failed with this:

ERROR: [youtube] jNQXAC9IVRw: Sign in to confirm you’re not a bot. Use --cookies-from-browser or --cookies for the authentication. See  https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp  for how to manually pass cookies. Also see  https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies  for tips on effectively exporting YouTube cookies
Enter fullscreen mode Exit fullscreen mode

Same wall, so switching to yt-dlp doesn't get you around the IP problem. It needs a residential proxy on a server too.

The error tells you to pass cookies. I wouldn't do that with a real account. yt-dlp's own wiki says "By using your account with yt-dlp, you run the risk of it being banned (temporarily or permanently)."


This article was created with the help of AI. An AI agent (Claude) ran every test above on my machine on 25 Oct 2026 and drafted the text from those runs, and every output block is copied from them.

Top comments (0)