# YouTube Transcript API IP Blocked: 3 Fixes

> youtube-transcript-api RequestBlocked and IpBlocked: why cloud servers get blocked (9 of 9 in our test), and three ways out with working Python code for each.

[Home](https://quanticdata.io/)/[Blog](https://quanticdata.io/blog/)/YouTube Transcript API IP Blocked: 3 Fixes

# youtube-transcript-api RequestBlocked and IpBlocked: why it happens and three ways out

TroubleshootingOct 20, 2026·8 min read·By [Aldo Morese](https://quanticdata.io/about/), founder of QuanticData

youtube-transcript-api 1.2.4 on 20 October 2026: the same code read 0 of 9 transcripts from a cloud server in Frankfurt, where every attempt raised RequestBlocked, and 9 of 9 through a rotating residential exit with a median of 2.09 seconds; the card lists the three ways out: a residential connection, a rotating proxy in GenericProxyConfig, an API that retries for you.

On this page [What RequestBlocked and IpBlocked mean](/blog/youtube-transcript-api-ip-blocked/#what-requestblocked-and-ipblocked-mean) [Why it works on your laptop and fails on the server](/blog/youtube-transcript-api-ip-blocked/#why-it-works-on-your-laptop-and-fails-on-the-server) [Way 1: run it from a residential connection, and slow down](/blog/youtube-transcript-api-ip-blocked/#way-1-run-it-from-a-residential-connection-and-slow-down) [Way 2: a rotating residential proxy configured in the package](/blog/youtube-transcript-api-ip-blocked/#way-2-a-rotating-residential-proxy-configured-in-the-package) [Way 3: an API that retries for you](/blog/youtube-transcript-api-ip-blocked/#way-3-an-api-that-retries-for-you) [Which way to choose](/blog/youtube-transcript-api-ip-blocked/#which-way-to-choose) [What not to do](/blog/youtube-transcript-api-ip-blocked/#what-not-to-do)

RequestBlocked and IpBlocked mean YouTube refused the IP address your code runs from, not that the video has no captions. Cloud addresses are refused most of all: on 20 October 2026, youtube-transcript-api 1.2.4 was blocked 9 of 9 times from a cloud server and read 9 of 9 transcripts through a residential exit. Three ways out follow.

The fix depends on where your code runs and how many videos it reads. Below: what each error means in the package's own source, the measurement, and three ways out with Python you can paste, from the cheapest to the one with nothing left to maintain.

## What RequestBlocked and IpBlocked mean

Both come from the open-source package, not from an official YouTube API. In version 1.2.4 they are raised in these cases:

| Exception | When version 1.2.4 raises it | What it tells you |
| --- | --- | --- |
| `RequestBlocked` | The player answers LOGIN_REQUIRED with "Sign in to confirm you're not a bot" | YouTube will not serve this address without a signed-in viewer |
| `IpBlocked` | HTTP 429 Too Many Requests, or a reCAPTCHA in the watch page | The address asked too often or is flagged; it is a subclass of RequestBlocked |
| `TranscriptsDisabled` | "Subtitles are disabled for this video" | The video has no captions; not a block |
| `NoTranscriptFound` | None of the languages you asked for exists | Pass the spoken language, for example `languages=["it", "en"]` |
| `AgeRestricted` | The video needs a signed-in viewer | Cookie sign-in is currently unsupported in the package |
| `VideoUnavailable` | The video was removed or made private | Not a block |

Because IpBlocked is a subclass, `except RequestBlocked` catches both. Catch IpBlocked first when you want to treat the two differently: a 429 can pass with time, a "not a bot" answer on a cloud address does not.

**Try it on your own targets.** Every QuanticData account gets $2 of free API usage per month.

[Start free — $2/month included](https://quanticdata.io/signup/?utm_source=blog&amp;utm_medium=website&amp;utm_campaign=blog-inline&amp;utm_content=youtube-transcript-api-ip-blocked)[Explore Video API: YouTube Transcript and Frames](https://quanticdata.io/video-api/)

## Why it works on your laptop and fails on the server

The package README says it in one line: "YouTube has started blocking most IPs that are known to belong to cloud providers." Your laptop sits on a home or office line, a residential address. The same code on AWS, Google Cloud, Azure or any VPS runs from a datacenter range. We measured it from our own server in a Frankfurt datacenter (DigitalOcean) on 20 October 2026, with three public videos, three rounds two seconds apart, 17:48 to 17:49 UTC:

| Route | Attempts | Result | Time per attempt |
| --- | --- | --- | --- |
| Direct, from the datacenter address | 9 | RequestBlocked 9 of 9 | 0.78 to 1.11 s |
| Same server and code, rotating residential exit in the United States | 9 | 9 of 9 read: 192 Italian snippets, 286 and 338 English ones | 1.57 to 2.61 s, median 2.09 s |

The very first request was refused, so this was not a rate limit: the address itself was the problem. Slowing down would not have helped, changing the address did.

## Way 1: run it from a residential connection, and slow down

For a few hundred videos, the simplest way out is to run the job where the address is already residential: your own machine, an office line, a small box at home. Then keep the pace human. When the package raises IpBlocked after a burst, wait and try again with a growing pause; when it raises RequestBlocked, waiting rarely helps.

```
import random, time
from youtube_transcript_api import YouTubeTranscriptApi, IpBlocked, RequestBlocked

ytt = YouTubeTranscriptApi()

def fetch_politely(video_id, languages=("en",), tries=4):
    for attempt in range(tries):
        try:
            return ytt.fetch(video_id, languages=list(languages))
        except IpBlocked:
            # HTTP 429 or a captcha: this address asked too often, so wait and retry
            time.sleep(15 * 2 ** attempt + random.uniform(0, 5))
        except RequestBlocked:
            # "confirm you're not a bot": the address is refused, change it (way 2 or 3)
            raise
    raise RuntimeError(f"{video_id}: still blocked after {tries} tries")

for vid in ["aircAruvnKk", "CDjjaTALI68"]:
    t = fetch_politely(vid)
    print(vid, t.language_code, len(t), "snippets")
    time.sleep(3)   # one video every few seconds, never a burst
```

Limits: it does not move to a server, a laptop that sleeps stops the job, and a home address that asks too often gets flagged as well.

## Way 2: a rotating residential proxy configured in the package

On a server, give the package an exit on a residential network. It accepts any HTTP or SOCKS proxy through `GenericProxyConfig`. One detail the README leaves out: in version 1.2.4 the generic config keeps TCP connections alive and never retries a blocked request, because both settings default to off. With a rotating gateway, a kept-alive connection holds on to the same exit, so a refused address stays refused. Two properties fix that:

```
import os
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api.proxies import GenericProxyConfig

class RotatingResidential(GenericProxyConfig):
    @property
    def prevent_keeping_connections_alive(self) -> bool:
        return True    # a new connection per request, so the gateway picks a new exit

    @property
    def retries_when_blocked(self) -> int:
        return 5       # a blocked fetch is retried, each time through a fresh exit

# host:port, username and password come from your QuanticData dashboard;
# the country goes in the username, here the United States
user, pwd, host = os.environ["QD_PROXY_USER"], os.environ["QD_PROXY_PASS"], os.environ["QD_PROXY_HOST"]
proxy = f"http://{user}-country-us:{pwd}@{host}"

ytt = YouTubeTranscriptApi(proxy_config=RotatingResidential(http_url=proxy, https_url=proxy))
t = ytt.fetch("aircAruvnKk", languages=["en"])
print(t.language_code, len(t), "snippets")
```

The second row of the table above used the plain `GenericProxyConfig` and read 9 of 9; the two properties keep the same setup working when one exit is refused. In a second run of nine with exactly this code, 4 of the 13 watch-page requests were refused and retried through a new exit, and 9 of 9 transcripts came back. Closing the connection on every request means a new tunnel each time, so count on several seconds per transcript. The cost is bandwidth: the package downloads the full watch page before it asks for the captions, and over those nine reads the proxy meter moved 14.4 MB, about 1.6 MB per transcript with the retries included. On [QuanticData residential proxies](https://quanticdata.io/residential-proxies/), the [Residential Basic](https://quanticdata.io/cheap-residential-proxies/) line costs $1.00 per GB, down to $0.80 per GB at 1,000 GB:

| Price per GB | Per transcript | Per 1,000 transcripts |
| --- | --- | --- |
| $1.00 | about $0.0016 | about $1.60 |
| $0.80, at 1,000 GB | about $0.0013 | about $1.28 |

The free trial is 100 MB for 5 days with no card, enough for about 60 transcripts before you pay. Use rotating exits, not static ones: the README warns that YouTube bans static proxies after extended use. Limits: the parser reads an undocumented part of YouTube, so a site change can break it until the maintainer ships a fix, and you still get the transcript only.

## Way 3: an API that retries for you

The [QuanticData Video API](https://quanticdata.io/video-api/) runs the whole path on our side. Each read is tried directly first; when YouTube refuses the address or answers empty captions, it is repeated through a residential exit inside the same call. On 20 October 2026 three videos of 8:23, 18:40 and 12:22 came back in 1.7 to 7.3 seconds, all three through that retry, and a read that still fails is not billed.

```
import os, requests

r = requests.post("https://api.quanticdata.io/v1/scraper/video",
    headers={"Authorization": f"Bearer {os.environ['QD_API_KEY']}"},
    json={"url": "https://www.youtube.com/watch?v=aircAruvnKk", "max_frames": 0},
    timeout=120)
data = r.json()
if data["type"] != "response":
    raise RuntimeError(data["message"])   # stable payload.code, and the read is not billed

video = data["payload"]
print(video["transcript"]["language"], len(video["chapters"]), "chapters")
print(video["meta"]["via_proxy"])         # True when the residential retry answered
print(video["content"][:600])             # Markdown timeline with [m:ss] stamps
```

There is no proxy to configure and no parser to update. You also get what the package does not return: the chapters the author wrote, the description, and up to 30 frames where the speaker points at the screen (here turned off with `max_frames: 0`). The same call is the read_video tool of the [QuanticData MCP server](https://quanticdata.io/mcp-server/), for Claude, Cursor and other MCP clients; the full walk-through is [Train an agent with the Video API](https://quanticdata.io/tutorials/train-an-agent-with-the-video-api/), and every field is in the [API reference](https://quanticdata.io/docs/#tag/Video/operation/readVideo).

## Which way to choose

| Your situation | Way | Why |
| --- | --- | --- |
| A few videos, run from your own computer | 1 | Free, nothing to configure |
| A server job that needs the transcript only, and you keep the code | 2 | 9 of 9 read through a rotating residential exit; about $1.60 per 1,000 at $1.00 per GB |
| An agent or pipeline that needs chapters, frames or quotes with timestamps | 3 | One timeline per call, retry built in, billed only on success |
| Thousands of videos with no proxy or parser to maintain | 3 | The retry and the fixes happen on our side |

For the wider picture, with hosted transcript services and the official YouTube Data API side by side, see [YouTube transcript APIs compared](https://quanticdata.io/blog/youtube-transcript-apis-compared/).

## What not to do

- **Do not sign in with cookies to get past the block.** The package's own error message warns that YouTube will eventually ban the account used, and cookie sign-in is currently unsupported in version 1.2.4.

- **Do not set HTTP_PROXY and hope.** In the project's issue tracker the maintainer points users to the package's proxy config instead: pass the proxy with `proxy_config`, as in way 2.

- **Do not hammer a refused address.** More requests from a flagged IP keep it flagged; back off on IpBlocked, change the address on RequestBlocked.

- **Do not read what you may not read.** Stick to public videos and follow YouTube's terms and the law where you run: a proxy changes where a request comes from, not what you are allowed to do.

### Sources & further reading

- [Requests documentation: proxies, the setting GenericProxyConfig passes through](https://requests.readthedocs.io/en/latest/user/advanced/#proxies)

- [RFC 6585: HTTP status 429 Too Many Requests](https://www.rfc-editor.org/rfc/rfc6585)

- [YouTube Help: automatic captions and their limits](https://support.google.com/youtube/answer/6373554)

- [YouTube Terms of Service](https://www.youtube.com/t/terms)

## FAQ

Quick answers on youtube transcript api ip blocked.

[Something else? Ask us](mailto:hello@quanticdata.io)

### What does RequestBlocked mean in youtube-transcript-api?

It means YouTube refused the IP address the request came from, usually by answering "Sign in to confirm you're not a bot". It is about the address, not the video: in our test of 20 October 2026 the same three videos were blocked 9 of 9 times from a cloud server and read 9 of 9 times through a residential exit.

### What is the difference between RequestBlocked and IpBlocked?

In version 1.2.4, IpBlocked is raised on HTTP 429 Too Many Requests or when the watch page shows a reCAPTCHA, and it is a subclass of RequestBlocked. RequestBlocked itself is raised when the player asks the viewer to sign in to prove it is not a bot. A 429 can pass if you slow down; the sign-in answer on a cloud address needs a different address.

### Why does youtube-transcript-api work locally but not on AWS or another cloud server?

YouTube blocks most addresses that belong to cloud providers, while a laptop sits on a residential line. The fix is a residential exit: a rotating residential proxy set in GenericProxyConfig, with keep-alive off and retries on, or an API such as the QuanticData Video API that retries through a residential exit inside the same call.

### Does a proxy fix RequestBlocked?

A rotating residential proxy does in most cases: in our run it read 9 of 9 transcripts from the same server that was blocked 9 of 9 times. Datacenter and static proxies do not fix it for long. With a rotating gateway, turn off keep-alive and allow retries, or a refused exit stays in use.

### What is the rate limit of youtube-transcript-api?

The package has no limit of its own and YouTube publishes none for this path. YouTube decides per address: a burst ends in IpBlocked, which is HTTP 429. From a cloud address even the first request can be refused. A few seconds between videos and a growing pause after a 429 keep a residential address working.

### Is there a YouTube transcript API that does not get IP blocked?

The QuanticData Video API handles the block for you: each read is tried directly, then repeated through a residential exit inside the same call. Failed reads are never billed, and it returns the transcript in the spoken language with [m:ss] stamps, the chapters and frames. Every account gets $2 of free API usage each month.

## Stop handling RequestBlocked yourself

One POST, the residential retry built in, the transcript with chapters and frames back in seconds. $2 of free API usage every month, no card, failed reads never billed.

[Start free — $2/month included](https://quanticdata.io/signup/?utm_source=blog&amp;utm_medium=website&amp;utm_campaign=blog-end&amp;utm_content=youtube-transcript-api-ip-blocked)[Explore Video API: YouTube Transcript and Frames](https://quanticdata.io/video-api/)

## Related reading

[Troubleshooting IPv6 Proxy Not Working? The Five Checks Five checks that settle almost every "IPv6 proxy not working" ticket: whether the target publishes an AAAA record at all (57 of 102 major sites do not), DNS resolved at the exit with socks5h, credentials the client can actually pass, the error you really got, and pacing by /64 when the site answers but blocks. Read more](https://quanticdata.io/blog/ipv6-proxy-not-working/) [Troubleshooting Read the Block: 4 Shapes, 4 Settings That Work A refused reply has a shape, and the shape tells you the setting. Across 53 sites measured between 26 and 28 September 2026 we met four: a short page with no canonical (Amazon, 2,007 bytes, 0 words), a redirect to the login form (Glassdoor, rendered: canonical /member/profile/login, 54 words), a rate-limit reply (Expedia, rendered: 381,468 bytes, 45 words, no h1) and an empty rendered page (Zillow, 759 words plain, 0 rendered). Each one resolves into a fetch mode, an exit and, where the page never exists, a collector with rows and seconds. Read more](https://quanticdata.io/blog/read-the-block-and-what-to-do/) [Troubleshooting SSL CERTIFICATE_VERIFY_FAILED Behind a Proxy A plain CONNECT proxy never touches certificates, so CERTIFICATE_VERIFY_FAILED means something re-signed the site or your trust bundle is wrong. We reproduced the error 42 times across seven clients to show which tail means what, and which fixes really work. Read more](https://quanticdata.io/blog/ssl-certificate-verify-failed-proxy/)

---

Source: https://quanticdata.io/blog/youtube-transcript-api-ip-blocked/ · Site index for AI: https://quanticdata.io/llms.txt
