[BUG] Can't use claude behind tunnel proxy

Status Fixed / completed
Maintainer reply ✓ Yes — ollie-anthropic
Activity 14 comments · opened Jun 18, 2025 · closed Aug 22, 2025
💡 Likely answer: A maintainer (ollie-anthropic, collaborator) responded on this thread — see the highlighted reply below.

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

  1. <!-- First step -->
  2. <!-- Second step -->
  3. <!-- 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. -->

View original on GitHub ↗

14 Comments

alanxmay · 1 year ago

same issue

ainightf · 1 year ago

I think it is your network.You can go to https://www.anthropic.com/supported-countries to see whick country claude support.I change to Janpan its ok

yunfengsay · 1 year ago
defi-failure · 1 year ago
You can use this. https://github.com/yunfengsay/command-proxy-wrapper

I'm using tunnel mode, this code might not work. The proxy configuration shown in the debug log is only for MITM proxy to capture network logs.

defi-failure · 1 year ago
I think it is your network.You can go to https://www.anthropic.com/supported-countries to see whick country claude support.I change to Janpan its ok

That could be the case, but I’m able to use the Claude API with curl in terminal through exactly same tunnel config, so I’m not entirely sure.

bromiao · 1 year ago

I try to send the debug message to claude, some commands were output like

export NODE_OPTIONS="--dns-result-order=ipv4first --max-http-header-size=32768"
claude

the steps:

  1. DEBUG=* claude
  1. ```

export NODE_OPTIONS="--dns-result-order=ipv4first --max-http-header-size=32768"
claude
```

  1. rm -f ~/.claude.json
  1. set a default api-key

finally, it works

<img width="787" alt="Image" src="https://github.com/user-attachments/assets/0bb48d5e-5148-4399-a769-a1962a5a6424" />

leon-titan · 1 year ago

same issue

Explorer1092 · 1 year ago

same issue 2

SamPeng87 · 1 year ago

I get that error.I think is cloudflare verify wait people.console.anthropic.com 403 is cloudflare verify.

auntan · 1 year ago

same

Lemou-Memo · 1 year ago
I think it is your network.You can go to https://www.anthropic.com/supported-countries to see whick country claude support.I change to Janpan its ok我认为是网络问题。你可以访问 https://www.anthropic.com/supported-countries 查看 Claude 支持的国家。我切换到日本后就好了

me too

semochkinalex · 1 year ago

same issue.

in russia, but using a netherlands VPN

when i write: curl checkip.amazonaws.com

I get a netherlands IP. It means I should have a non-blocked IP?

ollie-anthropic collaborator · 1 year ago

Hey, looks like this is an upstream problem via cloudflare's bot protection mechanisms. We have stricter policies for the OAuth endpoint. If you really need, you can use your API key for auth here, or try and change the country / vpn source.

github-actions[bot] · 12 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.