가이드 목록으로
Troubleshooting·2026년 8월 30일·6분 분량

ANTHROPIC_AUTH_TOKEN vs ANTHROPIC_API_KEY — which one Claude Code actually reads

These are not aliases. One becomes `x-api-key`, the other becomes `Authorization: Bearer` — and when both are set, the one you did not mean to use can win. Most "my key is correct but auth fails" reports against a custom base URL are this.

Last reviewed on .

These are not aliases. One becomes `x-api-key`, the other becomes `Authorization: Bearer` — and when both are set, the one you did not mean to use can win. Most "my key is correct but auth fails" reports against a custom base URL are this.

The error

the two variables
# Sent as:  x-api-key: <value>
export ANTHROPIC_API_KEY="sk-ant-..."

# Sent as:  Authorization: Bearer <value>
export ANTHROPIC_AUTH_TOKEN="sk-kn-..."

# Where those headers go:
export ANTHROPIC_BASE_URL="https://api.kunavo.com"

Causes and fixes at a glance

CauseFix
Gateway expects a bearer token; you set the API key variableMost OpenAI-compatible gateways authenticate on `Authorization: Bearer`. Put the gateway key in ANTHROPIC_AUTH_TOKEN.
Both variables set, from different providersA stale ANTHROPIC_API_KEY in your shell profile can be sent alongside the token. Unset the one you are not using.
Base URL set, credentials not changedPointing at a new host does not make an old provider's key valid there. The credential has to change with the host.
Variable set in a different shell than the one running the toolAn export in an interactive shell does not reach a GUI-launched process. Verify inside the same environment.

See what your environment is actually holding

Check both, in the shell that launches the tool, before changing anything. A surprising share of these sessions have both set — often one from a months-old profile edit nobody remembers.

inspect-env.sh
for v in ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL; do
  printf '%-22s %s\n' "$v" "$(printenv "$v" | cut -c1-12)"
done

# Prefixes tell you the provider at a glance:
#   sk-ant-  Anthropic direct
#   sk-kn-   Kunavo

Set the pair that matches your host, and unset the other

Treat host and credential as one unit. Against a third-party base URL, that is normally the bearer token plus the base URL, with the direct API key explicitly unset so it cannot be picked up.

third-party.sh
unset ANTHROPIC_API_KEY

export ANTHROPIC_AUTH_TOKEN="sk-kn-..."
export ANTHROPIC_BASE_URL="https://api.kunavo.com"

claude

Confirm on the wire, not in your head

If auth still fails, take the environment out of the question: issue the request by hand with the header you believe is being sent. A 200 here with a failure in the tool means the tool is not reading the variable you set — most often a different shell, or a config file overriding it.

verify.sh
curl -s -o /dev/null -w '%{http_code}\n' \
  "$ANTHROPIC_BASE_URL/v1/models" \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN"

If you’re calling through Kunavo

Kunavo authenticates on `Authorization: Bearer`, so with Claude Code the working pair is ANTHROPIC_AUTH_TOKEN plus ANTHROPIC_BASE_URL — and ANTHROPIC_API_KEY should be unset rather than left over, because a stale value there is the single most common cause of a session that looks configured and still refuses. The same `sk-kn-` key works unchanged as an OpenAI-style bearer token against /v1/chat/completions, so one credential covers both shapes. The full setup, including the model names to use, is in our Claude Code 401 guide.

FAQ

If both are set, which wins?

Do not rely on the answer — it is a precedence rule that has changed between versions and differs across SDKs. Set exactly one and unset the other; that is the only configuration that behaves the same everywhere.

Can I use ANTHROPIC_AUTH_TOKEN with Anthropic directly?

Anthropic's own API authenticates on x-api-key, so a direct Anthropic key belongs in ANTHROPIC_API_KEY. The token variable exists for hosts that expect a bearer credential.

Does the SDK use the same variables?

The Python and TypeScript SDKs read ANTHROPIC_API_KEY and send x-api-key. If you point an SDK at a bearer-auth gateway, pass the credential explicitly rather than relying on the environment.

Related guides

More error semantics live in the error reference; getting a key takes a minute via sign up and the authentication docs.