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.
What the error looks like
The full message usually reads like this:
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 botcatches both. Sign in to confirm your ageis 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 onsign in to confirmalone mixes the two up. We made that mistake in our own error handling before we split them.
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.
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.
# 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 nightlyIf the error survives the update, the cause is your IP or your rate. Read on.
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:
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.
Fix 3: pass cookies, from a spare account
This is what the error message itself suggests. On your own computer the quick version is:
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:
- Open a private (incognito) window and sign in to YouTube.
- In the same tab, open
https://www.youtube.com/robots.txt. - Export the youtube.com cookies to
cookies.txtwith a cookies.txt export extension, then close the private window without opening YouTube again.
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.
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.
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 A | Provider B | |
|---|---|---|
| Exits tested | 400 | 400 |
| Blocked by YouTube | 20.5% | 4.5% |
| Failed to connect at all | 13.3% | 0% |
| Usable exits | 66% | 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.
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:
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.
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.
Which fix is right for you?
| Your situation | Start with |
|---|---|
| Your own computer, a few videos | Fixes 1 and 2, then cookies from your browser |
| A playlist or a channel | Fix 2, then fix 3 with a spare account |
| A cloud server, video files needed | Fixes 1, 4 and 5 together |
| A cloud server, only the text needed | Fix 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.
Sometimes. YouTube changes often and yt-dlp releases follow quickly, so update first. If the error stays after an update, the cause is your IP or your request rate.
The yt-dlp wiki warns that using your account with yt-dlp risks a temporary or permanent ban. Use a spare account, keep the request rate low, and never use an account you cannot lose.
Your laptop has a home IP. Most cloud and data center IPs are treated as automated traffic, so the same command gets the bot check from a server.
No. Captions are a separate, much smaller request than the video. If text is all you need, fetch the caption track, or call a transcript API that handles the blocking for you.
