curlは成功するのにClaude Codeが接続できない:まず同じプロトコルを試す

curlは成功するのにClaude Codeが失敗する原因を切り分けます。Ofoxを通じて、実際のプロトコル、認証、ベースURL、最小限のクライアントテストを比較します。

クリーム色のカードに描かれた黒インクの石橋、暖かみのあるグレーの背景、錆色のバーと「Claude Code」のタイトル。

curlではAPIリクエストが成功するのにClaude Codeでは失敗する場合、まず両者が同じ種類のリクエストを送っているか確認してください。OpenAI Chat Completionsへのリクエストが成功しても、確認できるのはそのルートと認証情報が機能したことだけです。Anthropic Messagesへのリクエスト、ストリーミング応答、あるいはClaude Codeを実行しているプロセスでも動作するとは限りません。

OfoxとClaude Haiku 5.5を使って、この違いを確認しました。モデルはChat Completions経由で応答しました。意図的に不一致にしたMessages URLではHTTP 401が返りました。正しいAnthropic互換ルートではREADYが返り、最小限のClaude Codeリクエストも完了しました。HTTPプローブでルートとプロトコルの組み合わせを正しくすると、応答が成功しました。Claude Codeのセッションが失敗する状況は再現していないため、これはクライアントの失敗を修正できる証拠ではなく、接続エラーがすべてベースURLの問題だと示すものでもありません。

このガイドは、API認証情報はすでに使えるものの、コーディングクライアントが失敗する理由を切り分けたい開発者向けです。プロバイダーを初めて設定する場合は、Claude Codeの設定ガイド(英語)を参照してください。ここでは、失敗している層を特定するまで、既存のプロジェクト設定を変更せずに進めます。

テストで実際に確認できたこと

テストではClaude Code 2.1.296、OfoxのモデルID anthropic/claude-haiku-5.5、短く機密情報を含まないプロンプトを使用しました。ここで示すのは個々のリクエストであり、可用性や速度のベンチマークではありません。

プローブリクエストまたは設定観測された結果
OpenAI互換のテキストリクエスト/v1/chat/completions、Bearer認証HTTP 200。要求したJSONが返された
意図的に不一致にしたMessagesリクエスト/v1/v1/messages、x-api-keyHTTP 401。応答ではBearer認証が要求された
Anthropic互換のテキストリクエスト/anthropic/v1/messages、x-api-keyHTTP 200。READY
最小限のClaude Code実行ベースURL /anthropic、モデルを明示、ツールを無効化終了コード0、is_error: false、結果はREADY

不一致のリクエストでは、誤ったパスと、そのルートには適さない認証方式を組み合わせていました。このテストではパスと認証方式を同時に変えているため、それぞれが失敗にどう影響したかは切り分けられません。特に、この401応答はAPIキー自体が無効だった証拠ではありません。同じ認証情報は、対応するルートでは機能しました。

クライアントは、名前空間付きのモデル識別子に対してunrecognized_model警告も出しましたが、リクエスト自体は完了しました。診断時にはこの警告を記録してください。応答の失敗と同一視したり、すべての機能がサポートされていると推測したりしないでください。このプローブではツールを無効にしており、コーディングのワークフロー、MCP、アカウントの切り替え、長時間のストリーミングセッションはテストしていません。

エンドポイント、本文、認証情報を一致させる

テストする組み合わせを整理してください。プロバイダー、ベースURL、最終的なパス、モデルID、認証ヘッダー、リクエスト本文の形式です。プロバイダー間でモデル名を流用する場合は、対応関係を確認せずに別プロバイダーの例へコピーしないでください。

クライアントの仕様このテストで使ったOfoxのURL本文の形式
OpenAI Chat Completionshttps://api.ofox.ai/v1/chat/completionsmodel、messages
Anthropic Messageshttps://api.ofox.ai/anthropic/v1/messagesmodel、messages、max_tokens
Claude CodeのベースURLhttps://api.ofox.ai/anthropicクライアントが操作用のパスを追加する

このAnthropic互換設定では、OpenAI SDKで使うベースURL https://api.ofox.ai/v1をそのまま流用せず、https://api.ofox.ai/anthropicを指定してください。また、プレフィックスを受け取るベースURL欄に、/v1/messagesまで含む完全なURLを貼り付けないでください。

Anthropicのゲートウェイに関するドキュメントでは、ゲートウェイの設定と、その背後にあるプロバイダーが区別されています。また、サードパーティのゲートウェイを経由する非Claudeモデルのサポートは保証されないことも明記されています。このテストではClaudeモデルを使用しています。別のモデルでテキストプローブが成功しても、Claude Codeとの完全な互換性が確認できたことにはなりません。

AnthropicのベースURLを示す、英語表示のOfox Haikuコード例

これは、10月12日に撮影した、公開されているOfoxのコード例インターフェースの実際の画像です。Anthropicルートとモデルを示していますが、CLIテストの結果を撮影したものではありません。

最小限のMessagesプローブを送る

通常のシークレット管理方法で設定した環境変数にキーを保管してください。キーをスクリーンショット、記事のコメント、コマンド履歴、共有する診断ファイルに含めないでください。以下のPOSIXシェルの例では、OFOX_API_KEYがすでに設定されているものとします。

curl --silent --show-error --fail-with-body \
  --connect-timeout 10 --max-time 45 \
  'https://api.ofox.ai/anthropic/v1/messages' \
  -H "x-api-key: $OFOX_API_KEY" \
  -H 'anthropic-version: 2023-06-01' \
  -H 'content-type: application/json' \
  --data '{"model":"anthropic/claude-haiku-5.5","max_tokens":64,"messages":[{"role":"user","content":"Reply with READY only."}]}'

