Resolve "Hugging Face 401 Unauthorized"

Quick answer

A Hugging Face 401 Unauthorized means your request was not authenticated — the token is missing, invalid, or expired. Fix it by logging in with huggingface-cli login or setting a valid HF_TOKEN. If you are authenticated but still blocked, the repo is gated or private: accept the model's terms on its Hub page, and make sure your token has access — fine-grained tokens need the gated-repos permission enabled explicitly.

You try to download a model and get:

huggingface_hub.utils._errors.HfHubHTTPError: 401 Client Error: Unauthorized
for url: https://huggingface.co/meta-llama/Llama-3.1-8B/resolve/main/config.json

Or the more explicit variant:

Cannot access gated repo for url ... Access to model meta-llama/Llama-3.1-8B is
restricted. You must be authenticated to access it.

A 401 is specifically an identity failure — the Hub is saying "I don't know who you are." That is different from "I know you but you're not allowed" (a 403) and different again from "that repo doesn't exist for you" (a 404). People burn time trying gated-access fixes on what is actually a bad-token problem, or vice versa.

This guide separates the three cleanly, then walks the fixes: authenticating properly, the two-step dance for gated models, and the fine-grained-token gotcha that trips up almost everyone in 2024 and later.

Quick Answer

A Hugging Face 401 Unauthorized means your request wasn't authenticated — the token is missing, invalid, or expired. Log in with huggingface-cli login or set a valid HF_TOKEN. If you're authenticated but still blocked, the repo is gated or private: accept the model's terms on its Hub page, and make sure your token has access — fine-grained tokens need the gated-repos permission enabled explicitly.

TL;DR

  • 401 = identity. Missing/invalid/expired token → authenticate.
  • Verify with huggingface-cli whoami before guessing.
  • Gated models need two things: accept terms and a token with access.
  • Fine-grained tokens don't access gated repos by default — enable it.
  • 401 ≠ 403 ≠ 404. Different meanings, different fixes.
  • "Repository Not Found" can mean a private repo you can't see.
  • CI/Docker: pass HF_TOKEN as a secret, never commit it.

First, Tell the Three Errors Apart

401 vs 403 vs 404 on the Hugging Face Hub: three different failures, three different fixesA 401 means the token is missing, invalid, or expired. A 403 or GatedRepoError means you are known but have not accepted the terms or your token lacks gated access. A 404 Repository Not Found often means a private repo you cannot see, or a typo in the id.401 UnauthorizedWho are you?Missing, invalid, orexpired tokenFix: log in / valid token403 · GatedRepoErrorI know you, but no.Terms not accepted, ortoken lacks gated accessFix: accept terms + token scope404 Not FoundCan't confirm it exists.Private repo you can't see,or a typo in the idFix: request access / check id
401 vs 403 vs 404 on the Hugging Face Hub: three different failures, three different fixes

This is the distinction the error text doesn't make for you:

CodeMeaningTypical causeFix
401 Unauthorized"Who are you?"No token, or invalid/expired tokenAuthenticate with a valid token
403 / GatedRepoError"I know you, but no."Terms not accepted, or token lacks gated accessAccept terms + fix token scope
404 Repository Not Found"Can't confirm it exists."Private repo you can't see, or a typoRequest access / check the id
⚠️

Hugging Face deliberately returns "Repository Not Found" for private repos you lack access to, instead of confirming they exist. So a 404 can really be an access problem in disguise — don't assume the repo id is wrong until you've checked your permissions.

The Triage

Hugging Face 401 triage: are you authenticated, and does your token have access?First check whether huggingface-cli whoami works. If not, you are not authenticated — log in or set a valid token. If you are authenticated, decide whether the repo is gated, needing accepted terms plus a token with gated access, or private, needing org or repo access.401 error on from_pretrained / downloadhuggingface-cli whoami works?(valid, non-expired token)noNot authenticated (401)huggingface-cli login, or set avalid HF_TOKEN in the environmentyesrepo gatedor private?gatedGated modelAccept terms on the model page+ token has gated-repo accessprivatePrivate repoGet org / repo access(may show 'Repository Not Found')
Hugging Face 401 triage: are you authenticated, and does your token have access?

