OAuth login fails from Hetzner VPS — Cloudflare JS challenge blocks token exchange

Resolved 💬 7 comments Opened Jan 29, 2026 by arthurworsley Closed Apr 2, 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?

The OAuth login flow fails at the token exchange step when running Claude Code on a Hetzner Cloud VPS. Cloudflare issues a JavaScript challenge that the CLI cannot complete, blocking the outbound HTTPS request.

Steps:

  1. SSH into VPS, run claude login
  2. CLI displays authorization URL
  3. Open URL in local browser, sign in, authorize successfully
  4. Receive authorization code, paste it back into the CLI
  5. CLI fails with: "OAuth error: Request failed with status code 400"

Root cause — Cloudflare blocks claude.ai from the VPS:

$ curl -sS -D - -o /dev/null https://claude.ai/
HTTP/2 403
cf-mitigated: challenge
server: cloudflare

The cf-mitigated: challenge header confirms a JS challenge is being issued. The CLI cannot complete this challenge, so the token exchange request fails.

  • Both IPv4 and IPv6 return 403
  • console.anthropic.com returns HTTP 302 (OK) — only claude.ai is blocked
  • Previously authenticated successfully as root on the same server

What Should Happen?

The OAuth token exchange should succeed. The token exchange endpoint should be exempt from Cloudflare bot challenges for CLI/API clients (e.g. by User-Agent or endpoint path), or an alternative headless authentication method should be provided.

Error Messages/Logs

OAuth error: Request failed with status code 400

Full response headers from VPS:

HTTP/2 403
date: Thu, 29 Jan 2026 11:28:40 GMT
content-type: text/html; charset=UTF-8
cf-mitigated: challenge
server: cloudflare

Steps to Reproduce

  1. Provision a Hetzner Cloud VPS (any plan, ARM64 or x86)
  2. Install Claude Code via npm
  3. Run claude login
  4. Complete the browser authorization, paste code back
  5. Observe "OAuth error: Request failed with status code 400"

Claude Model

Claude Pro (subscription)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

Unknown — previously worked as root on same server

Claude Code Version

v2.1.23

Platform

Claude.ai (Pro subscription)

Operating System

Ubuntu 24.04.3 LTS (Noble Numbat), ARM64, Hetzner Cloud

Terminal/Shell

Bash via SSH

Additional Information

  • VPS provider: Hetzner Cloud (ARM64)
  • Hetzner is a major European cloud provider — this likely affects all Hetzner customers
  • Related issues: #10719, #19078, #9534, #5767
  • Workaround attempted: copying OAuth tokens from macOS Keychain to Linux gnome-keyring — works but breaks when token refresh also hits Cloudflare

View original on GitHub ↗

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