成功と判断するには、contentにREADYというテキストブロックが含まれるMessagesの応答が必要です。HTTPの結果と本文を合わせて確認してください。HTMLのログインページ、空の成功レスポンス、エラーオブジェクトは、受け入れ可能なモデル応答ではありません。

コマンドが失敗した場合は、HTTPステータス、エラーの種類、取得できる場合はリクエストIDを保存してください。プロバイダーに問題を報告する際はリクエストIDを使い、認証ヘッダーや個人情報を含むプロンプトは含めないでください。接続タイムアウト、証明書エラー、HTTP 401はそれぞれ異なる層で発生するため、同じ対処をしてはいけません。

プロジェクトの処理をせずにクライアントを実行する

テストに使ったバージョンでは、--bareで最小限のクライアントモードを有効にし、--tools ""でテキストのみのプローブ中はツールを無効にします。バージョン固有のフラグを使う前に、ご自身の環境でclaude --helpを確認してください。

claude --version

(
  unset ANTHROPIC_AUTH_TOKEN
  export ANTHROPIC_BASE_URL='https://api.ofox.ai/anthropic'
  export ANTHROPIC_API_KEY="$OFOX_API_KEY"
  claude --bare -p 'Reply with READY only.' \
    --model 'anthropic/claude-haiku-5.5' \
    --tools '' --no-session-persistence --output-format json
)

括弧で囲んだ部分の環境変数の変更は、このプローブの実行中に限られます。テストは空の一時ディレクトリから行いました。この操作によってプロジェクト設定を書き換えたり、組織の制御を取り除いたりすることはありません。組織でプロバイダーが制限されている場合は、承認された接続先を使用してください。管理されたポリシーを回避するための手順ではありません。

合格とするには、終了ステータスが0で、is_error: falseとなり、期待した結果が返る必要があります。今回の実行では、プロセスの開始から終了まで2.64秒かかりました。CLIのコスト欄はOfoxの請求額と照合していません。ゲートウェイで確定した料金として使わないでください。期待どおりの応答が返っても、確認できたのはこの最小限の接続だけです。

2つのプローブの結果が一致しない場合

Messagesが成功してクライアントが失敗する場合は、プロセスの環境を比較してください。シェルとIDEから起動したプロセスでは、開始時の環境変数が異なることがあります。起動設定を修正したら、対象のクライアントを再起動し、実際に有効になっているプロバイダーとモデルを確認してください。環境変数を丸ごと出力してはいけません。キーが含まれている可能性があります。

次に、設定の適用範囲を調べます。Claude Codeの設定ガイドでは、ユーザー、プロジェクト、ローカル、管理者による設定が説明されています。最後に編集したファイルの値が必ず有効になると思い込まず、実際に適用されている値を確認してください。設定を変更する前にコピーを保存してください。失敗するのが特定のリポジトリだけなら、最初にグローバル設定を変えるのではなく、クリーンなプローブとそのリポジトリのプロジェクト設定を比較してください。

症状次に行う切り分けテスト避けること
HTTP 401または403ルート、認証情報の種類、プロバイダーのポリシーが一致しているか確認するルートを確認する前に、機能しているキーをローテーションする
モデルが見つからないという応答正確なIDを、そのプロバイダーで利用できるモデルと照合する製品の名称をAPI上の識別子として扱う
証明書またはプロキシのエラー対象プロセスの承認済みネットワーク設定を比較するTLS検証を無効にする
最小限の応答は成功するが、長いセッションは失敗するストリームの終了状況とタイムアウトの証拠を収集するテキストのみのプローブをストリーミングテストと呼ぶ
テキストは動くが、ツール呼び出しは失敗するツール呼び出しのリクエストと結果のプロトコルを別々に確認するテキストが成功しただけでモデルのせいにする
IDEだけで失敗する意図した環境変数でIDEを再起動し、設定を確認し直す無関係な複数のグローバル設定を一度に編集する

DeepSeekへの接続については、DeepSeek向けClaude Code設定記事で、別のプロバイダー仕様を解説しています。その直接のエンドポイントを、このOfoxの例と混同しないでください。

段階的に実際の作業へ戻す

最小限のプローブが成功したら、通常のプロジェクト、使用するモデル、無害な読み取り専用のツールリクエスト、通常のワークフローの順に、レイヤーを一つずつ戻してください。各段階で、期待した操作と使用記録を確認します。後から失敗したときに変更点を絞り込めるよう、成功したプローブを基準として残してください。

有用な報告には、クライアントのバージョン、オペレーティングシステム、プロバイダーのルート、機密情報を伏せたモデル設定、失敗した時刻、リクエストID、再現に必要な最小のプロンプトを含めます。どの確認に成功したかも、分けて記載してください。「curlは動く」という情報が役立つ証拠になるのは、どのプロトコルをテストしたのかが分かる場合だけです。

よくある質問

curlリクエストが成功すれば、Claude Codeも正しく設定できていると分かりますか?
いいえ。そのリクエストが成功したことしか分かりません。クライアントにも当てはまると判断する前に、実際のパス、認証方式、モデル、プロセスの環境を比較してください。
接続エラーを直すために、証明書の検証を無効にすべきですか?
いいえ。証明書チェーンと、承認済みのプロキシ設定を調べてください。検証を無効にすると問題が隠れ、接続の安全性が損なわれます。
このクライアントテストで、ツール呼び出しやコーディングも動作すると確認できますか?
いいえ。このプローブでは意図的にツールを無効にしています。この設定に頼る前に、読み取り専用のツール操作と、実際のプロジェクトを想定したタスクを別々に検証してください。