Claude API Key Not Working? How to Fix It
If your Claude API key is throwing authentication errors, returning 401/403 responses, or simply not being accepted, the cause is almost always one of a handful of predictable problems: a malformed key, a missing or wrong header, an expired or revoked key, an organization/workspace mismatch, or a billing issue on the account. This guide walks through each one in order of likelihood so you can diagnose and fix it in a few minutes instead of guessing.
Before anything else, isolate the problem. Run a single, minimal request against the API with curl, outside of your application code. If the raw request fails the same way your app does, the key or account is the issue. If the raw request succeeds but your app still fails, the bug is in how your code sends the key — a much faster thing to fix.
Step 1: Test the key with a bare curl request
Strip away your SDK, framework, and environment variables. Use a plain curl call:
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 16,
"messages": [{"role": "user", "content": "ping"}]
}'
If this returns a valid response, your key is fine and the problem is in your application's configuration. If it returns an error, the message tells you exactly what's wrong — read it carefully instead of assuming.
Step 2: Check for the most common copy-paste mistakes
A large share of "key not working" reports come down to how the key was copied or stored:
- Trailing whitespace or newline — keys copied from a dashboard or
.envfile often pick up a trailing space or\n. Trim it:echo -n "$ANTHROPIC_API_KEY" | wc -cshould match the expected key length exactly. - Wrong header name — Anthropic's API expects
x-api-key, notAuthorization: Bearer. Mixing conventions from OpenAI-style code is a frequent cause of silent 401s. - Missing
anthropic-versionheader — some endpoints reject requests without a valid version header, and the error message can be misleading if you're not expecting it. - Quotes baked into the value — if you set the key in a
.envfile asANTHROPIC_API_KEY="sk-ant-...", some loaders include the quote characters literally. Print the variable and check the first and last characters. - Environment not reloaded — if you updated the key in your shell profile or deployment config but didn't restart the process, you're still running on the old value.
Step 3: Confirm the key hasn't been revoked or rotated
Keys get invalidated for a few reasons: someone on the team regenerated it, it was flagged for a security issue, or it was tied to a project/workspace that was deleted or reorganized. Log into the console and check:
- Is the key still listed as active?
- Does it belong to the organization and workspace you expect?
- Was it created under a different project than the one your billing is attached to?
If the key was recently rotated, every service using the old value — CI pipelines, serverless environment variables, local .env files on teammates' machines — needs to be updated individually. This is a common source of "it works for me but not in production" reports.
Step 4: Rule out billing and usage limits
A key can be syntactically valid and still get rejected if the account behind it has a billing problem: an expired card, a paused account, or a hard usage cap. These usually come back as a 4xx error with a message about billing or quota rather than a generic auth failure, but it's easy to mistake one for the other if you're not reading the body of the error response. Always log the full response body, not just the status code.
Step 5: Check for model or region restrictions
Some keys are scoped to specific models or have access limited during a trial period. If your bare curl test works for one model but fails for another, the key is valid — it's a permissions/model-access issue, not an authentication bug. Check which models your account actually has access to before assuming the key itself is broken.
If you're building on top of Claude for a product
A lot of key-related headaches come from managing raw Anthropic credentials across multiple environments: local dev, staging, CI, production, and teammates' machines. Every rotation means updating several places, and every outage investigation starts with "is it the key or is it the code?"
SubToAPI sits between your application and Claude, issuing its own scoped sub_live_... application keys instead of passing raw provider credentials around. You rotate or revoke a sub_live_... key from one dashboard without touching the underlying account, and every request — streaming, tool use, or standard messages — goes through the same predictable interface. If you're debugging key issues across a team, it's worth checking the quickstart to see whether centralizing key management removes this entire class of problem. Pricing starts at the Solo plan for €9, with Team and Scale tiers for multi-seat setups — see /pricing.
A quick diagnostic checklist
- [ ] Run a bare curl request outside your app
- [ ] Check for trailing whitespace, quotes, or newlines in the key
- [ ] Confirm you're using
x-api-key, notAuthorization: Bearer - [ ] Include a valid
anthropic-versionheader - [ ] Restart any process after changing environment variables
- [ ] Verify the key is still active in the console
- [ ] Check billing status and usage limits
- [ ] Confirm the model you're calling is available to that key
Work through this list top to bottom and you'll find the problem well before you need to contact support.
questions
Why does my Claude API key work in curl but not in my app? This almost always means your application code is sending the key incorrectly — wrong header name, extra whitespace, an unloaded environment variable, or quotes baked into the string. Compare the raw HTTP request your app sends (log the headers) against the working curl command line by line.
Can a Claude API key stop working without being changed? Yes. Billing failures, exceeded usage limits, organization restructuring, or a security-triggered revocation can all invalidate a key that was previously working, even if no one on your team touched it directly. Check the console and the error response body before assuming the key itself is malformed.
What's the difference between a 401 and a 403 error from the Claude API? A 401 generally means the key itself wasn't recognized as valid — bad format, revoked, or missing header. A 403 usually means the key is valid but doesn't have permission for what you're requesting, such as a restricted model or an organization-level limit. Read the error message body, not just the status code, to tell them apart.