401 Invalid API key — why your key is rejected
You pasted the key and the server still answers 401. Here are the five causes, ordered by how often they actually happen.
2 min · · Updated · errors · API keys · setup
A 401 with Invalid API key means one thing: the server could not match the key you sent to any active key. The cause is almost always in how the key was passed, not in the key itself.
Test the key on its own first
Before touching your client, confirm the key works. One command:
curl -s -o /dev/null -w "%{http_code}\n" https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"hi"}]}'A 200 means the key is fine and the problem is in your client configuration. A 401 means the key itself is the problem.
Five causes, most common first
Stray characters from copying. By far the most frequent. A trailing space, a newline, an invisible character from the clipboard. The key looks right but the bytes differ. Clear the value completely and paste it again without dragging across neighbouring characters.
The wrong header. The key travels as Authorization: Bearer fetch_.... Some clients default to x-api-key, which also works on the Anthropic-compatible path — but do not mix them. If both headers are present, only one is read, and not necessarily the one you filled in.
A revoked key. Revocation takes effect immediately and permanently. Open your keys page and check that the key in your client is still active. When in doubt, issue a new one — it costs nothing.
A key from a different service. Anthropic keys start with sk-ant-, OpenAI keys with sk-. Ours start with fetch_. A foreign prefix means your client is reading the wrong variable, or picked up a stale value from the system environment.
A shadowed variable. An exported shell variable overrides the value in a settings file. Run echo $ANTHROPIC_AUTH_TOKEN — if that is not your key, look for an export in .zshrc, .bashrc, or your terminal profile.
What 401 does not mean
An empty balance returns 402, not 401. A model not allowed for this key returns 403 (model_not_allowed_for_key). A disabled model returns 503 (model_disabled). If you see 401, your balance and account settings are not involved — the question is only about the key.
If none of that helped
Issue a fresh key, put it in a scratch file, verify it with the command above, and only then move it into your client. That separates a key problem from a configuration problem instead of debugging both at once.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- OpenAI API Keys in the Open: Why You Should Not Use ThemWhere free keys on GitHub come from, why using them is dangerous for you and for the owner, and how to protect your own key from the same leak.
- GLM API Errors: Why the Request Fails and How to Fix ItA wrong model id, an overflowing 128K context, the key, the balance, limits: the typical causes of GLM API errors and a quick way to find yours.
- This organization has been disabled in the Claude API: What to DoAn Anthropic key suddenly answers "organization has been disabled". What the error is, what to check, and how to move the SDK and Claude Code to another provider.
- Gemini API not working: region, key, limits and model nameStep-by-step Gemini API diagnostics: from checking status and region to a leaked key, 429 and 503 errors and a typo in the model name.