Claude API connection errorの原因と切り分け、Claude Codeの接続エラー対処
API connection errorはHTTPの応答が返る前に通信が途切れたときのエラー。Claude Codeの接続エラー表示の読み方と、VPN・ファイアウォール・プロキシの切り分け手順を書く。
API connection errorは「応答が返る前」の失敗
API connection errorは、Claude APIからHTTPの応答を受け取る前に通信が成立しなかったときのエラーです。サポート記事は、このエラーの多くが手元のファイアウォール・ネットワーク・VPNに起因すると案内しています。Anthropic側の障害を疑う前に、自分の経路を確かめる順序です。
SDKの側から見ると、この種の失敗は APIConnectionError として現れます。公式SDKの対応表では、HTTPステータスコードを持つ400・401・429・500以上のエラーと違い、ステータスコードの欄が「N/A」です。ステータスが無い。つまりサーバーから何も返っていません。
この違いが切り分けの出発点になります。
| 症状 | 応答は返ったか | 見る場所 |
|---|---|---|
APIConnectionError(ステータスなし) | 応答は返ったか返っていない | 見る場所VPN・ファイアウォール・プロキシ・DNS |
401 authentication_error | 応答は返ったか返った | 見る場所APIキーの状態 |
429 rate_limit_error | 応答は返ったか返った | 見る場所レート制限・利用上限 |
500 api_error / 529 overloaded_error | 応答は返ったか返った | 見る場所Anthropic側。バックオフして再試行 |
ステータスコードが付いたエラーは、通信自体は届いています。この記事が扱うのは一番上の行だけです。ステータスごとの対処はエラーハンドリングの記事にまとめています(Claude APIのエラーハンドリング設計)。
サポート記事が挙げる3つの対処
サポート記事の対処
- 1
ネットワーク制限の有無を確かめる
ファイアウォールやネットワーク制限が、Claude APIのエンドポイントへの接続を塞いでいないかを見ます。
- 2
接続を許可する設定に直す
塞いでいるルールがあれば、その接続を許可する内容へ変更します。
- 3
リクエストの間はVPNを使わない
VPN経由だと失敗する場合があるため、リクエストを送る間はVPNを外します。
解決しない場合は、ヘルプセンター右下のメッセージアイコン、またはConsoleの左下にある自分のイニシャルから「Get help」でサポートに連絡します。
試しやすいのは「VPNを外す → ネットワーク制限を疑う → 許可設定を入れる」の順です。VPNは切り替えるだけで結果が変わるので、最初の切り分けに向いています。以降の節で、それぞれの確かめ方を具体的に書きます。
手順1: 最小のリクエストで疎通を確かめる
アプリケーションのコードを疑う前に、同じマシン・同じネットワークから最小のリクエストを直接送ります。サポート記事の疎通確認は次の3段階です。
- Consoleにログインして、APIキーを作成する
- そのキーでテストリクエストを送る(公式のGetting startedに例がある)
- レスポンスのステータスコード・本文・エラーメッセージで成否を確かめる
Getting startedのcURLの例をもとにした確認コマンドは、次の形になります。通常のメッセージ作成リクエストなので、ごく小さくてもトークン課金は発生します。max_tokens を小さく絞ってあります。
export ANTHROPIC_API_KEY="sk-ant-..." # Consoleで作成したキー
curl -sS -m 15 https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-5-5",
"max_tokens": 16,
"messages": [{"role": "user", "content": "ping"}]
}' -i-m 15 は15秒で打ち切る指定、-i はレスポンスヘッダーも表示する指定です。結果は次のように読みます。
- JSONが返る: ステータスがいくつでも、Claude APIまで通信は届いています。この経路の接続に問題はありません。401が返ったならキーの問題、200ならその環境では正常です
- 接続エラーで終わる: 名前解決の失敗、接続拒否、タイムアウトなど、curl自身がメッセージを出して終了します。応答が返っていないので、経路上の遮断を疑います
- プロキシ由来のHTML(認証画面やブロック通知)が返る: 社内プロキシやセキュリティ製品が途中で応答している状態です。ヘッダーに
request-idが無いなら、Claude APIには届いていません
最後の判定は、公式の「すべての応答に request-id ヘッダーが付く」という仕様に基づく切り分けです。Claude APIが返した応答であれば、成功でも失敗でもヘッダーにこのIDが入ります。
届いた応答と届かない応答を、実際の出力で見分ける
キーを使わない確認もできます。キー無しで /v1/models をGETすると、認証エラーが返ります。エラーでも、Claude APIまで届いた証拠になります。キーもトークンも使わないので、課金は発生しません。
curl -sS -m 15 -i https://api.anthropic.com/v1/modelscurl 8.7.1での出力は次のとおりです(ヘッダーは一部のみ)。
HTTP/2 401
content-type: application/json
request-id: req_011Cfgnu…
{"type":"error","error":{"type":"authentication_error","message":"x-api-key header is required"},"request_id":"req_011Cfgnu…"}届いた場合と届かない場合
届いた
上の出力のように HTTP/2 401 と request-id、JSONのエラー本文がそろっています。キーを付けていないので401は想定どおりで、経路の問題ではありません。
届かない
ステータス行もJSONも出ず、curl: (数字) で始まる1行で終わります。この数字が次の表の手がかりです。
届かない側は、原因によってメッセージが変わります。次の4つは、curlで実際に出る代表的な出力です。
curl -sS -m 10 https://api.anthropic.invalid/v1/messages
curl -sS -m 10 http://127.0.0.1:9/v1/messages
curl -sS -m 10 -x http://127.0.0.1:9 https://api.anthropic.com/v1/models
curl -sS -m 3 http://10.255.255.1/| 状況 | curlの出力 | 疑う箇所 |
|---|---|---|
| 存在しないホスト名 | curlの出力curl: (6) Could not resolve host: api.anthropic.invalid | 疑う箇所DNS・名前解決 |
| 待ち受けの無いポート | curlの出力curl: (7) Failed to connect to 127.0.0.1 port 9 after 0 ms: Couldn't connect to server | 疑う箇所接続拒否 |
| 誤ったプロキシ指定 | curlの出力curl: (7) Failed to connect to 127.0.0.1 port 9 after 0 ms: Couldn't connect to server | 疑う箇所プロキシの宛先 |
| 応答の無い宛先 | curlの出力curl: (28) Connection timed out after 3006 milliseconds | 疑う箇所途中でパケットが捨てられる経路 |
3行目に注目すると、接続先に api.anthropic.com ではなくプロキシのアドレスが出ています。プロキシ経由の環境で (7) が出たら、まずプロキシ側の宛先を疑います。(28) は、拒否ではなく無応答です。ファイアウォールのルールによっては、拒否の返事を出さずにパケットを捨てるため、このタイムアウトの形になります。
手順2: SDKで同じ確認を再現する
curlは通るのにアプリだけ失敗するなら、差はSDK側の設定にあります。Pythonの場合、接続失敗を別の例外として受け、原因を出力する確認スクリプトが使えます。
import anthropic
client = anthropic.Anthropic(max_retries=0, timeout=15.0)
try:
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=16,
messages=[{"role": "user", "content": "ping"}],
)
print("OK", message._request_id)
except anthropic.APIConnectionError as e:
print("届いていない:", e.__cause__)
except anthropic.APIStatusError as e:
print("届いた:", e.status_code)SDKの既定値(Python)
接続エラーの再試行
2回
短い指数バックオフ。診断時は max_retries=0
タイムアウト
10分
timeout で変更できる
診断用のスクリプトで効くのは max_retries=0 と e.__cause__ の2つです。再試行を切ると失敗がすぐ見えます。__cause__ には APIConnectionError の原因になった例外が入り、名前解決の失敗か、接続拒否か、TLSの問題かが分かります。公式ドキュメントの例も、原因を __cause__ から取り出しています。再試行の対象は接続エラーだけではなく、408・409・429・500以上のエラーも既定で再試行されます。
APIStatusError の側に入れば通信は届いています。message._request_id は、成功時のレスポンスから取り出せるリクエストIDです。サポートへ問い合わせるときはこのIDが手掛かりになります。例外クラスの言語別の対応はClaude APIのエラー形式とSDK例外クラスの言語別対応表に整理しています。
手順3: VPNを外して比べる
curlも失敗するなら、経路そのものを疑います。最初に試すのはVPNです。
VPNを切ったネットワーク(自宅回線やテザリングなど)で、手順1のコマンドをそのまま実行します。VPNを切ると通る場合は、VPNの出口側か、VPN経由の社内プロキシが api.anthropic.com への通信を止めている可能性があります。サポート記事も「リクエストを送る間はVPNを使わない」ことを対処に挙げています。
VPNが必須の環境では、VPN管理者にClaude APIの宛先を通すよう依頼する形になります。宛先の指定方法は次の手順に続きます。
手順4: ファイアウォールに許可を入れる
VPNを外しても失敗する、あるいはVPNを外せない企業ネットワークでは、ファイアウォールの許可設定を確認します。公式のIPアドレスのページには、Claude APIへ接続する際の宛先(inbound)として、次のレンジが載っています。
| プロトコル | レンジ |
|---|---|
| IPv4 | レンジ160.79.104.0/23 |
| IPv6 | レンジ2607:6bc0::/48 |
ここで押さえておく点は3つです。
- 接続先は
https://api.anthropic.comなので、標準のHTTPS(443)も許可対象に含めます。アドレスだけでなくプロトコルとポートも許可ルールに入れます - IPv6のレンジもあります。IPv4だけを許可しているルールセットでは、IPv6で解決された接続だけが落ちる状況が起こり得ます
- AWS上のClaude Platformを使う場合、inboundの宛先はAWS側のIPレンジに解決されます。ここに挙げたレンジは当てはまりません
宛先が正しいレンジに解決されているかの確認や、outboundとの区別は、別記事で詳しく書いています(Claude APIのIPアドレスをファイアウォールに許可登録する手順)。削除しておきたい旧IPアドレスの一覧も、そちらに載せています。
手順5: プロキシ経由の環境ではSDKに設定を渡す
社内プロキシを通す環境では、curlはプロキシ設定に従うのにSDKは従わない、という食い違いが出ることがあります。公式のSDKドキュメントは、HTTPクライアントを差し替えてプロキシを指定する方法を示しています。
Pythonでは、DefaultHttpxClient にプロキシを渡します。
import anthropic
from anthropic import DefaultHttpxClient
client = anthropic.Anthropic(
http_client=DefaultHttpxClient(
proxy="http://my.test.proxy.example.com",
),
)TypeScriptでは、Node.jsの場合に undici の ProxyAgent を fetchOptions の dispatcher に渡します。
import Anthropic from "@anthropic-ai/sdk";
import * as undici from "undici";
const proxyAgent = new undici.ProxyAgent("http://localhost:8888");
const client = new Anthropic({
fetchOptions: { dispatcher: proxyAgent },
});プロキシのURLは自分の環境の値に置き換えます。SDKドキュメントの例はプロキシのURLだけです。認証付きプロキシの書式は社内のプロキシ管理者に確認します。
Claude Codeの接続エラー表示から原因を読む
Claude Codeでは、同じ「届かない」失敗が文言とカッコ内のコードで区別されて表示されます。この節は、表示の文言から疑う箇所を引くための索引です。公式のエラー一覧では、TCP接続が失敗した、または完了しなかった場合の表示が次のように並びます。
| 表示 | コード | 疑う箇所 |
|---|---|---|
Connection refused — a firewall or proxy may be blocking it | コードConnectionRefused / ECONNREFUSED | 疑う箇所ファイアウォール・プロキシ、残った ANTHROPIC_BASE_URL |
Can't reach the API server — check your internet or DNS | コードENOTFOUND / FailedToOpenSocket | 疑う箇所インターネット接続・DNS |
No internet route — check your connection or VPN | コードEHOSTUNREACH | 疑う箇所経路・VPN |
Couldn't connect through your proxy | コードERR_PROXY_TUNNEL | 疑う箇所プロキシの認証情報と許可ホスト |
Connection dropped | コードECONNRESET | 疑う箇所通信の途中切断 |
Request timed out. Check your internet connection and proxy settings | コードなし | 疑う箇所インターネット接続・プロキシ設定 |
v2.1.227より前は、どれも Unable to connect to API (ECONNREFUSED) のようにコードだけが付く表示でした。未知のコードは今も同じ形で出ます。
プロキシ経由でartifactを開くときは、artifact content fetch failed (proxy refused the connection: HTTP 407) と出ることがあります。この表示はAPI接続とは別です。プロキシの認証情報と、*.frame.claudeusercontent.com の許可を確認します。
表示ごとの詳しい手順は専用の記事にあります。Connection refused、Unable to connect to API、Unable to connect to Anthropic servicesが各表示の記事です。アップデート中の Connection dropped は別の記事で扱っています。
最初に確かめるのは、同じシェルから curl -I https://api.anthropic.com が通るかどうかです。Windows PowerShellでは curl.exe と書き、組み込みの別名と区別します。社内プロキシがあるなら、起動前に HTTPS_PROXY を設定します。
curlは通るのにClaude Codeだけ失敗するなら、次の点が候補です。
ANTHROPIC_BASE_URLが設定されたままで、止まったローカルのプロキシやゲートウェイを指している。この場合、curlが通ってもConnection refusedが出ます- LinuxやWSLで、
/etc/resolv.confが到達できないネームサーバーを指している - macOSで、切断したVPNの通信用インターフェース(
utun)やルーティング設定が残っている - Docker Desktopなどのコンテナ実行環境が外向きの通信に割り込んでいる
待っても応答が返らないときは、別の表示になります。API Error: No response from API は、応答ヘッダーが期限内に届かず、1回の再送でも答えが無かった状態です。プロキシが応答を保留する環境で起きます。待ち時間の調整はClaude CodeでNo response from APIが出るときにあります。
Streaming response ended before any complete data was received は、ストリーミング応答が有効なデータを返さず終わったため、ストリーミングなしで再送した旨の警告です。経路上のプロキシかゲートウェイが応答本文を加工しているのが主な原因で、ストリーミング応答をそのまま通す設定にします。
長い非ストリーミング要求は別の原因で切れる
接続自体は成立するのに、長い処理の途中で切れる型もあります。サーバー側で打ち切られた場合は、504 timeout_error というステータス付きの応答になります。ここで扱うのは、応答そのものが返らず切れる型です。公式ドキュメントによると、ネットワークによっては一定時間で待機中の接続を切ります。max_tokens を大きく取った非ストリーミングのリクエストは、応答が返るまで接続が無通信の時間が長く、この影響を受けやすい構成です。
対策は3つあります。
- ストリーミングのMessages APIを使う。イベントが流れ続けるので接続が無通信にならない
- 途中経過が不要なら、SDKにストリームを消費させて完成した
Messageだけ受け取る - 長時間かかる処理はMessage Batches APIに回し、結果をポーリングで受け取る
PythonのSDKは、非ストリーミングの要求が約10分を超えそうなとき ValueError で知らせます。stream=True にするかタイムアウトを上書きすると、この判定は働きません。TCPのキープアライブも既定で設定します。ストリーミングの復旧の挙動は、別記事にあります(Claude APIストリーミングのエラー復旧がv4.6で変わった)。
直らないときに手元へ残す情報
上の手順で直らないときは、サポートへの問い合わせ用に次を控えます。
- 手順1のcurlの出力(ヘッダー込み)
- 失敗したSDKの
e.__cause__の内容 - 成功したリクエストがあれば、その
request-id - VPNの有無、プロキシの有無、実行しているマシンの種類(自宅端末・社内サーバー・CIなど)
ドキュメントは、特定のリクエストについて問い合わせるときにリクエストIDを添えるよう案内しています。ただし接続エラーの場合、サーバーまで届いていないため、失敗したリクエスト自体にIDはありません。手元の環境情報のほうが手掛かりになります。パケットまで追う場合は、tsharkで再送とRSTの行だけを書き出す手順が使えます。
まとめ
サーバーやCIで失敗するなら、そのマシン上でキーなしのGETを1回打つと、経路を見るのかキーを見るのかが決まります。401が返れば経路は通っているので、残りはキーと権限の確認です。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- support.claude.com/en/articles/10366432-i-m-getting-an-api-connection-error-h…
- support.claude.com/en/articles/13403291-how-can-i-check-connectivity-to-the-c…
- platform.claude.com/docs/en/api/errors
- platform.claude.com/docs/en/api/sdks/python
- platform.claude.com/docs/en/api/ip-addresses
- code.claude.com/docs/en/errors