HTTP ステータスコードの実践的な使い分け - 401 と 403、3xx の違いをちゃんと選ぶ

HTTP ステータスコードの実践的な使い分け - 401 と 403、3xx の違いをちゃんと選ぶ

作成日:
更新日:

HTTP ステータスコードは「なんとなく 200 と 404 と 500 を知っていればいい」と思われがちですが、API を設計する側になると「ここは 401 か 403 か」「リダイレクトは 301 か 308 か」で必ず迷います。選び方を間違えると、キャッシュ・プロキシ・クライアントの自動リトライが誤動作します。

この記事では、実務で迷いやすいポイントを中心に、ステータスコードの使い分けを RFC 9110 や MDN をもとに整理します。

2xx: 成功

コード名前使いどころ
200OK標準的な成功。本文あり。「成功」の意味はメソッド依存
201Created新しいリソースを作成した。Location ヘッダで作成先を示すのが望ましい
202Accepted受理したが処理は未完了。非同期・キュー投入向け
204No Content成功したが返す本文がない。更新・削除など

実務では、PUT で既存を更新したら 200 か 204、新規作成したら 201。「成功したが返すものがない」なら 204、と覚えておくと迷いません。

3xx: リダイレクト(恒久/一時 × メソッド保持)

ここが3xx最大の論点です。「恒久か一時か」と「メソッドを保持するか」の2軸で見ます。

コード恒久/一時メソッド保持挙動
301 Moved Permanently恒久保証されない歴史的に POST が GET に変わる実装がある
302 Found一時保証されない同上
303 See Other一時必ず GET に変更フォーム送信後の遷移(PRG パターン)
307 Temporary Redirect一時必ず保持POST ならリダイレクト先も POST
308 Permanent Redirect恒久必ず保持301 のメソッド保持版

整理するとこうです。

  • メソッドを確実に保持したい(API・非 GET)→ 307(一時)/ 308(恒久)
  • 確実に GET にしたい(フォーム送信後)→ 303
  • 301/302 は仕様上メソッド保持が保証されない(歴史的に UA が POST→GET へ変える慣行を許容)。曖昧さを避けたい API では 307/308 が安全

NOTE

SEO 目的のサイト移転など「GET しか関わらない恒久リダイレクト」なら 301 で実害は少ないですが、非 GET を含むなら 308 を選ぶのが安全です。サイト公開時のリダイレクト設計は SEO チェックリストも参考にどうぞ。

4xx: クライアントエラー

コード名前使いどころ
400Bad Request不正な構文・必須欠落など、一般的な不正リクエスト
401Unauthorized未認証(認証情報なし/無効)。WWW-Authenticate を返すのが仕様
403Forbidden認証済みだが権限不足。再認証しても結果は変わらない
404Not Found見つからない、または存在を開示しない
405Method Not Allowedそのリソースで許可されないメソッド。Allow ヘッダで許可一覧を返す
409Conflict状態の競合(楽観ロック衝突・重複作成など)
410Gone恒久的に消えた(無くなったと確信)
422Unprocessable Content構文は正しいが意味的に処理不能(バリデーション失敗など)
429Too Many Requestsレート制限。Retry-After を付けるのが望ましい

401 と 403 の違い

いちばん混同されるのがこれです。

  • 401 = 未認証: 「あなたが誰か分からない」。認証すれば通る可能性がある。WWW-Authenticate を返す
  • 403 = 認可で拒否: 「あなたが誰かは分かるが、その権限はない」。再認証しても結果は変わらない

判断は単純で、「ログインしていない」なら 401、「ログイン済みだが権限がない」なら 403。認証方式そのものは パスキー/WebAuthnなども参照してください。

404 と 410

  • 404: 見つからない(一時的かもしれない、将来存在するかも不明)
  • 410: 恒久的に消えた(確信あり)。キャッシュやリンクの削除をクライアントに促せる

廃止を明示したいなら 410 が適切です。

422 の位置づけ

422 はコア HTTP(RFC 9110)には無く、WebDAV(RFC 4918)由来です。「構文は正しい(=400 ではない)が、意味的に処理できない」場合に使います。入力バリデーション失敗に 422 を使う設計は広まっていますが、これは規約ではなく慣行で、400 に統一する設計も妥当です。チームで方針を決める論点だと捉えてください。

5xx: サーバーエラー

コード名前使いどころ
500Internal Server Error未捕捉の例外など、原因を切り分けられない汎用エラー
502Bad Gatewayプロキシが上流から不正な応答を受けた
503Service Unavailable一時的な過負荷・メンテ。Retry-After を付けてよい
504Gateway Timeoutプロキシが上流から時間内に応答を得られない

502 と 504 はどちらも上流起因ですが、502 は「不正な応答が返ってきた」、504 は「そもそも応答が返ってこなかった」という違いです。

やりがちな誤用

200 でエラーを返すアンチパターン

最も多い設計ミスがこれです。失敗を HTTP 200 + 本文中のエラーフラグで返すと、HTTP の意味論が壊れ、キャッシュ・プロキシ・監視・自動リトライが誤動作します。失敗は適切な 4xx / 5xx で表現し、詳細は本文(RFC 9457 の Problem Details など)に載せるのが正道です。

429 と Retry-After

429(レート制限)には Retry-After(秒数か日時)で再試行までの待機を示すのが望ましいです。重要な注意として、RFC 6585 は「429 のレスポンスはキャッシュに保存してはならない」と明記しています。同様に 503 にも Retry-After を付けられます。CDN の Cache-Control 設計とあわせて、キャッシュ可能性を意識すると事故が減ります。

まとめ

  • 2xx: 201=作成、202=受理(未完了)、204=成功(本文なし)を使い分ける
  • 3xx: メソッド保持なら 307/308、確実に GET なら 303。301/302 は保持が保証されない
  • 401 と 403: 未認証なら 401(WWW-Authenticate)、権限不足なら 403
  • 404 と 410: 一時的かもなら 404、恒久的に消えたなら 410
  • 422: WebDAV 由来。バリデーション失敗に使うのは慣行(400 統一も可)
  • 5xx: 502=不正応答、504=応答なし。500 は汎用
  • 誤用: 200 でエラーを返さない。429/503 は Retry-After、429 はキャッシュ禁止

ステータスコードは「HTTP というプロトコルとの会話」です。正しく選ぶほど、クライアント・プロキシ・キャッシュがこちらの意図どおりに動いてくれる——その積み重ねが堅牢な API になります。

参考リンク