Skip to content

Network configuration

Run Claude Code behind corporate proxies, TLS inspection and mTLS, tune streaming watchdogs, and know exactly which hosts to allowlist.

Corporate networks are where most "Claude Code won't connect" tickets come from. This page covers the knobs that matter: proxies, certificate trust, client certificates, the timers that detect dead streams, and the full list of hosts your firewall needs to let through.

Everything here is configured with environment variables, and all of them can live in the env block of a settings file instead of your shell. Shell exports are read once at startup; changing them later does not affect a running session.

Proxies

Claude Code honours the usual proxy variables:

export HTTPS_PROXY=http://proxy.corp.example:3128
export HTTP_PROXY=http://proxy.corp.example:3128          # only if there is no HTTPS proxy
export NO_PROXY="localhost,.corp.example,10.20.0.0/16"   # comma or space separated; "*" bypasses everything

Lowercase names work too. Claude Code takes the first one set, in the order https_proxy, HTTPS_PROXY, http_proxy, HTTP_PROXY. WebSocket connections to localhost, ::1 and 127.0.0.0/8 never go via the proxy, so you do not need loopback entries in NO_PROXY.

A few limits:

  • No SOCKS. Only HTTP and HTTPS proxies are supported.
  • Basic auth goes in the URL, as in http://svc-claude:secret@proxy.corp.example:3128. Keep the password out of scripts; load it from a secret store.
  • NTLM, Kerberos and friends are not supported directly. An LLM gateway that speaks your proxy's authentication scheme is the usual workaround.

In Claude Desktop sessions where the app manages the provider connection (see mTLS below for which those are), the proxy variables are read only from managed settings and ~/.claude/settings.json.

Certificate trust

By default Claude Code trusts two sets of roots: the Mozilla bundle it ships with, and your operating system's trust store. Reading the OS store needs a runtime with tls.getCACertificates, which the native installer always has; npm installs need Node 22.15 or later, otherwise only the bundled roots and NODE_EXTRA_CA_CERTS apply.

That means a TLS-inspecting proxy usually just works, as long as its root certificate is in the OS store. If you need more control:

VariableEffect
CLAUDE_CODE_CERT_STORE=bundledTrust only the shipped Mozilla roots
CLAUDE_CODE_CERT_STORE=systemTrust only the OS store
CLAUDE_CODE_CERT_STORE=bundled,systemThe default
NODE_EXTRA_CA_CERTS=/etc/pki/corp-root.pemAdd your own CA bundle on top
CLAUDE_CODE_GZIP_REQUEST_BODIES=0Stop compressing request bodies, for inspection proxies that mangle gzip

CLAUDE_CODE_CERT_STORE has no dedicated settings key; set it under env or in the process environment.

Client certificates (mTLS)

If your gateway or proxy demands a client certificate:

export CLAUDE_CODE_CLIENT_CERT=/etc/claude/tls/client.crt
export CLAUDE_CODE_CLIENT_KEY=/etc/claude/tls/client.key
export CLAUDE_CODE_CLIENT_KEY_PASSPHRASE="..."   # only for an encrypted key

The files are read at startup and again whenever settings are applied (for example when an admin changes managed env mid-session).

Rotating certificates

Replace the files at the same paths; no restart is needed. From v2.1.232, when a request fails at the connection level (a reset or TLS handshake failure), Claude Code re-reads both files and retries with the new pair. Some details:

  • Nothing happens the moment you swap the files. The new pair is used on the retry after a qualifying failure, or after the next settings application, whichever comes first.
  • If the gateway completes the handshake and returns an HTTP error instead of rejecting the connection, there is no re-read; the new pair loads at the next settings application or restart.
  • If Claude Code reads a half-written rotation (certificate and key that do not match), it keeps the previous pair and tries again next failure.
  • OpenTelemetry exporters keep the certificate they loaded first, so restart for rotated certs to reach your collector.
  • CLAUDE_CODE_DISABLE_MTLS_RELOAD_ON_STALE_CONNECTION=1 turns off the failure-triggered re-read.

To confirm a rotation, run with debug logging and search the log for the line that starts Stale connection and mentions reloaded rotated mTLS client material. A missing line is not proof of failure, because pickups during settings application are not logged. Always rotate before the old pair expires so a restart does not load an expired one.

Where these variables are ignored

In cloud sessions, the host manages the API connection, so these keys are ignored when they come from a settings file env block (each is noted in the debug log): CLAUDE_CODE_CLIENT_CERT, CLAUDE_CODE_CLIENT_KEY, CLAUDE_CODE_CLIENT_KEY_PASSPHRASE, NODE_EXTRA_CA_CERTS, NODE_TLS_REJECT_UNAUTHORIZED and CLAUDE_CODE_OAUTH_SCOPES.

