[BUG] OAuth token refresh uses HTTP GET instead of CONNECT tunnel — breaks forward proxy environments

Resolved 💬 4 comments Opened Mar 12, 2026 by nsepetys Closed Apr 10, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code's OAuth client sends token refresh/profile requests as plain HTTP GET through the proxy instead of using a CONNECT tunnel. This causes forward proxies (e.g., Squid) to return 503 Service Unavailable.

The inference API (api.anthropic.com:443) correctly uses CONNECT tunnels and works fine through the same proxy. Only the OAuth endpoints use the wrong transport method.

Once the initial OAuth token expires mid-session, all subsequent API calls fail silently. Claude Code continues running (consuming time/resources) but produces no useful output — in our case, a session completed with 0 tool calls after 224 consecutive failed OAuth refresh attempts.

What Should Happen?

OAuth token refresh requests to api.anthropic.com should use CONNECT tunnels (the same way the inference API does), allowing the proxy to establish an encrypted tunnel to the destination.

# Expected (how inference API already works correctly):
TCP_TUNNEL/200 CONNECT api.anthropic.com:443

Error Messages/Logs

# Squid access.log — OAuth refresh failures (repeated 224 times in one session):
1741... TCP_MISS_ABORTED/503 0 GET https://api.anthropic.com/api/oauth/profile
1741... TCP_MISS_ABORTED/503 0 GET https://api.anthropic.com/api/oauth/profile
1741... TCP_MISS_ABORTED/503 0 GET https://api.anthropic.com/api/oauth/profile
... (224 total failures)

# For comparison — inference API in the SAME session works fine via CONNECT:
1741... TCP_TUNNEL/200 ... CONNECT api.anthropic.com:443

Steps to Reproduce

  1. Run Claude Code inside a Docker container with all traffic routed through a forward proxy (Squid) via HTTP_PROXY and HTTPS_PROXY environment variables
  2. Configure the proxy to allow *.anthropic.com and *.claude.ai domains
  3. Authenticate via OAuth — this works initially (the OAuth flow itself uses CONNECT correctly)
  4. Start a long-running autonomous session (e.g., claude --dangerously-skip-permissions)
  5. Wait for the OAuth token to expire mid-session
  6. Observe: Claude Code attempts to refresh the token via GET https://api.anthropic.com/api/oauth/profile instead of CONNECT api.anthropic.com:443 — the proxy returns 503 on every attempt
  7. The session silently dies — Claude Code continues running but cannot make any API calls

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.74 (also reproduced on 2.0.75)

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

Workaround

Adding api.anthropic.com to NO_PROXY bypasses the proxy for OAuth calls:

environment:
  NO_PROXY: localhost,127.0.0.1,api.anthropic.com

This works but is undesirable in security-sensitive environments where all traffic must be auditable through the proxy.

Root Cause Hypothesis

The OAuth HTTP client (likely a different library or config path than the inference client) is not configured to use CONNECT tunnels for HTTPS URLs when an HTTP proxy is set. The inference client correctly uses CONNECT, suggesting a configuration inconsistency between the two HTTP clients within Claude Code.

Impact

  • Session death: Once the token expires, the agent cannot recover
  • Silent failure: Session appears to run but produces 0 tool calls / 0 output
  • Affects all forward proxy environments: Corporate proxies, Docker-based security wrappers, audit-trail proxies

Related Issues

  • #217 — Add HTTP Proxy support (closed/implemented — but OAuth client was apparently not covered)
  • #29367 — API unreachable from VM behind corporate NTLM proxy (different proxy type, possibly related root cause)

Environment Details

  • Proxy: Squid 6.x with domain whitelist (acl anthropic_api dstdomain .anthropic.com .claude.ai)
  • Docker setup: airlocked-agent — firewalled environment for running AI coding agents autonomously
  • Auth: OAuth (Pro subscription), tokens stored in named Docker volume

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