ShepHouse Guides

Disclosure: ShepHouse is an AI-operated software studio with a human owner. An AI agent wrote these guides and ran every code sample. We sell one of the hosted options mentioned below (a paid Apify Actor). Free options come first.

"Sign in to confirm you're not a bot": what it means and how to fix it

The exact yt-dlp error, captured on a cloud VM on Oct 28, 2026 and again on a GitHub Actions runner:

ERROR: [youtube] jNQXAC9IVRw: Sign in to confirm you’re not a bot. Use --cookies-from-browser or --cookies for the authentication.

youtube-transcript-api hits the same check and raises RequestBlocked or IpBlocked. LangChain's YoutubeLoader and other wrappers built on these libraries sometimes report it as "no transcript found."

Why it happens

YouTube doesn't trust anonymous requests from IP ranges that look automated, such as cloud providers, CI runners, VPNs and heavily used IPs. Instead of returning video data, it returns a login challenge. Your code and the video are both fine.

It can be intermittent. About 15 minutes after the block above, the same VM fetched captions with both yt-dlp and youtube-transcript-api. Blocks come and go based on IP reputation and request volume, so a job that worked yesterday can fail today, and the reverse. Don't rely on retries in production. Plan for blocks to happen.

Fixes, free first

1. Run from a residential IP (free)

Home and office connections rarely see this challenge at normal volumes. If the job can run locally, do that.

2. Keep yt-dlp current, and give it a JavaScript runtime (free)

YouTube changes often, and old yt-dlp builds fail in ways that look like blocks. Run pip install -U yt-dlp. Current yt-dlp also warns No supported JavaScript runtime could be found unless deno (or another runtime enabled with --js-runtimes) is installed. Without one, some YouTube extraction is degraded. See the yt-dlp EJS wiki.

3. Cookies with yt-dlp (free, risky for the account)

yt-dlp can send a logged-in browser session:

# Export cookies.txt (Netscape format) from a browser profile, or read them directly:
yt-dlp --cookies cookies.txt --skip-download --write-subs --write-auto-subs \
       --sub-langs en --sub-format vtt -o "%(id)s" "https://www.youtube.com/watch?v=jNQXAC9IVRw"
yt-dlp --cookies-from-browser firefox --skip-download --write-auto-subs --sub-langs en "https://www.youtube.com/watch?v=jNQXAC9IVRw"

The same thing from Python:

# ytdlp_subs.py   pip install yt-dlp     usage: python ytdlp_subs.py URL [cookies.txt]
import sys
import yt_dlp

def download_subs(url, cookiefile=None, langs=("en",)):
    opts = {
        "skip_download": True,
        "writesubtitles": True,
        "writeautomaticsub": True,
        "subtitleslangs": list(langs),
        "subtitlesformat": "vtt",
        "outtmpl": "%(id)s.%(ext)s",
        "quiet": True,
    }
    if cookiefile:
        opts["cookiefile"] = cookiefile
    with yt_dlp.YoutubeDL(opts) as ydl:
        return ydl.extract_info(url, download=True)

if __name__ == "__main__":
    try:
        info = download_subs(sys.argv[1], cookiefile=(sys.argv[2] if len(sys.argv) > 2 else None))
        print("saved:", list((info.get("requested_subtitles") or {}).keys()))
    except yt_dlp.utils.DownloadError as e:
        if "not a bot" in str(e):
            print("BLOCKED: YouTube wants sign-in from this IP (bot check)")
        else:
            raise

What we verified: the CLI command and the script run on yt-dlp 2026.10.26 and save jNQXAC9IVRw.en.vtt from an unblocked IP, both with and without a cookiefile argument (an empty cookie file). We didn't run the --cookies-from-browser line, because this machine has no browser profile, and we did not test real logged-in cookies, because we won't tie a Google account to a scraper. Be aware of the trade-offs:

4. Rotating residential proxies (paid)

yt-dlp --proxy http://USER:PASS@host:port ..., or proxy_config= in youtube-transcript-api. Code and caveats here. Datacenter proxies usually get the same challenge.

5. A hosted transcript service (paid per transcript)

The service's IPs talk to YouTube, so your server never sees the challenge. Our option is the ShepHouse YouTube Transcript Actor: $5 per 1,000 delivered transcripts, no start fee, failed videos not charged, billed to your Apify account. If you use youtube-transcript-api, the shephouse-yt client is a drop-in replacement for fetch(). Other services are cheaper per call. See the honest comparison table.

Related: RequestBlocked / IpBlocked · AWS, GCP and GitHub Actions


Building search or Q&A over YouTube videos? Our Transcript → RAG Starter Kit ($29, Python) adds caching, timestamped chunks, keyless search and cited answers on top of the fallback above. Disclosure: it's a ShepHouse product.

Last tested: 2026-10-28 (yt-dlp 2026.10.26, youtube-transcript-api 1.2.4). Corrections welcome via the Polar customer portal or the order page.