In Claude Desktop sessions where the app owns the connection (the Code tab on a third-party provider, and Cowork), those variables and the proxy variables are read only from managed settings and ~/.claude/settings.json, never from a repository's own settings. That stops a cloned repo redirecting traffic for a session whose credentials come from the app. Local, SSH and WSL Code tab sessions signed in through claude.ai behave like the terminal and read every scope. (Before v2.1.217, these variables were ignored in every settings file whenever the app owned the connection.)

Checking your setup

Most of these values are not validated when read, so a typo usually surfaces as a connection or certificate error later. The exception is the proxy URL: if it cannot be parsed (missing http://, say), Claude Code refuses to start and names the variable.

To see what loaded before you send anything:

claude --debug-file /tmp/claude-net.log

(Plain --debug writes to ~/.claude/debug/<session-id>.txt.) Look for lines such as:

CA certs: Appended extra certificates from NODE_EXTRA_CA_CERTS (/etc/pki/corp-root.pem)
mTLS: Loaded client certificate from CLAUDE_CODE_CLIENT_CERT
mTLS: Loaded client key from CLAUDE_CODE_CLIENT_KEY

Failures show as Failed to read or Failed to load lines with a reason.

In /status:

  • Proxy shows the active URL, or flags an unparseable one as invalid and ignored.
  • mTLS client cert and mTLS client key appear only if the files loaded.
  • Additional CA cert(s) shows the NODE_EXTRA_CA_CERTS path but does not prove the file loaded; check the debug log for that.

Background agents

Background agents run under a per-user supervisor process that starts on demand and outlives your terminal. It inherits the environment of whichever shell started it first, and an OS-installed supervisor gets no shell environment at all. So a proxy or CA path exported only in .zshrc reaches background agents some of the time, which is the worst kind of bug.

Put network variables in ~/.claude/settings.json or managed settings. Settings are the only thing that reliably reaches every background session.

The same applies to corporate launchers. The supervisor starts Claude Code from a fixed path, not via PATH, so a wrapper earlier on PATH is bypassed. Use the processWrapper setting (or CLAUDE_CODE_PROCESS_WRAPPER, which wins if both are set, delivered through settings, not the shell). See corporate launcher. After changing it, run claude daemon stop --any so the next background session starts a supervisor with the new configuration (an installed service takes claude daemon stop without --any).

Streaming watchdogs

Four independent timers abort a model response that goes quiet, so a dead connection fails and retries rather than hanging forever:

TimerFires whenApplies toDefault
First-byte deadlineNo response headers after sendingDirect Anthropic API and Claude Platform on AWS (including via an HTTPS proxy), but not when a gateway base URL is set. Opt-in on Bedrock; never on Vertex AI or Foundry.180 s on the direct API, 300 s elsewhere, plus 1 s per 32 KB of request body
Event-level watchdogNo response events parseAll providers. Where the byte watchdog runs (except Bedrock), incoming bytes also reset it, for up to about five minutes without an event.300 s
Byte-level watchdogNo bytes at all, keep-alives includedDirect API, Claude Platform on AWS and gateway connections including a custom ANTHROPIC_BASE_URL. Opt-in on Bedrock; never on Vertex AI or Foundry.180 s on the direct API; through a custom base URL, 180 s with feature flags fetched, 300 s without; 300 s elsewhere
Body idle timeoutNo bytes for five minutesProviders other than the direct API, Claude Platform on AWS and opted-in Bedrock, unless API_FORCE_IDLE_TIMEOUT says otherwise5 min

CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1 turns on the byte watchdog for Bedrock's event-stream responses, replacing the body idle timeout there. CLAUDE_STREAM_IDLE_TIMEOUT_MS then also governs Bedrock silence. Bytes still do not reset the event watchdog on Bedrock, and with debug logging each stream logs a line beginning wire-heartbeat: _chunkTimes absent.

Tuning variables (full details in environment variables):

VariableWhat it does
CLAUDE_ENABLE_STREAM_WATCHDOG1/0 forces the event watchdog on or off where it applies
CLAUDE_ENABLE_BYTE_WATCHDOG1/0 forces the byte watchdog on or off where it applies; 0 also disables the first-byte deadline
CLAUDE_STREAM_IDLE_TIMEOUT_MSTimeout for both watchdogs. Raised to at least 5 minutes; capped at 30 minutes for the byte watchdog
CLAUDE_BYTE_STREAM_IDLE_TIMEOUT_MSByte watchdog only, clamped to 10 s to 30 min; beats the previous variable
CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MSFirst-byte deadline directly; unset, it follows the byte watchdog timeout
API_FORCE_IDLE_TIMEOUT0 disables the body idle timeout, 1 enables it everywhere. Watchdogs run regardless, so raise them too if streams legitimately pause

When a watchdog fires mid-stream, Claude Code may retry, end the turn with an error, keep what arrived and show an incomplete-response notice, or end normally, depending on how far the response got. In headless sessions and subagents it may first ask Claude to continue the cut-off response. A first-byte abort has no partial output, so it simply re-sends or fails. The errors page covers each case.

Hosts to allowlist

For the standalone CLI:

HostUsed for
api.anthropic.comModel requests, the WebFetch domain safety check, feature flags, telemetry event logging
claude.aiclaude.ai account authentication
claude.comThe browser sign-in page (redirects to claude.ai); some pre-approved documentation fetches
platform.claude.comConsole authentication, and OAuth token exchange, refresh and revocation for claude.ai accounts too
mcp-proxy.anthropic.comclaude.ai MCP connectors. Disable with ENABLE_CLAUDEAI_MCP_SERVERS=false or disableClaudeAiConnectors
downloads.claude.aiPlugin executables, native installer, auto-updater and version checks
storage.googleapis.comPlugin install counts and metadata in /plugin; the installer and updater before v2.1.116
registry.npmjs.orgnpm-source plugins and their dependencies, npx MCP servers, and npm or bun installs of Claude Code
bridge.claudeusercontent.comThe Claude in Chrome WebSocket bridge
*.frame.claudeusercontent.comReading artifact content. Drop with "enableArtifact": false or CLAUDE_CODE_DISABLE_ARTIFACT=1
github.comCloning plugin marketplaces and plugins, including Anthropic's. CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1 forces HTTPS for owner/repo sources
raw.githubusercontent.comThe /release-notes changelog (also fetched in the background on the first interactive start after an update)
*-review.googlesource.comGerrit change lookup for trusted googlesource.com checkouts in Desktop Code tab sessions; optional
http-intake.logs.us5.datadoghq.comOperational telemetry, direct Anthropic API only; optional
browser-intake-us5-datadoghq.comOperational error reports, direct API only, when enabled server-side; optional
formulae.brew.shUpdate checks on Homebrew installs only
code.claude.comDocumentation lookups by the built-in guide agent and pre-approved WebFetch; blocking it only affects those

Notes for building the allowlist:

  • If you install via npm or distribute the binary yourself, you do not need the installer and updater uses of downloads.claude.ai, but npm and bun installs need registry.npmjs.org unless you mirror it.
  • CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC turns off both Datadog hosts. Third-party provider sessions never send to them.
  • On Bedrock, Vertex AI, Foundry or a signed-in Claude apps gateway, model and auth traffic goes to your provider instead. WebFetch still calls api.anthropic.com for its safety check unless you set skipWebFetchPreflight: true.
  • Behind an ANTHROPIC_BASE_URL gateway, the fast mode availability check still calls api.anthropic.com (honouring your HTTP proxy). A blocked host and a gateway credential Anthropic rejects both show as a connectivity error; only the first is fixed by allowlisting.

IP allowlisting for Claude

If your organisation uses IP allowlisting for Claude, send bridge.claudeusercontent.com out through the same proxy egress as claude.ai and api.anthropic.com (same Zscaler app segment or Netskope steering policy, for example). Connections to it are checked against your allowlist by source address, so if it egresses elsewhere the Chrome extension fails while everything else works. Only add a proxy's egress address to your allowlist if that address is dedicated to you; a shared range admits the vendor's other customers.

GitHub IP restrictions

Cloud sessions in Anthropic-hosted environments and Code Review reach your repositories from Anthropic infrastructure. Self-hosted environment sessions connect from inside your network unless their runner uses the Anthropic git proxy.

For GitHub Enterprise Cloud with IP restrictions, enable IP allow list inheritance for installed GitHub Apps and add Anthropic's published outbound IP addresses; inheritance only covers requests the app makes as an installation, not on behalf of users. For GitHub Enterprise Server behind a firewall, allowlist the same outbound addresses so hosted sessions, the repository picker and git-proxy runners can reach it.

Desktop and the browser

The table above is for the CLI. Claude Desktop and claude.ai also load code and content from additional CDN hosts such as assets-proxy.anthropic.com and other *.claudeusercontent.com origins; blocking them gives a blank page rather than an error. Interactive widgets such as MCP Apps load from *.claudemcpcontent.com (keep the wildcard).

Artifacts may request fonts.googleapis.com and fonts.gstatic.com (optional; fallback fonts are used) and JavaScript libraries from cdnjs.cloudflare.com, cdn.jsdelivr.net, cdn.tailwindcss.com, code.jquery.com and unpkg.com (no fallback). If you block any of these, reject quickly rather than silently dropping, so pages do not hang waiting.