[BUG] Can't use claude behind tunnel proxy
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: <!-- output of
claude --version--> 1.0.27 (Claude Code) - Operating System: <!-- e.g. macOS 14.3, Windows 11, Ubuntu 22.04 --> macOS 14.6.1
- Terminal: <!-- e.g. iTerm2, Terminal App --> Warp, Terminal(native)
Bug Description
<!-- A clear and concise description of the bug -->
❯ claude
╭──────────────────────────╮
│ ✻ Welcome to Claude Code │
╰──────────────────────────╯
Unable to connect to Anthropic services
Failed to connect to console.anthropic.com: ERR_BAD_REQUEST
Please check your internet connection and network settings.
Note: Claude Code might not be available in your country. Check supported countries at https://anthropic.com/supported-countries
<details>
<summary>this is debug output</summary>
╭──────────────────────────╮
│ ✻ Welcome to Claude Code │
╰──────────────────────────╯
follow-redirects options {
maxRedirects: 21,
maxBodyLength: Infinity,
protocol: 'https:',
path: '/api/hello',
method: 'GET',
headers: [Object: null prototype] {
Accept: 'application/json, text/plain, */*',
'User-Agent': 'claude-cli/1.0.27 (external, cli)',
'Accept-Encoding': 'gzip, compress, deflate, br'
},
agents: {
http: undefined,
https: bd1 {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
options: [Object],
requests: [Object: null prototype] {},
sockets: [Object: null prototype] {},
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 0,
proxy: URL {},
proxyHeaders: {},
connectOpts: [Object],
Symbol(shapeMode): false,
Symbol(kCapture): false,
Symbol(AgentBaseInternalState): {}
}
},
auth: undefined,
family: undefined,
beforeRedirect: [Function: mz9],
beforeRedirects: { proxy: [Function: G] },
hostname: 'api.anthropic.com',
port: '',
agent: bd1 {
_events: [Object: null prototype] {
free: [Function (anonymous)],
newListener: [Function: maybeEnableKeylog]
},
_eventsCount: 2,
_maxListeners: undefined,
options: { path: undefined },
requests: [Object: null prototype] {},
sockets: [Object: null prototype] {},
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 0,
proxy: URL {
href: 'http://127.0.0.1:8080/',
origin: 'http://127.0.0.1:8080',
protocol: 'http:',
username: '',
password: '',
host: '127.0.0.1:8080',
hostname: '127.0.0.1',
port: '8080',
pathname: '/',
search: '',
searchParams: URLSearchParams {},
hash: ''
},
proxyHeaders: {},
connectOpts: { ALPNProtocols: [Array], host: '127.0.0.1', port: 8080 },
Symbol(shapeMode): false,
Symbol(kCapture): false,
Symbol(AgentBaseInternalState): {}
},
nativeProtocols: {
'http:': {
_connectionListener: [Function: connectionListener],
METHODS: [Array],
STATUS_CODES: [Object],
Agent: [Function],
ClientRequest: [Function: ClientRequest],
IncomingMessage: [Function: IncomingMessage],
OutgoingMessage: [Function: OutgoingMessage],
Server: [Function: Server],
ServerResponse: [Function: ServerResponse],
createServer: [Function: createServer],
validateHeaderName: [Function],
validateHeaderValue: [Function],
get: [Function: get],
request: [Function: request],
setMaxIdleHTTPParsers: [Function: setMaxIdleHTTPParsers],
maxHeaderSize: [Getter],
globalAgent: [Getter/Setter],
WebSocket: [Getter],
CloseEvent: [Getter],
MessageEvent: [Getter]
},
'https:': {
Agent: [Function: Agent],
globalAgent: [Agent],
Server: [Function: Server],
createServer: [Function: createServer],
get: [Function: get],
request: [Function: request]
}
}
} +0ms
follow-redirects options {
maxRedirects: 21,
maxBodyLength: Infinity,
protocol: 'https:',
path: '/v1/oauth/hello',
method: 'GET',
headers: [Object: null prototype] {
Accept: 'application/json, text/plain, */*',
'User-Agent': 'claude-cli/1.0.27 (external, cli)',
'Accept-Encoding': 'gzip, compress, deflate, br'
},
agents: {
http: undefined,
https: bd1 {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
options: [Object],
requests: [Object: null prototype] {},
sockets: [Object: null prototype],
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 0,
proxy: URL {},
proxyHeaders: {},
connectOpts: [Object],
Symbol(shapeMode): false,
Symbol(kCapture): false,
Symbol(AgentBaseInternalState): {}
}
},
auth: undefined,
family: undefined,
beforeRedirect: [Function: mz9],
beforeRedirects: { proxy: [Function: G] },
hostname: 'console.anthropic.com',
port: '',
agent: bd1 {
_events: [Object: null prototype] {
free: [Function (anonymous)],
newListener: [Function: maybeEnableKeylog]
},
_eventsCount: 2,
_maxListeners: undefined,
options: { path: undefined },
requests: [Object: null prototype] {},
sockets: [Object: null prototype] {
'api.anthropic.com:443:::::::::::::::::::::': []
},
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 0,
proxy: URL {
href: 'http://127.0.0.1:8080/',
origin: 'http://127.0.0.1:8080',
protocol: 'http:',
username: '',
password: '',
host: '127.0.0.1:8080',
hostname: '127.0.0.1',
port: '8080',
pathname: '/',
search: '',
searchParams: URLSearchParams {},
hash: ''
},
proxyHeaders: {},
connectOpts: { ALPNProtocols: [Array], host: '127.0.0.1', port: 8080 },
Symbol(shapeMode): false,
Symbol(kCapture): false,
Symbol(AgentBaseInternalState): {}
},
nativeProtocols: {
'http:': {
_connectionListener: [Function: connectionListener],
METHODS: [Array],
STATUS_CODES: [Object],
Agent: [Function],
ClientRequest: [Function: ClientRequest],
IncomingMessage: [Function: IncomingMessage],
OutgoingMessage: [Function: OutgoingMessage],
Server: [Function: Server],
ServerResponse: [Function: ServerResponse],
createServer: [Function: createServer],
validateHeaderName: [Function],
validateHeaderValue: [Function],
get: [Function: get],
request: [Function: request],
setMaxIdleHTTPParsers: [Function: setMaxIdleHTTPParsers],
maxHeaderSize: [Getter],
globalAgent: [Getter/Setter],
WebSocket: [Getter],
CloseEvent: [Getter],
MessageEvent: [Getter]
},
'https:': {
Agent: [Function: Agent],
globalAgent: [Agent],
Server: [Function: Server],
createServer: [Function: createServer],
get: [Function: get],
request: [Function: request]
}
}
} +3ms
https-proxy-agent Creating `net.Socket`: { ALPNProtocols: [ 'http/1.1' ], host: '127.0.0.1', port: 8080 } +125ms
https-proxy-agent Creating `net.Socket`: { ALPNProtocols: [ 'http/1.1' ], host: '127.0.0.1', port: 8080 } +1ms
╭──────────────────────────╮
│ ✻ Welcome to Claude Code │
╰──────────────────────────╯
Unable to connect to Anthropic services
Failed to connect to console.anthropic.com: ERR_BAD_REQUEST
Please check your internet connection and network settings.
Note: Claude Code might not be available in your country. Check supported countries at https://anthropic.com/supported-countries
</details>
I captured the network traffic and noticed that the request to https://api.anthropic.com/api/hello succeeded, but the request to https://console.anthropic.com/v1/oauth/hello returned a 403 Forbidden error, likely triggered by Cloudflare's bot protection. See the network log below.
<details>
<summary>https://console.anthropic.com/v1/oauth/hello network log</summary>
GET https://console.anthropic.com/v1/oauth/hello
Accept: application/json, text/plain, */*
User-Agent: claude-cli/1.0.27 (external, cli)
Accept-Encoding: gzip, compress, deflate, br
Host: console.anthropic.com
Connection: close
<< 403 Forbidden 4.4k
Date: Wed, 18 Jun 2025 12:27:04 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
accept-ch: Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA
cf-mitigated: challenge
critical-ch: Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA
cross-origin-embedder-policy: require-corp
cross-origin-opener-policy: same-origin
cross-origin-resource-policy: same-origin
origin-agent-cluster: ?1
permissions-policy: accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()
referrer-policy: same-origin
server-timing: chlray;desc="******"
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Set-Cookie: __cf_bm=*******; path=/; expires=******; domain=.console.anthropic.com; HttpOnly; Secure; SameSite=None
Vary: Accept-Encoding
Server: cloudflare
CF-RAY: *******
Content-Encoding: br
alt-svc: h3=":443"; ma=86400
<some html>
</details>
<details>
<summary>https://api.anthropic.com/api/hello network log</summary>
GET https://api.anthropic.com/api/hello
Accept: application/json, text/plain, */*
User-Agent: claude-cli/1.0.27 (external, cli)
Accept-Encoding: gzip, compress, deflate, br
Host: api.anthropic.com
Connection: close
<< 200 OK 19b
Date: Wed, 18 Jun 2025 12:27:04 GMT
Content-Type: application/json
Content-Length: 19
Connection: close
request-id: *****
strict-transport-security: max-age=31536000; includeSubDomains; preload
via: 1.1 google
cf-cache-status: DYNAMIC
X-Robots-Tag: none
Server: cloudflare
CF-RAY: *******-SIN
{
"message": "hello"
}
</details>
Also, I noticed that the claude client is reporting an event named tengu_preflight_check_failed to https://statsig.anthropic.com. I'm not sure what it means, but hopefully it helps you identify the issue.
<details>
<summary>event request body</summary>
{
"events": [
{
"eventName": "tengu_preflight_check_failed",
"metadata": {
"isConnectivityError": false,
"hasErrorMessage": true,
"model": "claude-sonnet-4-20250514",
"sessionId": "*******",
"userType": "external",
"betas": "claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
"env": "{\"platform\":\"darwin\",\"nodeVersion\":\"v24.1.0\",\"terminal\":\"WarpTerminal\",\"packageManagers\":\"npm\",\"runtimes\":\"node\",\"isRunningWithBun\":false,\"isCi\":false,\"isClaubbit\":false,\"isGithubAction\":false,\"isClaudeCodeAction\":false,\"isClaudeAiAuth\":false,\"version\":\"1.0.27\"}",
"entrypoint": "cli"
},
"user": {
"customIDs": {
"sessionId": "*******"
},
"userID": "********",
"appVersion": "1.0.27",
"custom": {
"userType": "external"
},
"statsigEnvironment": {
"tier": "production"
}
},
"time": 1000
}
],
"statsigMetadata": {
"sdkVersion": "3.12.1",
"sdkType": "javascript-client",
"stableID": "******",
"sessionID": "******",
"fallbackUrl": null
}
}
</details>
Steps to Reproduce
- <!-- First step -->
- <!-- Second step -->
- <!-- And so on... -->
Expected Behavior
<!-- What you expected to happen -->
Actual Behavior
<!-- What actually happened -->
Additional Context
<!-- Add any other context about the problem here, such as screenshots, logs, etc. -->
This issue has 14 comments on GitHub. Read the full discussion on GitHub ↗