Back to blog

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

Why yt-dlp hits YouTube's bot check, the six fixes in the order to try them, and what we measured across 800 residential proxy exits.

TL;DR: Sign in to confirm you're not a bot means YouTube decided your request looks automated. Try the fixes in this order: update yt-dlp, slow down, pass cookies from a spare account, add a PO token provider, and on a server, change the IP you send from. If all you need is the text of the video, you do not need yt-dlp at all: fetch the captions instead.

Troubleshooting

What the error looks like

The full message usually reads like this:

text
ERROR: [youtube] dQw4w9WgXcQ: 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.

Two details save time when you search your logs for it:

  • The apostrophe in "you're" is often a curly one (U+2019), not a straight quote. A grep for not a bot catches both.
  • Sign in to confirm your age is a different wall. That one is an age gate on the video, and the fix is cookies from an account that can watch age restricted videos. Matching on sign in to confirm alone mixes the two up. We made that mistake in our own error handling before we split them.
Guide

Why YouTube shows it

YouTube scores every request. The things that push a request toward the bot check are:

  • Where it comes from. Cloud servers (AWS, Google Cloud, Azure, Hetzner, DigitalOcean and the rest), most VPN exits and busy shared addresses carry a bad reputation. The same command that works on your laptop fails on a server for this reason alone.

  • How fast it goes. The yt-dlp wiki puts the rate limit for guest sessions at about 300 videos an hour, and about 2,000 for a signed in account. Past that, you get blocked.

  • How it looks. Old yt-dlp versions, or clients YouTube now expects a proof of origin (PO) token from, stand out.

The block is on the request, not on yt-dlp. That is why the fixes are about the request.

Guide

Fix 1: update yt-dlp

YouTube changes its pages and player often, and yt-dlp releases follow within days. An old build from a distro package is the most common cause of errors that have already been fixed.

bash
# installed with pip
python3 -m pip install -U "yt-dlp[default]"

# the standalone binary
yt-dlp -U

# when a fix landed but is not in a release yet
yt-dlp --update-to nightly

If the error survives the update, the cause is your IP or your rate. Read on.

Guide

Fix 2: slow down

If you are downloading a playlist or a channel, the bot check can simply mean you went too fast. The wiki suggests waiting about 5 to 10 seconds between downloads:

bash
yt-dlp -t sleep "https://www.youtube.com/playlist?list=..."
# or set the pauses yourself
yt-dlp --sleep-requests 1 --sleep-interval 5 --max-sleep-interval 10 "URL"

This is free and it is the fix people skip. Try it before cookies.

Guide

Fix 3: pass cookies, from a spare account

This is what the error message itself suggests. On your own computer the quick version is:

bash
yt-dlp --cookies-from-browser firefox "URL"

On a server, or for anything that runs unattended, export a cookies file instead. The yt-dlp wiki's method matters, because YouTube rotates account cookies on any open YouTube tab:

  1. Open a private (incognito) window and sign in to YouTube.
  2. In the same tab, open https://www.youtube.com/robots.txt.
  3. Export the youtube.com cookies to cookies.txt with a cookies.txt export extension, then close the private window without opening YouTube again.
bash
yt-dlp --cookies cookies.txt "URL"

Read this before you do it: the wiki warns that "by using your account with yt-dlp, you run the risk of it being banned (temporarily or permanently)." Use an account you can lose, never your main one, and keep the rate low. Treat cookies.txt like a password, because it is one.

Guide

Fix 4: add a PO token provider

YouTube now asks some clients for a proof of origin token, and requests without one get blocked or fail with 403 errors. The yt-dlp wiki's PO Token Guide recommends a provider plugin rather than copying tokens by hand, since tokens are now tied to the video. The plugin it points to first is bgutil-ytdlp-pot-provider, with yt-dlp-getpot-wpc as a fallback. Neither is part of yt-dlp itself, so read their install notes for your setup.

Guide

Fix 5: change the IP you send from

On a cloud server, fixes 1 to 4 often only delay the block. The address itself is the problem, and the honest fix is to send YouTube traffic from somewhere else: a residential or mobile proxy, or a machine on a home connection.

Not all residential proxies are equal, and this is the part we have measured ourselves. We run YouTube requests through rotating residential proxies in production, and in September 2026 we tested two providers side by side: 400 fresh exits each, interleaved in time, every exit sent to the same video.

Provider AProvider B
Exits tested400400
Blocked by YouTube20.5%4.5%
Failed to connect at all13.3%0%
Usable exits66%95.5%

Three things from that test are worth knowing even if you never buy a proxy:

  • "Residential" does not mean clean. One in five of provider A's addresses was already blocked before we sent a single real request.

  • The watch page loading proves nothing. For most of provider A's blocks, the video page itself loaded fine, and the bot check came on the next request, the player call, which is the one that returns the formats and the caption tracks. If you test a proxy, test that call, not the page.

  • A block on one exit is not a block on the provider. Rotating to a fresh exit and retrying once got past almost all of it. Across our production requests, about 17% needed a fresh exit, and well under 1% reached a customer as a failure.

Proxies cost money per gigabyte, and video is heavy. That is the reason for the last fix.

Guide

Fix 6: if you only need the text, skip the video

A lot of yt-dlp runs on servers exist for one thing: getting the words out of a video, to summarize it, search it or feed it to a model. For that you do not need the video, or even the audio, when the video has captions. The caption track is a separate request that is a tiny fraction of the size.

With yt-dlp you can ask for captions only:

bash
yt-dlp --skip-download --write-subs --write-auto-subs --sub-langs en --sub-format vtt "URL"

That still goes through the same bot check, so on a server it fails the same way. If you would rather not run proxies, cookies and plugins at all, a hosted transcript API does that part for you. TranscriptFetch is ours: you send a video URL or ID and get the transcript back as JSON, and when a video has no captions it can transcribe the audio instead.

bash
curl https://transcriptfetch.com/api/v2/transcripts/video \
  -H "Authorization: Bearer $TRANSCRIPTFETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video":"dQw4w9WgXcQ"}'

The first 50 transcripts each month are free, and failed requests are never charged. If you only need one transcript now, the free YouTube transcript generator works in the browser without an account.

Buying guide

Which fix is right for you?

Your situationStart with
Your own computer, a few videosFixes 1 and 2, then cookies from your browser
A playlist or a channelFix 2, then fix 3 with a spare account
A cloud server, video files neededFixes 1, 4 and 5 together
A cloud server, only the text neededFix 6

If you hit the same wall with the Python library youtube-transcript-api instead of yt-dlp, it raises RequestBlocked; our RequestBlocked guide covers that one.

FAQ

YouTube decided the request looks automated, usually because of the IP it came from (a cloud server, a VPN, a busy shared address) or because too many videos were requested too fast. It is a block on the request, not a bug in yt-dlp.