「404エラーのページを見たことがない人はいない」と言っても過言ではありませんが、 200番台と300番台の違いをすらすら説明できる人はそれほど多くありません。 HTTP(HyperText Transfer Protocol)のステータスコードはWebの根幹をなす仕様ですが、 番号が多く似たものも多いため、開発中にどれを返すべきか迷う場面は誰にでもあります。 この記事では、1xx〜5xxの体系から実務でよく見るコードの意味・使い分け・対処法まで、 開発者とWebサイト運営者の両方の視点で解説します。
HTTPステータスコードの体系 — 1xx〜5xx
HTTPステータスコードは3桁の数字で、先頭の1桁がカテゴリを表します。 RFC(Request for Comments)7231をはじめとする一連の仕様で定義されています。
| カテゴリ | 意味 | 代表的なコード | 特徴 |
|---|---|---|---|
| 1xx | 情報(Informational) | 100, 101 | 処理続行中。WebSocketアップグレード時に101が使われる |
| 2xx | 成功(Success) | 200, 201, 204 | リクエスト成功。最もよく使われるカテゴリ |
| 3xx | リダイレクト(Redirection) | 301, 302, 304 | 追加の処理が必要。URLが変わったことを伝える |
| 4xx | クライアントエラー(Client Error) | 400, 401, 403, 404 | リクエスト側の問題。修正が必要なのはクライアント |
| 5xx | サーバーエラー(Server Error) | 500, 502, 503, 504 | サーバー側の問題。リクエスト自体は正しい |
2xx 成功レスポンス — 使い分けが意外と難しい
「成功したら200を返せばいい」と思いがちですが、REST APIの設計では意味の違いを使い分けることで APIの意図が明確になります。
| コード | 名称 | 意味・使いどころ |
|---|---|---|
| 200 | OK | GETの取得成功・PUTやPATCHの更新成功。汎用的な成功コード |
| 201 | Created | POSTでリソースを新規作成した。Locationヘッダーで作成先URLを返す |
| 204 | No Content | DELETEの成功など、レスポンスボディが不要な場合。ボディは空にする |
| 206 | Partial Content | 動画ストリーミング・ファイルの範囲取得(Rangeヘッダーと組み合わせて使用) |
REST APIの慣習
POST(作成)→ 201、PUT/PATCH(更新)→ 200、DELETE(削除)→ 204がよく使われる組み合わせです。 すべてに200を返すAPIも多いですが、201と204を使うとAPIクライアント側でレスポンスの意味が明確になります。
3xx リダイレクト — SEOへの影響を知る
3xxはブラウザ(またはクローラー)に「別のURLを見てください」と伝えるコードです。 選ぶコードによってSEO評価の引き継ぎ方が変わります。
| コード | 名称 | SEO評価の引き継ぎ | 使いどころ |
|---|---|---|---|
| 301 | Moved Permanently | 転送される(推奨) | URLの恒久的な変更、HTTP→HTTPSへの移行 |
| 302 | Found(一時リダイレクト) | 転送されない | A/Bテスト、ログイン前のリダイレクト |
| 304 | Not Modified | — | キャッシュが有効(ETagで判定)。ボディなしで返す |
| 307 | Temporary Redirect | 転送されない | 302と同義だがHTTPメソッドを変えない(POSTがそのままPOSTで飛ぶ) |
| 308 | Permanent Redirect | 転送される | 301と同義だがHTTPメソッドを変えない(POSTがそのままPOSTで飛ぶ) |
ドメイン変更やURL体系の変更には必ず301を使いましょう。302を使うと検索エンジンが古いURLを保持し続け、リンク評価が新URLに移りません。 また302は仕様上HTTPメソッドをGETに変更してリダイレクトする実装が多いため、 POSTをリダイレクトしたい場合は307/308が適切です。
4xx クライアントエラー — 原因はリクエスト側にある
4xxはリクエスト側に問題があるコードです。サーバーを再起動しても解決しません。 特に401と403は混同されやすいため、丁寧に解説します。
400 Bad Request
HTTPリクエスト自体が不正な場合です。JSONの構文エラー・無効なクエリパラメータ・ 必須ヘッダーの欠落などが該当します。バリデーション違反には422を使うケースも多いですが、 400を広く使うAPIも多く、どちらかに統一することが重要です。
401 Unauthorized — 「誰?」
名前は「Unauthorized(認可されていない)」ですが、意味は「認証されていない」です。 Authorizationヘッダーがない・トークンが無効・期限切れなど、 「あなたが誰かわからない」状態のときに返します。
クライアントは再認証(ログインやトークン再取得)を試みることが期待されます。 レスポンスには WWW-Authenticate ヘッダーを付けることが推奨されています(RFC 7235)。
403 Forbidden — 「誰かはわかるが、ダメ」
認証済みだが権限がない状態です。ログインしている一般ユーザーが管理者専用ページにアクセスした場合や、 IP制限にかかった場合などに返します。
401 vs 403 まとめ
- 未ログイン状態でAPIを叩いた → 401(再ログインで解決できるかもしれない)
- ログイン済みだが管理者権限が必要なページ → 403(再ログインしても変わらない)
404 Not Found
指定したURLのリソースが存在しない場合です。「存在しないのか、アクセス権がないのかを教えたくない」 セキュリティ上の理由から、403の代わりに404を返す実装もあります(存在すること自体を隠す)。 削除済みリソースを明示したい場合は410 Goneを検討してください。
その他のよく使う4xxコード
| コード | 名称 | 使いどころ |
|---|---|---|
| 405 | Method Not Allowed | GETしか許可していないエンドポイントにPOSTした場合など |
| 408 | Request Timeout | クライアントがリクエストを送りきれずタイムアウト |
| 409 | Conflict | すでに存在するメールアドレスで登録しようとした場合など |
| 410 | Gone | リソースが永久に削除された(クローラーへのインデックス削除を促す) |
| 422 | Unprocessable Entity | JSON形式は正しいがバリデーション失敗(必須フィールドなし・型違い等) |
| 429 | Too Many Requests | レートリミット超過。Retry-Afterヘッダーと組み合わせて使う |
5xx サーバーエラー — 問題はサーバー側にある
5xxはリクエスト自体は正しいが、サーバー側で問題が発生したコードです。 nginx・Docker・クラウド環境でよく遭遇するものを中心に解説します。
| コード | 名称 | よく見る状況 |
|---|---|---|
| 500 | Internal Server Error | アプリケーションの未処理例外・バグ・設定ファイルのエラー |
| 502 | Bad Gateway | nginxの背後のアプリサーバーがクラッシュ・Dockerコンテナが落ちている |
| 503 | Service Unavailable | デプロイ中・メンテナンス中・負荷が高すぎてリクエストをさばけない |
| 504 | Gateway Timeout | バックエンドへのリクエストがタイムアウト(DBが遅い・外部API応答待ちなど) |
500と502の見分け方:500はアプリサーバー自体がエラーを返しています(エラーログにスタックトレースあり)。 502はプロキシ(nginx等)がバックエンドから応答を得られなかった場合で、 nginxのエラーログにupstream connect() failedなどが記録されます。
503と504の見分け方:503は「サービスが使えない」、504は「タイムアウトした」です。 504が頻発する場合は、DBのスロークエリやN+1問題を疑いましょう。
シーン別早見表 — どのコードを使うか迷ったとき
実務でよく迷う場面を3カテゴリに分けて整理します。 エラーコードの意味をさらに深掘りしたいときはエラーコード横断検索ツールでHTTPステータスコード・SQLStateなどを横断検索できます。
REST API設計
| シナリオ | 推奨コード |
|---|---|
| GETでデータ取得成功 | 200 |
| POSTで新規リソース作成成功 | 201 + Locationヘッダー |
| DELETEで削除成功(ボディなし) | 204 |
| リクエストボディのバリデーション失敗 | 422 |
| 重複レコードの作成を試みた | 409 |
| レートリミット超過 | 429 + Retry-After |
Webアプリケーション開発
| シナリオ | 推奨コード |
|---|---|
| ページが存在しない | 404 |
| 削除したコンテンツのURL | 410(SEO観点で301より有効な場面も) |
| ログインが必要なページ(未ログイン) | 401(またはログインページへ302) |
| 権限不足のページ(ログイン済み) | 403 |
| URLが恒久的に変わった | 301 |
インフラ運用
| 状況 | コード | 調査ポイント |
|---|---|---|
| アプリが落ちた・バグで例外発生 | 500 | アプリのエラーログ・スタックトレース |
| nginxの裏でNode.js/Pythonが落ちた | 502 | nginxエラーログ・コンテナの起動状態 |
| デプロイ中・計画メンテナンス | 503 | Retry-Afterヘッダーで再試行時間を告知する |
| DBのスロークエリ・外部API遅延 | 504 | DBのスロークエリログ・外部API応答時間 |
まとめ
- 1xx〜5xxはカテゴリを示す。4xxはクライアントの問題・5xxはサーバーの問題
- 401は「誰かわからない(未認証)」、403は「誰かわかるが権限なし(認証済み・認可なし)」
- POSTの成功は201、DELETEでボディ不要なら204を使うとAPIの意図が明確になる
- 301はSEO評価を転送する恒久的リダイレクト、302はSEO評価を転送しない一時的リダイレクト
- 422はJSONとしては正しいがアプリレベルのバリデーション失敗に使う
- 502はプロキシのバックエンド接続失敗、503は意図的なサービス停止、504はタイムアウト
- 429が返ってきたら
Retry-Afterヘッダーを確認し、指数バックオフでリトライする - 削除したURLには404より410を返すとクローラーへのインデックス削除を促せる