Claude Code Proxy: Gateway or Corporate Proxy, and How to Configure Each (2026)
"Claude Code proxy" means two unrelated things. One is an LLM gateway that answers model requests, configured with ANTHROPIC_BASE_URL plus a credential. The other is a corporate HTTP proxy that your network forces all traffic through, configured with HTTPS_PROXY. They stack, and they fail differently.
Mixing them up is the reason a lot of setups stall. Someone is told "we run everything through a proxy", sets ANTHROPIC_BASE_URL to the corporate proxy address, and gets a 404 — because that address does not serve /v1/messages. This guide separates the two, gives the exact variables for each, and shows how to confirm which one is actually live. Everything below is from Anthropic's Claude Code documentation as of September 2026; these settings change between versions, so check the current docs before treating a version-specific detail as permanent.
The two things called a Claude Code proxy
|
|
LLM gateway / API proxy |
Corporate HTTP proxy |
|---|---|---|
|
What it does |
Answers the model request itself |
Forwards TCP traffic to wherever it was going |
|
Who runs it |
Your platform team, or a managed endpoint provider |
Your network or security team |
|
Main variable |
|
|
|
Also needs |
A credential the gateway issues |
Sometimes a CA certificate, sometimes client certificates |
|
Changes the destination? |
Yes — requests never reach |
No — the destination is unchanged, only the path there |
|
Typical failure |
|
TLS handshake errors, connection resets, hangs |
A useful test question: does this thing know what a model is? A gateway does — it authenticates you, picks an upstream, and returns a Messages API response. An HTTP proxy does not; it moves bytes. If you set ANTHROPIC_BASE_URL to something that only moves bytes, nothing works.
You can need both at once: a gateway inside your network, reached through the corporate proxy. That combination is covered further down.
Route 1: pointing Claude Code at a gateway
The Claude Code docs describe this as two values — the base URL and a credential.
export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
export ANTHROPIC_AUTH_TOKEN=sk-gateway-keyTwo details decide whether this works on the first try.
The base URL is the origin, with no path. The documented verification request posts to the variable with /v1/messages appended to it (the exact command is in the verification section below), which tells you the client adds that path itself. Including /v1 in the variable produces /v1/v1/messages and a 404 — the single most common setup mistake, and one the error message does not explain.
The credential variable decides the header. Per the docs, ANTHROPIC_AUTH_TOKEN is sent as Authorization: Bearer, ANTHROPIC_API_KEY is sent as x-api-key, and an apiKeyHelper command's output is sent in both. A credential in the wrong variable arrives in a header the gateway does not read, and you get a 401. If your gateway team did not say which kind it is, the docs recommend starting with ANTHROPIC_AUTH_TOKEN and switching if the test request returns 401.
Some gateways also want a routing or tenant header. That is ANTHROPIC_CUSTOM_HEADERS, one Name: Value pair per line — and \n between pairs when you set it inside a JSON settings file, since JSON strings cannot span lines.
Two side effects worth knowing before you commit: a gateway credential takes precedence over a saved claude.ai login (the login stays saved and unused until you unset the variable), and the docs state that Remote Control and voice dictation are unavailable while a gateway credential is active, with Remote Control also disabled while ANTHROPIC_BASE_URL points at a non-Anthropic host.
For what a gateway is for in the first place — shared billing, protocol conversion, a network path that works — the Claude API proxy guide covers the category and the evaluation criteria. For what changes when the model behind the endpoint is not Claude, see running Claude Code with alternative models.
Route 2: the corporate HTTP proxy
This one does not touch ANTHROPIC_BASE_URL at all. Requests still go to api.anthropic.com (or to your gateway); they just take a different path to get there.
# HTTPS proxy (recommended)
export HTTPS_PROXY=https://proxy.example.com:8080
# HTTP proxy, if HTTPS is not available
export HTTP_PROXY=http://proxy.example.com:8080
# Bypass the proxy for specific hosts — space- or comma-separated
export NO_PROXY="localhost,192.168.1.1,example.com,.example.com"Details from the documentation that save time:
- Lowercase variants work, and Claude Code uses the first one set, in the order
https_proxy,HTTPS_PROXY,http_proxy,HTTP_PROXY. A stale lowercase export in a shell profile silently wins over the uppercase one you just set. NO_PROXY="*"bypasses the proxy for everything.- Loopback needs no entry. WebSocket connections to
localhost,::1, and127.0.0.0/8never go through the proxy. - SOCKS proxies are not supported.
- Basic auth goes in the URL:
http://username:password@proxy.example.com:8080. The docs warn against hardcoding that in scripts. For NTLM or Kerberos proxies, they suggest a gateway that supports the authentication method instead.
Certificates
A TLS-inspecting proxy presents its own certificate, which is where most corporate setups actually break.
By default Claude Code trusts both its bundled Mozilla CA set and the operating system's certificate store, so a proxy whose root certificate is installed in the OS trust store works with no extra configuration. Reading the OS store needs a runtime with tls.getCACertificates: the native installer always has it; npm installs need Node 22.15 or later. On older Node, only the bundled set and NODE_EXTRA_CA_CERTS apply.
# Trust an additional CA explicitly
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
# Restrict which stores are trusted (default is bundled,system)
export CLAUDE_CODE_CERT_STORE=bundledIf the proxy requires client certificates, the mTLS variables are CLAUDE_CODE_CLIENT_CERT, CLAUDE_CODE_CLIENT_KEY, and optionally CLAUDE_CODE_CLIENT_KEY_PASSPHRASE.
Allowlisting
If egress is restricted, the proxy needs to allow the hosts Claude Code depends on. The documented list includes api.anthropic.com for API requests, claude.ai and claude.com and platform.claude.com for authentication, downloads.claude.ai for installer and update traffic, and registry.npmjs.org for npm installs and npx-launched MCP servers. The full table in the network configuration docs is longer; read it before finalising a rule set, because a partial allowlist produces failures that look like unrelated bugs.
Where the values belong
Both routes read plain environment variables, so the real question is which layer you put them in — the same question covered in depth in Claude Code's configuration layers.
Shell export — for trying something out. It applies to that terminal and programs started from it; an editor launched from the dock never sees it.
Settings file env block — for anything permanent:
{
"env": {
"ANTHROPIC_BASE_URL": "https://llm-gateway.example.com",
"ANTHROPIC_AUTH_TOKEN": "sk-gateway-key",
"HTTPS_PROXY": "https://proxy.example.com:8080"
}
}~/.claude/settings.json applies to every project; .claude/settings.local.json applies to one project and is not committed. The documentation is explicit that the credential must not go in a project's committed .claude/settings.json. When a shell export and a settings env block set the same variable, the settings value wins.
There is one case where the settings file is not merely tidier but required: background agents. They run under a per-user supervisor process that outlives your shell, so a shell-only export reaches them when that shell happened to start the supervisor and silently does not when a different one did. The docs say to put network variables in settings for that reason.
Verifying it took effect
Assume nothing. Claude Code does not validate most of these settings when it reads them, so a wrong value usually surfaces as an error on a later request.
Before launching the client, hit the gateway directly. This separates "is the endpoint reachable and the credential valid" from "is the client configured":
curl -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'A response starting {"id":"msg_ means the URL and credential both work. An unknown model error also proves it, since the gateway authenticated the request before rejecting the model name — you do not need to know which models it serves for this test.
Inside a session, run /status and read the rows the docs name:
Anthropic base URL— appears only when a gateway address is set. Missing means the variable never reached the session.Auth token/API key— namesANTHROPIC_AUTH_TOKEN,ANTHROPIC_API_KEY, or anapiKeyHelper. ALogin methodline naming a claude.ai account instead means the gateway credential is not active.Proxy— shows the active proxy URL, and marks an unparseable value as invalid and ignored.mTLS client cert/mTLS client key— appear only when the files loaded, so a missing row means the load failed.Additional CA cert(s)— shows theNODE_EXTRA_CA_CERTSpath without checking the file loaded. Confirm that one in the debug log.
For anything the status rows do not settle, start with debug logging. Output goes to ~/.claude/debug/<session-id>.txt, not the terminal:
claude --debugThe log carries confirmation lines such as CA certs: Appended extra certificates from NODE_EXTRA_CA_CERTS (...) and mTLS: Loaded client certificate from CLAUDE_CODE_CLIENT_CERT, or a Failed to read line with the reason.
One startup check does exist: the proxy URL is parsed at launch, and a value missing its http:// scheme stops launch with an error naming the variable to fix.
When both apply at once
A gateway inside a network that also runs an inspecting proxy needs both sets of variables, and they do not conflict — the gateway decides where the request goes, the proxy decides how it gets there. Two things to know about the combination:
Nonessential background traffic — version checks, telemetry, release notes — still leaves the gateway path and goes to Anthropic and third-party hosts. On a network that only permits egress to the gateway, those requests fail and show up as blocked connections. Setting CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 alongside the gateway variables turns them off, at the cost of auto-updates, so plan another update path.
The fast mode availability check still calls api.anthropic.com rather than the gateway base URL, and it does honour a configured HTTP proxy — so where a network block is the cause, an allowlist entry for that host in the proxy is the fix.
FAQ
What is a Claude Code proxy?
The term covers two different things: an LLM gateway that serves model requests, set with ANTHROPIC_BASE_URL and a credential; and a corporate HTTP proxy that traffic is routed through, set with HTTPS_PROXY. Only the first changes where your requests are answered.
Which environment variables configure a proxy in Claude Code?
For a gateway: ANTHROPIC_BASE_URL plus ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY, optionally ANTHROPIC_CUSTOM_HEADERS. For a network proxy: HTTP_PROXY, HTTPS_PROXY, NO_PROXY, plus NODE_EXTRA_CA_CERTS and the CLAUDE_CODE_CLIENT_CERT family when certificates are involved.
Should ANTHROPIC_BASE_URL include /v1?
No. The client appends /v1/messages itself, so a base URL ending in /v1 produces a doubled path and a 404. Set the origin only.
Does Claude Code support SOCKS proxies?
No. The documentation states SOCKS proxies are not supported. Use an HTTP or HTTPS proxy, or route through a gateway.
Why does my proxy setting have no effect?
Most often the variable did not reach the session: environment variables are read at startup, so a running session will not pick up a later shell change; a lowercase https_proxy elsewhere in your profile may be winning; or the value is in a shell export that a background agent's supervisor never inherited. Run /status and check the Proxy and Anthropic base URL rows before changing anything else.
Can I put the proxy and gateway settings in settings.json?
Yes — every variable on this page can go in the env block of a settings file, and that is the only form that reliably reaches background agents. Keep credentials in ~/.claude/settings.json or an uncommitted .claude/settings.local.json, never in a project's committed settings file.
ROIBest AI serves the Messages API shape at an Anthropic-compatible endpoint, so connecting Claude Code to it is the Route 1 configuration above — a base URL and a credential, placed in whichever layer suits how permanent the setup is.