← All guides

RequestBlocked in Google Colab: why notebooks get blocked most, and what to do instead

Written by the VidWords Team · · Updated · Report a correction

Colab is where most people meet this error, and it is the worst place to debug it: the environment is disposable, the fix everyone reaches for is a coin flip, and the standard remedy involves putting a password into a document you are about to share.

The 30-second version

Why notebooks get blocked more than servers do

A production server on Render or Railway is blocked because it is a datacenter IP with an automated traffic profile. Colab is that plus a compounding factor: it is the default place people run example code.

Search results, YouTube tutorials and LLM answers all converge on the same five lines of youtube-transcript-api, and a large share of the people running them run them in a free Colab notebook. Colab allocates you a runtime from a shared pool, so the address you receive has a history you did not create. You can be blocked on your first cell execution, before you have made a single request, because the previous occupant of that address spent the afternoon pulling a thousand transcripts.

This is why the experience is so confusing: the exact code from a working tutorial fails immediately, with no signal that anything is wrong with the code. Nothing is wrong with the code.

Why "restart the runtime" is the wrong lesson

Restarting or reconnecting can land you on a different runtime with a different address, and sometimes that address is clean. So the notebook that just failed now succeeds, and the natural conclusion is that restarting fixes it.

What you have actually learned is that the outcome is random. That is a much worse position than a deterministic failure, because:

If you are going to depend on the retry-with-a-new-runtime behaviour at all, at least make it explicit and bounded, and make sure the retry actually opens a new connection rather than reusing a pooled one — details in the RequestBlocked / IpBlocked guide.

The Colab-specific hazard: credentials in a shared notebook

The standard remedy is a rotating residential proxy. In a script on your own machine you put the credentials in an environment variable and forget about it. In Colab that instinct is a genuine security problem.

A notebook cell's source is saved into the .ipynb file. If you write your Webshare username and password into a cell, they are now in the document — and notebooks are shared constantly, committed to GitHub, exported to PDF and handed round as course materials. A proxy subscription leaked this way is billed by the gigabyte to whoever finds it.

Colab has a built-in answer. Use the Secrets panel (the key icon in the left sidebar), store the values there, and read them at runtime:

from google.colab import userdata

PROXY_USER = userdata.get("WEBSHARE_USER")
PROXY_PASS = userdata.get("WEBSHARE_PASS")

Secrets live in your Google account, not in the notebook file, and a copy of the notebook shared with someone else does not carry them. The cell above is safe to publish; the same two values typed as literals are not.

The same applies to any API token you use from a notebook. Two lines, and it removes an entire class of accident.

The other Colab constraint people forget: the machine goes away

Colab's own FAQ is direct about this: "Virtual machines are deleted when idle for a while, and have a maximum lifetime enforced by the Colab service", "runtimes will time out if you are idle", and in the free tier "notebooks can run for at most 12 hours". It also warns that "Colab resources are not guaranteed and not unlimited".

For transcript work that has a specific and expensive consequence: anything you wrote to the local filesystem is gone, so tomorrow you fetch it all again. Every refetch is another set of requests that can be blocked, for data you already successfully retrieved once. People end up blaming the library for a problem they created by not persisting anything.

Mount Drive and cache there. This is the highest-value change in the whole notebook:

import json, os
from google.colab import drive

drive.mount("/content/drive")
CACHE = "/content/drive/MyDrive/transcript_cache"
os.makedirs(CACHE, exist_ok=True)

def cached(video_id, lang, fetch):
    path = os.path.join(CACHE, f"{video_id}.{lang}.json")
    if os.path.exists(path):
        with open(path) as f:
            return json.load(f)
    data = fetch(video_id, lang)          # the part that can get blocked
    with open(path, "w") as f:
        json.dump(data, f)
    return data

Cache failures too, with the error code. A video with captions disabled will still have them disabled next week; asking again every session is pure exposure for a guaranteed answer. Storing outcomes rather than only successes is what turns a flaky notebook into a resumable one — rerun the cell and it picks up exactly where it stopped instead of starting over.

If you are doing research, work in two passes

Most Colab transcript work is analysis: a corpus of videos, then some counting, coding or modelling over the text. Those two halves have completely different reliability profiles, and putting them in one loop is what makes a notebook fragile.

  1. Acquisition pass. One cell whose only job is to get text and write it to Drive, designed to be run repeatedly and to skip everything it already has. Let it fail on some videos; run it again.
  2. Analysis pass. Reads only from Drive, never touches the network, and therefore always runs to completion — reproducibly, which also matters if the work is going into a paper.

This also protects your results: a corpus assembled over several sessions is a fixed artifact you can cite and re-analyse, rather than something that silently differs each time you run the notebook. More on building a defensible corpus in transcripts for research.

The route that skips the address problem

Because Colab is disposable and shared, the case for not owning the retrieval stack is stronger here than anywhere else. There is no server to configure, no proxy subscription to protect, and nothing to keep current between sessions — one HTTPS call, with the token in Colab Secrets:

import requests
from google.colab import userdata

TOKEN = userdata.get("VIDWORDS_TOKEN")

def fetch(video_ids, lang="en"):
    resp = requests.post(
        "https://vidwords.com/api/transcripts",
        headers={"Authorization": f"Basic {TOKEN}"},
        json={"ids": video_ids, "lang": lang},
        timeout=60,
    )
    resp.raise_for_status()
    return resp.json()["results"]

for video in fetch(["dQw4w9WgXcQ", "9bZkp7q19f0"]):
    if "error" in video:
        print(video["id"], "->", video["error"])   # no_transcript, video_unavailable, invalid_id
        continue
    print(video["title"])
    print(video["text"][:200], "...")

Two details that matter in a notebook. Failures come back per video as an error field rather than raising, so one bad id does not abort a cell you have been running for ten minutes. And you can send up to 50 ids in one request, so a 200-video corpus is four calls rather than 200 opportunities to be blocked.

One delivered transcript costs one credit; a video with no transcript costs nothing. A free account includes 25 transcripts a month with no card, which is enough to test the notebook end to end before deciding anything. Everything else is in the API reference. Wrap it in the Drive cache above and the notebook becomes resumable as well as reliable.

Which route to pick

FAQ

Does Colab Pro fix the block?

It changes your compute allocation, not YouTube's opinion of the address you are given. There is no tier that buys a residential IP.

Can I run a proxy inside the notebook?

You can configure the library to use one — that is the supported remedy. Keep the credentials in Colab Secrets rather than in a cell, and be aware the README states plainly that a proxy "doesn't guarantee that you won't be blocked".

Why does the first cell work and the tenth fail?

You crossed a threshold on an address whose recent history you did not control. It is not your tenth request that mattered — it is the total from that address.

The video genuinely has no captions. Now what?

No proxy helps; there is nothing to download. Getting text out of that video means transcribing its audio, which is a different and more expensive operation — see why a transcript can be missing.

Read the API docs →