Anthropic API Authentication Headers Guide
If you're getting a 401 or 403 error calling Claude, it's almost always a headers problem. The Anthropic API doesn't use a standard Authorization: Bearer header like most REST APIs — it has its own header requirements, and missing or misconfigured ones are the most common cause of failed requests.
This guide covers exactly which headers Anthropic's API expects, what each one does, and the mistakes that cause silent failures. We'll also look at what changes if you're authenticating against a proxy or gateway like SubToAPI instead of calling Anthropic directly.
The three required headers
Every request to Anthropic's Messages API needs three headers set correctly:
x-api-key: sk-ant-api03-...
anthropic-version: 2023-06-01
content-type: application/json
x-api-key
This is your authentication credential — not Authorization, not Bearer. Anthropic uses a dedicated header. Your key starts with sk-ant- and is generated in the Anthropic Console. If you send it as Authorization: Bearer sk-ant-... instead of x-api-key, you'll get a 401 with an "authentication_error" type, and it's easy to miss why because the key itself is valid — it's just in the wrong header.
anthropic-version
This is a date-based version string (e.g. 2023-06-01) that pins the API behavior you're coding against. It's mandatory, not optional — omit it and you'll get a 400 error, not a helpful default. Anthropic ships new model capabilities and response shapes under new version strings, so pinning this explicitly protects you from breaking changes when Anthropic updates the default.
content-type
Standard JSON content type, required for any POST request with a body. Easy to forget if you're building requests manually rather than through an SDK.
A working curl example
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-opus-4-20250514",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Explain the x-api-key header in one sentence."}
]
}'
If any of the three headers is missing, this returns an error before Anthropic even looks at the model or messages fields.
Optional but important headers
Beyond the three required ones, a few optional headers matter for specific features:
anthropic-beta— required when using features still in beta (certain tool-use modes, extended context, PDF support, etc.). The exact string depends on the feature and changes over time, so check the docs for the feature you're using rather than hardcoding an old value.anthropic-dangerous-direct-browser-access— required only if you're calling the API directly from client-side JavaScript in a browser, which Anthropic strongly discourages for security reasons (your API key would be exposed to anyone inspecting network requests).
That last point is worth dwelling on: never put your Anthropic API key in frontend code. Any header you can set from a browser can be read from a browser. If you need Claude access in a web or mobile app, route requests through your own backend, or through a service designed for that purpose.
Common authentication mistakes
A few patterns account for most header-related failures:
- Using
Authorization: Bearerinstead ofx-api-key. This is the single most common mistake for developers coming from OpenAI's API, which does use Bearer tokens. - Omitting
anthropic-version. Some SDKs set this automatically; raw curl or fetch calls often don't, and the error message doesn't always make the missing header obvious. - Sending the key with extra whitespace or quotes from a
.envfile that wasn't parsed correctly — the key looks right in logs but fails silently. - Reusing a key across environments without rotation, so a leaked staging key also has production access.
Headers when using a gateway instead of calling Anthropic directly
If you're accessing Claude through a proxy or API gateway rather than Anthropic's endpoint directly, the header contract is usually simpler, because the gateway handles the Anthropic-specific headers for you.
With SubToAPI, for example, authentication is a standard Authorization: Bearer header with your application key (sub_live_...):
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-4-20250514",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello"}
]
}'
No x-api-key, no anthropic-version to track, no beta headers to manage manually. SubToAPI turns your existing Claude access into a standard HTTPS API with one key per application, so your team can issue, rotate, and scope keys per project without touching Anthropic console credentials directly. See the quickstart for the full setup, or the Messages endpoint reference for request/response details.
Debugging a 401 step by step
When a request fails authentication, check in this order:
- Is the key in
x-api-key, notAuthorization? (Or, if using a gateway, the reverse.) - Is
anthropic-versionpresent and a valid date string? - Did the key get truncated or quoted when loaded from environment variables — print its length to confirm?
- Is the key active in the console, not revoked or expired?
- Are you hitting the correct base URL for your provider — direct Anthropic endpoint vs. a gateway endpoint use different hostnames and header schemes, and mixing them up produces confusing errors.
Most authentication issues resolve at step 1 or 2. If you've confirmed headers are correct and still get 401s, the key itself is the problem — regenerate it.
questions
Does Anthropic use Bearer tokens like OpenAI? No. Anthropic requires the key in a dedicated x-api-key header, not Authorization: Bearer. Sending it as a Bearer token returns a 401 even if the key is valid.
Why do I get a 400 error even with a correct API key? Almost always a missing or malformed anthropic-version header. It's required on every request and must be a valid date string Anthropic has published.
Is it safe to call the Anthropic API directly from browser JavaScript? No. Any key sent from client-side code is visible to users via network inspection. Route calls through a backend or a gateway service, and keep API keys server-side only.