HTTPステータスコードの基本|200・404・500の意味と使い分け
HTTPステータスコードは、サーバーがリクエストの結果を3桁で返す仕組みです。まず結論を言うと、200は成功、404は見つからない、500はサーバー側の想定外エラーです。
Webサイトの表示確認だけでなく、APIの設計、fetch() のエラーハンドリング、curl での疎通確認でも毎日のように出てきます。意味を丸暗記するより、「誰が直せる問題か」で分けると実務で迷いにくくなります。
200 OK: リクエストは成功した404 Not Found: 指定したURLやリソースが見つからない500 Internal Server Error: サーバー内部で予期しない問題が起きた4xx: 主にクライアント側の指定や入力に原因がある5xx: 主にサーバー側の処理や構成に原因がある
ここがポイント: 迷ったら「URLや入力を直せば解決するか」「サーバーの実装や設定を直さないと解決しないか」で見ると、4xx と 5xx を切り分けやすくなります。
まず押さえたいHTTPステータスコードの見方
HTTPステータスコードは RFC 9110 で整理されており、MDN の一覧 でも5つの分類で確認できます。
1xx: 処理継続の案内2xx: 成功3xx: リダイレクト4xx: クライアントエラー5xx: サーバーエラー
この記事では、最初に覚えるべき3つとして 200 404 500 に絞って見ます。現場ではこの3つの意味を正しく返せるだけでも、ログの読みやすさもAPIの使いやすさもかなり変わります。
200・404・500の意味と使い分け
この3つは見た目が似ていても、返す場面ははっきり違います。特にAPIでは、ここを雑にすると利用側が再試行すべきか、URLを見直すべきか、入力を直すべきか判断できなくなります。
200 OK
200 OK は、リクエストが成功したことを示します。RFC 9110 でも成功レスポンスの基本として扱われています。
よく使う場面は次の通りです。
- ページ表示に成功した
GET - 一覧取得や詳細取得に成功した API
- 更新処理が完了し、結果を本文で返したいとき
例:
HTTP/1.1 200 OK
Content-Type: application/json
{"id":42,"name":"Masa"}
ただし、成功なら何でも 200 でよいわけではありません。次のように、より適切なコードがある場面もあります。
- 新規作成が完了した:
201 Created - 本文を返さない更新・削除成功:
204 No Content
「成功した」ことと「何が成功したか」は別です。作成なのか、取得なのか、本文があるのかで分けると、呼び出し側が処理しやすくなります。
404 Not Found
404 Not Found は、サーバーが対象リソースを見つけられないときに返します。RFC 9110 の 404 定義 では、現在の表現が見つからない、または存在を明かしたくない場合を含みます。
実務で多いのは次のケースです。
- URLの打ち間違い
- ルーティングに存在しないパスへアクセスした
- 既に削除された記事やデータを読みに行った
- ID指定のAPIで、対象データが存在しない
例:
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error":"User not found"}
ここで大事なのは、404 は「処理失敗」ではなく「対象がない」ことを伝えるコードだという点です。存在しないユーザーIDを検索したのに 500 を返すと、利用側はサーバー障害だと誤解します。
なお、MDN の 404 解説 にある通り、404だけでは一時的か恒久的かまでは示しません。完全に廃止したことを明確にしたいなら 410 Gone を検討します。
500 Internal Server Error
500 Internal Server Error は、サーバーが予期しない状態に遭遇し、リクエストを処理できなかったときのコードです。RFC 9110 の 500 定義 でもその位置づけです。
典型例は次の通りです。
- 例外が未処理のまま落ちた
- データベース接続に失敗した
- アプリ設定や依存サービスの障害で処理が続けられない
- 想定していない
nullや型不一致でクラッシュした
例:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"error":"Internal Server Error"}
500 は最後の逃げ道です。入力ミスや存在しないURLまで500にすると、障害調査のログがノイズだらけになります。利用者にとっても、再試行してよいのか、問い合わせるべきか判断しにくくなります。
サンプルで見る使い分け
ここでは、ユーザー情報を返すAPIを例にすると違いが見えやすくなります。
例1: 正常に取得できた
リクエスト:
curl -i https://example.com/api/users/42
レスポンス:
HTTP/1.1 200 OK
Content-Type: application/json
{"id":42,"name":"Masa"}
ユーザーが存在し、取得できたので 200 です。
例2: 指定したIDが存在しない
リクエスト:
curl -i https://example.com/api/users/99999
レスポンス:
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error":"User not found"}
アプリは動いています。問題はサーバー障害ではなく、欲しいデータがないことです。だから 404 が合います。
例3: サーバー処理で例外が発生した
リクエスト:
curl -i https://example.com/api/users/42
レスポンス:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"error":"Internal Server Error"}
同じURLでも、内部処理で落ちれば 500 です。URLの問題ではないので 404 ではありません。
よくある失敗と改善例
HTTPステータスコードは、動けばいいという実装にするとすぐ崩れます。初心者がつまずきやすい点を先に押さえておくと、後から直す手間を減らせます。
NG: エラー内容を本文に書いているのに 200 を返す
悪い例:
HTTP/1.1 200 OK
Content-Type: application/json
{"error":"Not found"}
これだと、HTTPのレベルでは成功に見えます。監視、SDK、ブラウザの処理、キャッシュ制御で混乱が起きやすくなります。
改善:
- 対象がないなら
404 - 入力不正なら
400 Bad Request - 認証不足なら
401 Unauthorized - 権限不足なら
403 Forbidden
NG: ユーザー入力の不正を 500 にする
たとえば必須項目が空、JSON形式が壊れている、数値のはずが文字列だった、というケースはサーバー障害ではありません。
改善:
- 構文や入力不正は
400 - 形式は正しいが状態が衝突するなら
409 Conflict - サーバー内部の予期しない例外だけを
500にする
NG: 新規作成でも常に 200 を返す
新しいリソースを作ったなら、201 Created の方が意味が明確です。API利用側は、作成成功か通常取得かをステータスだけで判別できます。
ブラウザとCLIで確認する方法
コードを書いているときは、まず実際のステータスを見て判断するのが近道です。
Fetch API で確認する
ブラウザの fetch() では、レスポンスの status でHTTPステータスコードを取得できます。MDN の Response.status でも基本動作を確認できます。
const response = await fetch('/api/users/42');
if (response.status === 200) {
const data = await response.json();
console.log(data);
} else if (response.status === 404) {
console.log('対象データがありません');
} else if (response.status >= 500) {
console.log('サーバー側の問題です');
}
curl で確認する
ターミナルでは curl -i が手早いです。
curl -i https://example.com/api/users/42
ヘッダーの先頭行に HTTP/1.1 200 OK のような形で出るので、まずそこを見ます。本文だけ見て判断すると、200 なのにエラーJSONを返している実装ミスを見落としやすくなります。
実務での使いどころ
HTTPステータスコードを正しく返すと、単に見た目が整うだけではありません。運用面で効いてきます。
- フロントエンドが再試行、エラー表示、画面遷移を分けやすい
- API利用者が原因を早く切り分けられる
- 監視で
5xxだけを障害候補として集計しやすい - ログ分析で「URLミス」と「サーバー障害」が混ざりにくい
特にAPIでは、ステータスコードが契約の一部です。レスポンス本文のメッセージだけに頼る設計より、保守しやすくなります。
迷ったときの判断基準
最後に、200・404・500で迷ったときの最低限の基準を並べます。
- 正常に処理できた:
200 - 対象URLやリソースが存在しない:
404 - サーバー内部の予期しない問題で処理不能:
500 - 新規作成なら
201、本文なし成功なら204も検討する - 入力ミスやバリデーションエラーを
500にしない
この切り分けができるだけで、APIの使い勝手も障害調査の速度も変わります。次にコードを書くときは、エラーメッセージより先に「この結果に合うHTTPステータスは何か」を確認してみてください。