Answer two questions in order and you'll always land on the right fix:

  1. Are you authenticated? huggingface-cli whoami — if it errors, you're not.
  2. If authenticated, is the repo gated or private? Gated needs accepted terms plus token access; private needs org/repo membership.

Step-by-step Solution

Step 1: Verify who you are

Before changing anything, check your current identity:

huggingface-cli whoami
  • Prints your username → you have a working token; skip to gated/private access.
  • Errors or "Not logged in" → you're not authenticated; do Step 2.

Step 2: Authenticate

Pick one method. CLI login is best for a dev machine; the env var is best for CI/servers:

# Interactive login (stores the token in ~/.cache/huggingface/token)
huggingface-cli login
 
# Or set the environment variable (read automatically by huggingface_hub)
export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx

Or pass the token directly in code:

from transformers import AutoModel
 
model = AutoModel.from_pretrained(
    "your-org/private-model",
    token="hf_xxxxxxxxxxxxxxxxxxxx",   # explicit token wins over env/cache
)

Create the token at huggingface.co/settings/tokens. A read token is enough for downloading; you only need write to push.

🔑

Token resolution order: an explicit token= argument wins, then HF_TOKEN in the environment, then the cached login file. If a bad HF_TOKEN is set, it overrides your good huggingface-cli login — which is a very common "I logged in but still 401" cause. Check with env | grep HF_TOKEN.

Step 3: For gated models, accept the terms

Gated models (Llama, Gemma, Mistral, and many others) require you to accept their license on the Hub before any token works:

  1. Open the model page, e.g. huggingface.co/meta-llama/Llama-3.1-8B.
  2. Click Agree and access repository (or Request access if approval is needed).
  3. Wait for approval if it's manual — instant for most, hours for a few.

Only after this does your authenticated token gain access. Accepting terms without a token, or a token without accepting terms, both fail.

Step 4: Fix fine-grained token permissions

This is the modern gotcha. Fine-grained tokens do not access gated repos by default, even for models you've been granted. In the token's settings:

  • Enable "Read access to contents of all public gated repos you can access", or
  • Grant the specific repository under the token's permitted resources.

A legacy read token has gated access implicitly; a fine-grained one does not until you turn it on. If a classic token works and a fine-grained one 403s on the same model, this is why.

Platform-Specific Notes

CI/CD (GitHub Actions, GitLab)

Store the token as a secret, never in the repo:

# GitHub Actions
env:
  HF_TOKEN: ${{ secrets.HF_TOKEN }}

huggingface_hub reads HF_TOKEN automatically, so no code change is needed. Never echo the token or commit it — a leaked token is a security incident.

Docker

Pass the token at run time, not build time, so it isn't baked into a layer:

docker run -e HF_TOKEN=hf_xxx your-image

For builds that must download gated models, use BuildKit secrets (--mount=type=secret) rather than an ARG or ENV, which persist in the image history.

Spaces / notebooks

In a Hugging Face Space, add the token as a repository secret named HF_TOKEN. In Colab/Kaggle, set it via the secrets manager and load it into the environment — don't paste it into a cell you might share.

Verification Steps

  1. huggingface-cli whoami prints your username.
  2. A gated download succeeds:
from huggingface_hub import hf_hub_download
p = hf_hub_download("meta-llama/Llama-3.1-8B", "config.json")
print(p)   # a local path, no 401
  1. The model page shows "You have been granted access" (gated case).
  2. env | grep HF_TOKEN shows the token you expect — not a stale one.
  3. In CI, the job logs show the download succeeding without printing the token.

Green state: whoami names you, the gated download returns a path, the model page confirms access, and no HF_TOKEN in the environment contradicts your login.

Security Best Practices

  • Use read-scoped or fine-grained tokens for downloads — never a write token in a training job.
  • One token per environment (laptop, CI, prod) so you can revoke one without breaking the others.
  • Never commit tokens or print them in logs; rotate immediately if leaked.
  • Prefer fine-grained tokens in production — scope them to the exact repos you need.
  • Set HF_TOKEN from a secret store, not a .env committed to the repo.

Prevention

  • Authenticate once per environment and verify with whoami.
  • Accept gated terms before the first automated run, not during it.
  • Enable gated-repo access on fine-grained tokens up front.
  • Store HF_TOKEN as a CI/Docker secret, never in code.
  • Add a startup check that calls whoami and fails loudly if unauthenticated.
  • Document which token each service uses so rotation is painless.

