Skip to content

Start typing. Errors match on their exact yt-dlp output.

to move, to open esc to close

Fix "HTTP Error 403: Forbidden" in yt-dlp

Tested on yt-dlp 2026.07.28 Updated
What yt-dlp prints
ERROR: unable to download video data: HTTP Error 403: Forbidden

Quick answer

A 403 from yt-dlp almost never means you are blocked. It means the download URL yt-dlp extracted was rejected when it went to fetch it — usually because the cached player it derived the URL signature from is out of date. Update, clear the cache, and try again:

fixes it about eight times out of ten
yt-dlp -U && yt-dlp --rm-cache-dir && yt-dlp "URL"

Why a 403 happens

Downloading from YouTube is two separate steps, and the error comes from the second one. First yt-dlp fetches the watch page and extracts a list of media URLs. Those URLs are not permanent links to a file — each one carries a signature and an expiry timestamp, and the server checks both before serving a byte.

The signature is computed by JavaScript inside YouTube's player. yt-dlp downloads that player, works out what the function does, and applies it locally. To avoid doing that on every run it caches the result. When YouTube ships a new player — which happens often, and without notice — the cached logic produces signatures the server no longer accepts. The server does not say "your signature is wrong". It says 403 Forbidden.

That is the whole reason a 403 is so rarely about permissions. Nothing about your account, your IP or your right to view the video has changed. A link expired, or was computed with stale code.

The fixes, in the order worth trying

1. Update yt-dlp

If YouTube changed the player in a way yt-dlp cannot parse yet, no local fix helps — the extractor itself needs updating, and that update usually lands within a day or two. This is the first thing to rule out, and it takes ten seconds:

bash
yt-dlp --version
yt-dlp -U

If -U replies that the binary cannot update itself, yt-dlp came from pip or a package manager and has to be updated the same way. That distinction matters more than it sounds — how you installed it decides how fast extractor fixes reach you, and a distribution package can be a year behind.

2. Clear the player cache

This is the specific fix for a stale cached player, and it is the one that resolves most 403s that survive an update:

bash
yt-dlp --rm-cache-dir

It deletes ~/.cache/yt-dlp (or %LOCALAPPDATA%\yt-dlp on Windows). There is nothing precious in there — the next run rebuilds it. If you are scripting yt-dlp and hitting intermittent 403s, running this weekly is cheaper than debugging it each time.

3. Stop naming an exact format

A selector pinned to a specific format id sends you to one particular host, and some of those have far shorter URL expiry than others. A selector with a fallback lets yt-dlp pick again:

instead of -f 137+140
yt-dlp -f "bv*[height<=1080]+ba/b[height<=1080]" "URL"

The / is the fallback and the * in bv* allows a combined stream as well as a video-only one. Both are covered in format selection, which is worth twenty minutes if you use yt-dlp regularly.

4. Slow down

If the 403 appears part-way through a playlist rather than on the first video, it is a rate problem wearing a different error's clothes. Extraction is what gets throttled, and the symptom is inconsistent:

bash
yt-dlp --sleep-requests 1.5 --limit-rate 2M -i "PLAYLIST_URL"

See HTTP Error 429 for the full set of pacing flags — those apply here too when 403s come in bursts.

5. Supply cookies

Last, not first. Cookies help when the content genuinely needs an account, and they do nothing for an expired URL. They also carry a real cost: a session sent through a downloader is a session that can get flagged.

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

Confirming it worked

Do not test with a full download — a 4 GB file is a slow way to find out you are still broken. --simulate runs the whole extraction, including the part that 403s, and writes nothing:

bash
yt-dlp --simulate -v "URL"

Clean output means the URLs extracted fine. If you still see the 403, the -v output now has the two lines worth reading: the yt-dlp version, and the last line before the traceback.

If it still fails

A 403 that survives all five steps is usually not a 403 problem. Check which of these you actually have:

  • Every video fails, immediately, on a fresh install. Something between you and YouTube is intercepting the connection — a corporate proxy, a filtering DNS, an antivirus TLS scanner. See certificate verify failed, which often accompanies it.
  • Only age-restricted or members-only videos fail. That is an access problem that happens to surface as 403. Cookies are the answer, and the cookies guide covers getting them out correctly.
  • It works for a while, then 403s consistently. Rate limiting. Wait an hour before concluding anything else — most soft blocks expire on their own.
  • Only one specific video. Try it in a browser. If it plays there and not in yt-dlp, it is an extractor bug worth reporting with the full -v output.

What not to do

Two pieces of advice circulate widely for this error and both are wrong. --no-check-certificate disables TLS verification, which has nothing to do with an HTTP 403 — it turns a security check off and fixes nothing. And a random --user-agent string copied from a forum post makes things worse rather than better: YouTube expects the user agent to match the client yt-dlp is claiming to be, and a mismatch is one of the signals that triggers the bot check.

Frequently asked

Does a 403 mean my IP is banned?
Almost never. A ban shows up as 429 Too Many Requests or as a bot check, not as 403. A 403 on the media URL means that specific link expired or was rejected — the same request from the same IP works again as soon as yt-dlp fetches a fresh URL.
Why does --rm-cache-dir fix it?
yt-dlp caches the JavaScript player it extracts signatures from. When YouTube ships a new player, a stale cached copy produces signatures the server rejects, and the rejection is a 403. Clearing the cache forces yt-dlp to fetch and re-parse the current player.
I get 403 on some videos but not others.
That points at format rather than access. Some formats are served from hosts with stricter URL expiry than others. Try a different selector — -f "bv*[height<=1080]+ba/b" instead of a specific itag — and the problem usually disappears.
Will a VPN fix a 403?
Usually not, and it can make things worse: datacentre IP ranges are exactly what triggers bot checks. If the video is genuinely geo-restricted the error is "Video unavailable in your country", not 403.