Back to blog

Python · GCP · Troubleshooting

youtube-transcript-api Blocked on GCP? Why It Happens and What to Do

The same script that works on your laptop raises RequestBlocked or IpBlocked on Cloud Run, Cloud Functions, and GCE. A reserved static IP stays inside Google's published ranges.

· 3 min read · YTAPI

The script runs on your laptop. You deploy it to Cloud Run, Cloud Functions, or a GCE VM, and youtube-transcript-api starts failing:

youtube_transcript_api._errors.RequestBlocked:
Could not retrieve a transcript for the video ...
YouTube is blocking requests from your IP. This usually is due to one of the
following reasons:
- You have done too many requests and your IP has been blocked by YouTube
- You are doing requests from an IP belonging to a cloud provider (like AWS,
  Google Cloud Platform, Azure, etc.). Unfortunately, most IPs from cloud
  providers are blocked by YouTube.

Sometimes the class is IpBlocked instead. In current library code that means YouTube answered HTTP 429, or returned a reCAPTCHA page, rather than the player message "Sign in to confirm you're not a bot". IpBlocked is a subclass of RequestBlocked, so a handler written for the parent catches both. The AWS write-up has the longer version of why hosting providers get this treatment. The rest of this page is the part that is specific to Google Cloud.

A static IP on GCP is still a Google IP

Google publishes the address ranges it uses for cloud customers. Cloud Run, Cloud Functions, App Engine, GKE, and a GCE VM with a normal external address all leave from those ranges.

The recipe people follow when a partner asks for a firewall allowlist is Serverless VPC Access plus Cloud NAT, or a reserved external IP on a VM. That gives you a stable address. The address is still announced as Google Cloud. YouTube is matching the network, in the same way it matches AWS. Reserving the address, or pinning it with Cloud NAT, keeps the requests inside the network that is already being refused.

A brand-new project does not start clean. Those ranges are shared with everyone else running scrapers, scanners, and batch jobs on GCP. The reputation is on the range.

What actually changes the outcome

Run it off GCP

A home or office machine at low volume usually gets through. Fine for a one-off backfill. Awkward for anything that has to run every hour, because the machine has to stay on and you are back to operating a server.

Send the YouTube traffic through a residential proxy

This is the workaround the library documents. Datacenter proxies, including cheap "static residential" products that are really hosting addresses, tend to get the same refusal. The proxy has to exit from consumer connections, and you have to rotate when one of them gets burned. The AWS page has a GenericProxyConfig example and the cost notes: per-gigabyte billing, retries, and latency that jumps around.

Cookies

The exception text still mentions cookies. In the current release, cookie authentication is disabled. The constructor does not take a cookie file, and the project's README says YouTube's recent changes broke the old implementation. Exporting cookies.txt does nothing for this library until that feature is actually in the version you have installed.

Call a hosted transcript API from Cloud Run

Your Cloud Run service then talks to an ordinary HTTPS endpoint. The YouTube request happens somewhere else. Whether that is worth paying for depends on how often you would otherwise be babysitting proxies.

import os
import requests

res = requests.post(
    "https://api.ytapi.dev/v1/transcripts",
    headers={"Authorization": f"Bearer {os.environ['YTAPI_KEY']}"},
    json={"video_id": "dQw4w9WgXcQ", "format": "text"},
    timeout=30,
)
res.raise_for_status()
print(res.text)

A 404, including a video with no captions, is not billed. The Python guide has the same call with language fallback and error handling. The same wall on Vercel, Render, and Railway is written up separately, because those platforms sell their own "static outbound IP" products and none of them leave the datacenter either.

FAQ

Does Cloud NAT with a reserved static IP fix it?

No. The reserved address is still in Google Cloud's published ranges. It makes your outbound address predictable, which helps for allowlists on other services, but it doesn't make the traffic look like it comes from a viewer.

Does the region I deploy to matter?

Not in any way you can rely on. Every region's addresses belong to Google Cloud. Moving from one region to another can change how soon you get blocked, but not whether.

Can I call a transcript API from Cloud Run or Cloud Functions?

Yes. It's an ordinary outbound HTTPS request to the provider, so it works from any runtime, including ones with short time limits. Set the client timeout below your function's own limit.