Troubleshooting Matrix

SymptomLikely causeFix
401 on any downloadNot authenticatedhuggingface-cli login / set HF_TOKEN
401 after loginStale/overriding HF_TOKENenv | grep HF_TOKEN; re-login
403 / GatedRepoErrorTerms not acceptedAccept on the model page
403 with fine-grained tokenMissing gated permissionEnable gated-repos access on the token
404 Repository Not FoundPrivate repo / typoRequest access / verify the id
Works locally, 401 in CISecret not setAdd HF_TOKEN secret to the job
401 only in DockerToken not passed-e HF_TOKEN=... at run time
Access page says "granted" but still 401Wrong/expired tokenCreate a fresh token, re-authenticate

External References

FAQs

Is a 401 ever caused by the model repo, not my token? Rarely. A 401 is about authentication, so it's almost always your token or login. If the token is valid and you've accepted the terms, a persistent failure is more likely a 403 (permissions) or a temporary Hub outage — check the status page.

Do I need a write token to download models? No. read scope is sufficient for downloading, including gated models you've been granted. Use write only for uploading. Smaller scope is safer.

Why does token=True sometimes work and token="hf_..." fail? token=True tells the library to use your cached login, which may be a different (working) token than the string you pasted. If a literal token fails, it's likely invalid, expired, or lacks gated access — regenerate it.

Can I check a token without downloading anything? Yes: huggingface-cli whoami uses the token to identify you. If it prints your username, the token authenticates; if it errors, the token is the problem.

The model was public yesterday and 401s today — what changed? The maintainer likely gated it, or your token expired/was rotated. Visit the model page: if it now shows a terms prompt, accept it and re-authenticate.

Key takeaways

  • A 401 means 'who are you?' — the token is missing, invalid, or expired, so authenticate first.
  • Verify your identity with huggingface-cli whoami before anything else; it confirms the token actually works.
  • Gated models need two things: accept the terms on the model page AND use a token that has access.
  • Fine-grained tokens do not access gated repos by default — enable the gated-repos permission or grant the specific repo.
  • 401, 403/GatedRepoError, and 404 'Repository Not Found' are three different failures with three different fixes.
  • A 'Repository Not Found' can mean a private repo you can't see — Hugging Face hides existence rather than leaking it.

Frequently asked questions

What does Hugging Face 401 Unauthorized mean?

It means your request reached the Hub but was not authenticated. No token was sent, or the token is invalid, expired, or revoked. It is an identity problem, not a permissions one — the fix is to log in with huggingface-cli login or set a valid HF_TOKEN, then retry.

How do I fix a 401 when downloading a gated model like Llama or Gemma?

Two steps are required. First, open the model page on huggingface.co and click Agree/Request access to accept the terms. Second, authenticate with a token that has access — huggingface-cli login or token=hf_... in code. Missing either step returns a 401 or 403.

My token works in the browser but not with a fine-grained token — why?

Fine-grained tokens do not include gated-repo access by default. In the token settings, enable 'Read access to contents of all public gated repos you can access', or grant the specific repository. A classic read token has this implicitly; a fine-grained one does not until you turn it on.

What's the difference between 401, 403, and 404 on Hugging Face?

401 Unauthorized means the token is missing or invalid — authenticate. 403 or GatedRepoError means you are known but not permitted — accept terms or fix the token scope. 404 Repository Not Found often means a private repo you cannot see, or a typo. They need different fixes, so read the code, not just the word 'error'.

How do I set the Hugging Face token in CI or Docker?

Pass it as an environment secret named HF_TOKEN — never bake it into the image or commit it. In GitHub Actions, add it as a repository secret and export it as HF_TOKEN in the job. The huggingface_hub library reads HF_TOKEN automatically, so no code change is needed.

Why do I still get 401 after huggingface-cli login?

Usually a stale or overriding token. An invalid HF_TOKEN in the environment overrides your login, or an old token sits in the cache. Run huggingface-cli whoami to see who you are, then huggingface-cli logout and log in again with a fresh token from your account settings.


Related Posts