yt-dlp: "Sign in to confirm you're not a bot"
What the error actually means, the fixes in order of how long each one lasts, and the two that make things worse.
Your download stops on this:
ERROR: [youtube] xxxxxxxxxxx: Sign in to confirm you're not a bot.
This helps protect our community. Learn more
Nothing is wrong with your setup. YouTube decided that the request did not look like it came from a browser, and asked it to prove otherwise. Below, what that means, then the fixes in the order worth trying, then the two things that are commonly recommended and make it worse.
What is actually happening
YouTube does not check who you are here. It checks what your request looks like: headers, timing, the client it claims to be, whether it arrives with the tokens a real player would have picked up on the way.
The important part is the last one. YouTube is gradually requiring a PO Token, a value a real player obtains by running YouTube’s own JavaScript. yt-dlp cannot produce one on its own, and the yt-dlp maintainers say so plainly. When a request needs a token and has none, this error is what comes back.
Two consequences follow, and they explain almost everything about this error:
- It is not deterministic. The same link fails and then works twenty minutes later, or works from your laptop and fails from your server, because the check is on the request and its origin, not on the video.
- Every fix has a shelf life. They work until YouTube changes what it measures. Any page that gives you one magic flag and no date was written before the last change.
The fixes, longest-lasting first
1. Update yt-dlp, and update it properly
Genuinely the fix most of the time, and the one people skip because it sounds too easy. yt-dlp ships workarounds for these checks within days; a build from two months ago is a build from before the last three changes.
yt-dlp -U
If your yt-dlp came from a package manager, -U may refuse to touch it. Check
what you actually have:
yt-dlp --version
and update it the way it was installed — brew upgrade yt-dlp,
pipx upgrade yt-dlp, pip install -U yt-dlp. If it is more than a few weeks
behind, stop here and try again before anything else.
The nightly channel exists for exactly this window, when a fix is merged but not yet in a stable release:
yt-dlp --update-to nightly
2. Give it cookies, but not the obvious way
Cookies make your request look like a signed-in browser session, which is the strongest signal you can hand over. There are two ways to do it, and the convenient one has a real problem.
yt-dlp --cookies-from-browser safari "URL"
This reads cookies straight from your browser. It works, and it breaks in a specific way: YouTube rotates those cookies. Your browser and yt-dlp then hold different versions of the same session, and the older one gets invalidated, which logs you out and can make things worse than before you started.
The yt-dlp wiki recommends a different route, and it is worth the extra minute:
- Open a private browsing window and log into YouTube.
- In the same tab, go to
https://www.youtube.com/robots.txt. - Export the cookies to a file with a browser extension.
- Close the private window without logging out.
Closing it without logging out is the whole point: the session is never invalidated, so the exported cookies keep working.
yt-dlp --cookies cookies.txt "URL"
The warning that belongs with this, which most pages leave out. The yt-dlp maintainers put it in writing: using your account with yt-dlp risks getting that account banned, temporarily or permanently. If the account is one you care about — a channel, a subscription, years of history — do not use it here. Make a throwaway.
3. Slow down
If you are working through a playlist or a list of links, the failure is often just rate limiting wearing a different mask. Put a real gap between requests:
yt-dlp -t sleep "URL"
or set it yourself:
yt-dlp --sleep-requests 2 --sleep-interval 5 --max-sleep-interval 10 "URL"
Five to ten seconds between downloads is the figure the yt-dlp documentation gives. It is slower. It also finishes, which is faster than a batch that dies at video nine.
4. Change the client it pretends to be
yt-dlp can ask YouTube as one of several official clients, and they are not checked equally hard:
yt-dlp --extractor-args "youtube:player_client=mweb" "URL"
Do not trust a specific client name you read in an article, including this
one. Which clients work changes every few months, and the pages recommending
android are quoting advice that was true in 2024. The living answer is in
yt-dlp’s own extractor guide,
which the maintainers update as the situation moves. Check the date on anything
else.
The two fixes that make it worse
A VPN. Almost every VPN exits through datacenter IP ranges, and datacenter IPs are the single most suspicious thing about a request. Turning the VPN off and going back to your ordinary connection fixes this error more often than turning one on. If you got the error while connected, disconnect and retry before changing anything else.
A server. Same reason, permanently. A download that works on your laptop and fails on your VPS is not a configuration problem; the VPS is on an address range that never watches YouTube.
Why this keeps happening
Nothing above is a fix in the sense of being over. YouTube changes what it measures, yt-dlp adapts, the cycle repeats — and the practical consequence is that the version of yt-dlp you are running matters more than any flag you pass it. A current build with no options beats a two-month-old build with all of them.
Which is the boring reason a downloader has to keep its own engine current rather than shipping a copy and forgetting about it. It is what the app I build does in the background, and it is most of what a graphical downloader is actually for.
If you are on the command line, the equivalent is worth setting up once:
yt-dlp -U before a batch, or a scheduled update, so that the next time this
error appears you have already ruled out the answer it turns out to be four
times out of five.