Blog

Claude Code Authentication Precedence: What Wins When Several Credentials Are Set

When several credentials are present at once, which one does Claude Code actually use? The official authentication precedence list answers that, and it explains most 'my key stopped working' reports.

Claude Code Authentication Precedence: What Wins When Several Credentials Are Set

When several Claude Code credentials are present on the same machine, the tool does not guess and it is not random: the official documentation defines an explicit Claude Code authentication precedence order, and every request is served by the first source on that list that applies. That single fact explains two of the most confusing reports in the ecosystem. One is the subscription user whose requests keep flowing through an old API key. The other is the engineer who set a new token, watched the old one keep winning, and concluded the tool was broken. This article walks the official order level by level, covers the three conflicts that account for most confusion, and ends with a method for confirming which credential is actually in use instead of assuming. If you are still at the setup stage rather than the debugging stage, start with the first-configuration guide instead; this article is for the case where something is already configured and behaving unexpectedly.

Claude Code authentication precedence, level by level

The order below follows the official authentication page, which is the authoritative source and the page to re-check whenever this topic matters, because the details evolve faster than blog posts do.

  1. Cloud provider credentials. When CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, or CLAUDE_CODE_USE_FOUNDRY is set, the corresponding cloud provider's credential path is selected before anything else on this list.
  2. ANTHROPIC_AUTH_TOKEN. Sent as an Authorization: Bearer header. This is the variable to use when routing through an LLM gateway or proxy that authenticates with bearer tokens rather than Anthropic API keys.
  3. ANTHROPIC_API_KEY. Sent as the X-Api-Key header, for direct API access with a key from the Claude Console. In interactive mode you are prompted once to approve or decline the key, and your choice is remembered; to change it later, use the custom API key toggle in /config, which only appears while the variable is set. In non-interactive mode, such as when -p is passed, the key is always used when present.
  4. apiKeyHelper script output. For dynamic or rotating credentials, such as short-lived tokens fetched from a vault.
  5. CLAUDE_CODE_OAUTH_TOKEN. A long-lived OAuth token generated by claude setup-token, intended for CI pipelines and scripts where browser login is not available. One subtlety matters here: if you run /login while the variable is set, Claude Code switches the current session to the new login, but reads the variable again in every new session until you remove it from your shell profile or from the env block of a settings file.
  6. Anthropic profile and federation credentials. The credentials written by the ant CLI and by Workload Identity Federation. A profile written by ant auth login ranks at this level only when you name it in ANTHROPIC_PROFILE; otherwise it ranks below /login.
  7. Subscription OAuth credentials from /login. The default path for Claude Pro, Max, Team, and Enterprise users.

Two notes sit outside the numbered list. First, a signed-in Claude apps gateway session is a provider selection rather than a credential: it outranks the cloud provider selections, and when it exists the CLI authenticates with the gateway token even if a cloud provider variable is set, while the bearer token, API key, apiKeyHelper, and profiles are not used. Managed settings that force a gateway sign-in behave similarly: the session uses only the gateway sign-in, skips the other credential sources, and asks you to sign in with /login. Second, an approved ANTHROPIC_API_KEY wins over an active subscription: the documentation notes that Claude Code uses the API key once you approve it, which can produce authentication failures when the key belongs to a disabled or expired organization. Running unset ANTHROPIC_API_KEY falls back to the subscription.

Three conflicts, starting with ANTHROPIC_AUTH_TOKEN vs ANTHROPIC_API_KEY

The precedence list turns several recurring mysteries into one-line answers.

Conflict one: you signed in, but requests still run through the API key. This is the "Claude Code login not taking effect" report, and "Claude Code API key not working" is its mirror image when the key is older than the subscription. Both come from the same rule: an approved API key takes precedence over a /login session, and /login does not replace an API key that is already in play. The fix is mechanical. Run /status and look at which method is active; when a login and an API key are both configured, /status marks the credential that is not in use. To go back to the subscription, unset the variable in the current shell and remove it from your shell profile, then relaunch Claude Code. The errors reference covers the billing-shaped variant of the same mistake, where requests silently run through a stray key when the subscription was the intent. Note that the variable may also live in the env block of a settings file rather than your profile.

Conflict two: both ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY are set. The order settles it: the bearer token ranks above the API key, so the gateway-oriented credential is used, and apiKeyHelper output only comes into play when nothing above it is set. If you set both during a migration and expected the key to win, this explains the outcome without any tool misbehavior.

Conflict three: you need this to work in CI, where /login is not available. The CI OAuth token answer for Claude Code is CLAUDE_CODE_OAUTH_TOKEN, generated with claude setup-token; the command opens the same browser authorization flow as /login, the token prints to the terminal, and nothing is saved to disk, so you copy it into your CI secret store yourself. Two boundaries are worth knowing before you design around it. The token authenticates with your subscription and can only make model requests: it cannot establish Remote Control sessions or fetch claude.ai connectors, though MCP servers you configure locally still work. And if you remove the variable later, remember that every new session re-reads the environment: a token "removed" from the current shell only is not removed at all. Related: in bare mode the tool does not read CLAUDE_CODE_OAUTH_TOKEN at all, so scripted runs that use --bare should authenticate with an API key or an apiKeyHelper instead. The CI guide covers the unattended pipeline setup around these choices.

How to tell which credential is actually in use

Instead of guessing, work the list mechanically:

  1. Inventory the environment. Check which relevant variables are set, not only in the shell but also in the env block of settings files, which is a common hiding place for stale credentials.
  2. Identify the mode. Interactive sessions, non-interactive -p runs, and bare-mode runs do not read the same sources; for example the interactive approval prompt and remembered choice only exist in interactive mode.
  3. Walk the precedence order. Find the first level that applies to your environment; that is your credential, regardless of what you set most recently.
  4. Confirm the scope. These variables and the helper apply to the CLI and the surfaces that wrap it, including the VS Code extension, the Agent SDK, and GitHub Actions. Claude Desktop and cloud sessions do not read them: those use OAuth, with a documented exception when a desktop session runs a third-party inference configuration. Cloud sessions always use your subscription credentials, and setting ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN in the cloud environment does not override them.

If the HTTP symptom matters more than the mechanism, the error code guide maps the status codes; this article is the root-cause companion for the 401 family. The endpoint context for pointing these credentials at a compatible service is in the platform documentation. And if the goal is to change or rotate credentials cleanly rather than to debug them, the provider switching guide carries the checklist.

The quick reference

| Credential source | Where it applies |
| :- | :- |
| Cloud provider variables / gateway session | CLI and wrapped surfaces; gateway outranks cloud providers |
| ANTHROPIC_AUTH_TOKEN | CLI, VS Code extension, Agent SDK, GitHub Actions; send bearer token through gateways |
| ANTHROPIC_API_KEY | Same surfaces; approved key outranks a /login subscription |
| apiKeyHelper | Same surfaces; consulted only when nothing above it is set |
| CLAUDE_CODE_OAUTH_TOKEN | CI and scripts; not read in bare mode |
| Profiles and federation | CLI logins; not read in bare mode, Claude Desktop, or cloud sessions |
| /login subscription | Default for individual plans; not available to override in cloud sessions |

Two habits keep this table useful. Re-check the official authentication page before making changes, because precedence details and the surfaces covered are exactly the kind of thing that gets refined over time; and confirm outcomes with /status rather than assuming, since it names the active method and marks the source that is configured but not in use. A credential you can see, explained by an order you can cite, is a much better position than a machine full of keys where one of them quietly wins.