claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[BUG] Can't use claude behind tunnel proxy

Open defi-failure opened this issue 6 months ago • 9 comments

Environment

  • Platform (select one):
    • [x] Anthropic API
    • [ ] AWS Bedrock
    • [ ] Google Vertex AI
    • [ ] Other:
  • Claude CLI version: 1.0.27 (Claude Code)
  • Operating System: macOS 14.6.1
  • Terminal: Warp, Terminal(native)

Bug Description

❯ 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
this is debug output
╭──────────────────────────╮
│ ✻ 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

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.

`https://console.anthropic.com/v1/oauth/hello` network log
 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>
`https://api.anthropic.com/api/hello` network log
 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"
    }

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.

event request body
{
  "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
  }
}

Steps to Reproduce

Expected Behavior

Actual Behavior

Additional Context

defi-failure avatar Jun 18 '25 12:06 defi-failure

same issue

alanxmay avatar Jun 19 '25 08:06 alanxmay

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

ainightf avatar Jun 20 '25 12:06 ainightf

You can use this. https://github.com/yunfengsay/command-proxy-wrapper

yunfengsay avatar Jun 20 '25 15:06 yunfengsay

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 avatar Jun 20 '25 16:06 defi-failure

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.

defi-failure avatar Jun 20 '25 17:06 defi-failure

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

  2.  export NODE_OPTIONS="--dns-result-order=ipv4first --max-http-header-size=32768"
     claude
    
  3. rm -f ~/.claude.json

  4. set a default api-key

finally, it works

Image

bromiao avatar Jun 21 '25 17:06 bromiao

same issue

leon-titan avatar Jun 23 '25 03:06 leon-titan

same issue 2

Explorer1092 avatar Jun 24 '25 07:06 Explorer1092

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

SamPeng87 avatar Jun 27 '25 04:06 SamPeng87

same

auntan avatar Jul 04 '25 15:07 auntan

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

Lemou-Memo avatar Jul 14 '25 02:07 Lemou-Memo

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?

semochkinalex avatar Jul 28 '25 17:07 semochkinalex

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.

ollie-anthropic avatar Aug 22 '25 19:08 ollie-anthropic

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.

github-actions[bot] avatar Aug 31 '25 14:08 github-actions[bot]