この記事の要点
• HTTPステータスコードは3桁の数字でリクエストの処理結果を表す
• 1xx=情報、2xx=成功、3xx=リダイレクト、4xx=クライアントエラー、5xx=サーバーエラー
• 実務では200/201/204/400/401/404/500を正しく使い分けることが重要
ステータスコードとは
HTTPステータスコードは、サーバーがクライアントのリクエストをどのように処理したかを示す3桁の数字です。レスポンスの1行目(ステータスライン)に含まれます。
HTTP/1.1 200 OK
^^^
ステータスコード
構成: ステータスコード + 理由フレーズ(OK、Not Foundなど)
ステータスコードのクラス
最初の1桁でカテゴリを示します:
| クラス | 意味 | 用途 |
|---|---|---|
| 1xx | 情報レスポンス | リクエスト処理中 |
| 2xx | 成功 | リクエストが正常に処理された |
| 3xx | リダイレクト | 別のリソースへ誘導 |
| 4xx | クライアントエラー | リクエストに問題がある |
| 5xx | サーバーエラー | サーバー側で処理できなかった |
ポイント: 4xxはクライアント側の問題(修正して再送すれば成功する可能性)、5xxはサーバー側の問題(同じリクエストを送っても失敗する)という違いがあります。
2xx - 成功
リクエストが正常に処理されたことを示します。
主要な2xxコード
| コード | 名前 | 意味 | 使用場面 |
|---|---|---|---|
| 200 | OK | リクエスト成功 | GET、PUT、PATCHの成功 |
| 201 | Created | リソース作成成功 | POSTで新規作成 |
| 204 | No Content | 成功(ボディなし) | DELETE、PUTの成功 |
| 206 | Partial Content | 部分的なコンテンツ | 範囲指定ダウンロード |
200 OK - 一般的な成功
# GETリクエスト
GET /api/users/123 HTTP/1.1
# レスポンス
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "Alice"}
201 Created - リソース作成成功
# POSTリクエスト
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Bob"}
# レスポンス
HTTP/1.1 201 Created
Location: /api/users/456
Content-Type: application/json
{"id": 456, "name": "Bob", "created_at": "2026-05-02T10:00:00Z"}
実践メモ: 201を返す際は、Locationヘッダーで作成したリソースのURLを返すのがベストプラクティスです。
204 No Content - 成功(ボディなし)
# DELETEリクエスト
DELETE /api/users/123 HTTP/1.1
# レスポンス
HTTP/1.1 204 No Content
削除や更新が成功したが、返すべきコンテンツがない場合に使用します。
3xx - リダイレクト
クライアントに別のリソースへアクセスするよう指示します。
主要な3xxコード
| コード | 名前 | 意味 | メソッド変更 | 使用場面 |
|---|---|---|---|---|
| 301 | Moved Permanently | 永続的な移動 | GET/HEADのみ保持 | URL変更(SEO重視) |
| 302 | Found | 一時的な移動 | GET/HEADのみ保持 | 一時的な誘導 |
| 303 | See Other | 別リソースを参照 | GETに変更 | POST後のリダイレクト |
| 304 | Not Modified | 未変更 | - | キャッシュが有効 |
| 307 | Temporary Redirect | 一時的な移動 | メソッド保持 | メンテナンス時 |
| 308 | Permanent Redirect | 永続的な移動 | メソッド保持 | URL変更(メソッド保持) |
301 vs 302 vs 307
# 301 Moved Permanently(永続的)
HTTP/1.1 301 Moved Permanently
Location: https://newdomain.com/page
# 302 Found(一時的、歴史的理由で挙動が曖昧)
HTTP/1.1 302 Found
Location: https://example.com/temp-page
# 307 Temporary Redirect(一時的、メソッド保持)
HTTP/1.1 307 Temporary Redirect
Location: https://example.com/maintenance
ポイント: 現代のAPIでは、301/308(永続)と303/307(一時)を明確に使い分けるべきです。302は歴史的な理由で挙動が曖昧です。
304 Not Modified - キャッシュ有効
# リクエスト(キャッシュ検証)
GET /api/data HTTP/1.1
If-None-Match: "abc123"
# レスポンス(変更なし)
HTTP/1.1 304 Not Modified
ETag: "abc123"
リソースが変更されていない場合、ボディを送信せずキャッシュを使うよう指示します。
4xx - クライアントエラー
クライアント側のリクエストに問題があることを示します。
主要な4xxコード
| コード | 名前 | 意味 | 使用場面 |
|---|---|---|---|
| 400 | Bad Request | リクエスト不正 | 構文エラー、バリデーション失敗 |
| 401 | Unauthorized | 認証が必要 | 未ログイン、トークン無効 |
| 403 | Forbidden | アクセス拒否 | 権限不足 |
| 404 | Not Found | リソースが存在しない | 存在しないURL |
| 405 | Method Not Allowed | メソッド許可されていない | GETのみ許可のエンドポイントにPOST |
| 409 | Conflict | リソースの競合 | 重複登録、楽観的ロック失敗 |
| 422 | Unprocessable Entity | 意味的エラー | バリデーションエラー(詳細) |
| 429 | Too Many Requests | リクエスト過多 | レート制限超過 |
400 Bad Request - リクエスト不正
# 不正なJSONを送信
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Alice", email: "invalid-json"}
# レスポンス
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid JSON syntax",
"details": "Unexpected token 'e' at position 18"
}
401 vs 403 の違い
| コード | 意味 | 解決方法 | 例 |
|---|---|---|---|
| 401 Unauthorized | 認証が必要 | ログイン・トークン再取得 | 未ログイン状態でアクセス |
| 403 Forbidden | 権限不足 | 権限の付与を依頼 | 一般ユーザーが管理者画面にアクセス |
# 401 - 認証が必要
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
{"error": "Authentication required"}
# 403 - 権限不足
HTTP/1.1 403 Forbidden
{"error": "You do not have permission to access this resource"}
注意: 401は「認証されていない(Unauthenticated)」の意味ですが、歴史的な理由でUnauthorizedという名前になっています。
404 Not Found - リソースが存在しない
GET /api/users/99999 HTTP/1.1
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error": "User not found"}
409 Conflict - リソースの競合
# メールアドレス重複
POST /api/users HTTP/1.1
Content-Type: application/json
{"email": "existing@example.com"}
# レスポンス
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"error": "Email already exists",
"field": "email",
"value": "existing@example.com"
}
422 Unprocessable Entity - バリデーションエラー
POST /api/users HTTP/1.1
Content-Type: application/json
{
"name": "A",
"email": "invalid-email",
"age": -5
}
# レスポンス
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"errors": [
{"field": "name", "message": "Name must be at least 2 characters"},
{"field": "email", "message": "Invalid email format"},
{"field": "age", "message": "Age must be positive"}
]
}
実践メモ: 400と422の使い分け:構文エラーや必須項目不足は400、構文は正しいが業務ルール違反は422を使うのが一般的です。
429 Too Many Requests - レート制限
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1714651200
{"error": "Rate limit exceeded. Try again in 1 hour."}
5xx - サーバーエラー
サーバー側で処理できなかったことを示します。
主要な5xxコード
| コード | 名前 | 意味 | 使用場面 |
|---|---|---|---|
| 500 | Internal Server Error | 内部サーバーエラー | 予期しない例外 |
| 502 | Bad Gateway | ゲートウェイエラー | プロキシ先サーバーの応答不正 |
| 503 | Service Unavailable | サービス利用不可 | メンテナンス、過負荷 |
| 504 | Gateway Timeout | ゲートウェイタイムアウト | プロキシ先サーバーが応答しない |
500 Internal Server Error - 内部エラー
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": "An unexpected error occurred",
"request_id": "abc-123-xyz"
}
注意: 本番環境では、500エラーのレスポンスにスタックトレースや詳細なエラー情報を含めないでください。セキュリティリスクになります。
503 Service Unavailable - サービス利用不可
HTTP/1.1 503 Service Unavailable
Retry-After: 300
{
"error": "Service temporarily unavailable due to maintenance",
"estimated_recovery": "2026-05-02T12:00:00Z"
}
ステータスコードの選び方
API設計での基本方針
| 状況 | 推奨コード | 理由 |
|---|---|---|
| リソース取得成功 | 200 | 標準的な成功 |
| リソース作成成功 | 201 | 作成されたことを明示 |
| 削除・更新成功(ボディなし) | 204 | コンテンツがないことを明示 |
| 必須パラメータ不足 | 400 | リクエストの構文エラー |
| バリデーションエラー | 422 | 意味的なエラー |
| 未ログイン | 401 | 認証が必要 |
| 権限不足 | 403 | アクセス拒否 |
| リソース不存在 | 404 | 見つからない |
| 重複登録 | 409 | 競合 |
| サーバー内部エラー | 500 | 予期しないエラー |
よくある迷いポイント
Q1: 削除済みリソースへのGETは404?410?
- 404(Not Found)が一般的
- 410(Gone)は「永久に削除された」ことを明示したい場合
Q2: 権限不足で404を返すべき?
- セキュリティ上、リソースの存在を隠したい場合は404
- 明示的に拒否を示したい場合は403
Q3: メンテナンス中は503?502?
- 503(Service Unavailable)が適切
- Retry-Afterヘッダーで復旧時刻を示す
まとめ
HTTPステータスコードはクライアントとサーバー間の共通言語です。適切なステータスコードを返すことで、エラーハンドリングやデバッグが容易になります。
関連記事
- HTTPの基本 - リクエストとレスポンスの構造
- HTTPメソッド - GET / POST / PUT / DELETE / PATCH の使い分け
- HTTPヘッダー入門 - リクエスト/レスポンスヘッダーの全体像
参考リソース
- MDN - HTTP response status codes
- RFC 9110 - HTTP Semantics (Status Codes)
- IANA - HTTP Status Code Registry
- httpstatuses.com - HTTP Status Code Reference