WebアプリケーションやAPIを作っていると、必ず出てくるのが HTTPステータスコード です。
とりあえず 200 OK を返しておけば動いてしまうので、最初のうちは深く考えずに実装してしまうことも多いと思います。
ただ、開発が進み、エラー処理や認証、バリデーションなどが増えてくると、
- ここ、本当に 200 でいいのかな?
- 400 と 404、どちらを返すべきなのか?
- 422 や 409 など、あまり使っていないコードはどう使えばよいのか?
といった迷いが出てきます。
HTTPステータスコードは、「サーバーがクライアントにどういう結果になったかを伝えるための公式な“短いメッセージ”」です。
適切に使い分けることで、バグの原因が分かりやすくなり、仕様も読み取りやすくなり、将来APIを触る人にも優しい設計 につながります。
この記事では、
- HTTPステータスコードのざっくりした全体像
- よく使うコードの意味と使いどころ
- 実務で特に迷いやすいポイント
- 最低限おさえておきたい判断の軸
を整理していきます。
HTTPステータスコードの概要

まずは「HTTPステータスコードとは何か」を簡単に整理します。
HTTPステータスコードは、レスポンス本文とは別に、「リクエストの結果がどうなったか」を端的に示します。
たとえば「成功しました」「クライアント側のミスです」「サーバー側でトラブルが起きました」といった情報を、3桁の数字 で伝えます。
大まかな分類は次の5つです。
- 1xx:情報(Informational) → 実務ではあまり意識しないことが多いです。
- 2xx:成功(Success) → リクエストが成功したことを表します。
- 3xx:リダイレクト(Redirection) → 別の場所に移動しました、という案内です。
- 4xx:クライアントエラー(Client Error) → 入力内容や認証など、クライアント側に問題がある場合です。
- 5xx:サーバーエラー(Server Error) → サーバー側で予期しない問題が起きた場合です。
ここまでの話だと少し抽象的なので、次の章から 具体的にどのコードをどう使うのか を見ていきます。
詳細解説:よく使うHTTPステータスコード
ここでは、実務で遭遇しやすいステータスコードを中心に解説します。
すべてを一度に暗記する必要はありませんが、「この状況ではこのコードを使う」というイメージを持てるように整理していきます。
2xx:成功系ステータスコード
200 OK
最もよく使われるステータスコードです。
意味としては「リクエストは問題なく処理でき、期待通りの結果を返しました」という状態を表します。
たとえば、ユーザー一覧を取得するAPIがあるとします。
GET /users HTTP/1.1
Host: example.comこれが正常に処理され、ユーザー一覧のJSONを返せた場合は、
HTTP/1.1 200 OK
Content-Type: application/json
[ ... ユーザー一覧 ... ]のように返します。
201 Created
新しいリソースが作成されたとき に返すステータスコードです。
主に POST で新規作成した場合に使います。
例えばユーザー作成APIで、新しいユーザー id=123 が作られたケースを考えます。
HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json
{ "id": 123, "name": "..." }このように Locationヘッダで新しく作られたリソースの場所を示す と、より親切です。
APIクライアントは 201 Created を見れば、「あ、新しく作られたのだな」とすぐに判断できます。
204 No Content
処理は成功したものの、返すべき内容が特にないとき に使います。
典型的な例は DELETE です。
DELETE /users/123 HTTP/1.1これが正常に処理され、対象ユーザーが削除された場合、
HTTP/1.1 204 No Contentとだけ返すことができます。
余計なボディを返さないことで、クライアント側にも分かりやすく、通信量も減らせます。
3xx:リダイレクト系ステータスコード
画面遷移やURLの変更など、「別の場所へ案内したい」ときに使います。
301 Moved Permanently
恒久的な移動 を表します。
「今後はこのURLではなく、こちらの新URLを使ってください」という意味になります。
たとえば、ブログのURL構造を変更した場合などに使います。
ブラウザや検索エンジンは、301 を見て新しいURLを記憶してくれます。
302 Found(や 307 / 308)
一時的なリダイレクト に使います。
歴史的な経緯もあり、302 はブラウザによって扱いが微妙に違う面があります。
最近はより厳密な意味でのリダイレクトとして、
- 307 Temporary Redirect
- 308 Permanent Redirect
を使う場面も増えていますが、初学者向けとしては 「302 は一時的な移動」 という理解で問題ありません。
304 Not Modified
キャッシュの文脈で使うステータスコードです。
クライアント側のキャッシュがまだ有効な場合、「そのまま使って大丈夫です」という意味で 304 を返します。
これにより、サーバーは同じデータを何度も返さずに済み、クライアントもレスポンスを高速に処理できます。
4xx:クライアントエラー系ステータスコード
リクエストに問題がある場合 に使います。
ここでのポイントは、「誰が悪いのか」という観点で考えることです。
クライアント側の指定や入力内容に問題があるときは 4xx になります。
400 Bad Request
リクエストが不正で、サーバーが意味を解釈できない場合 に使います。
例としては、
- JSON が壊れていて解析できない
- 必須パラメータがまったく送られていない
- 全く想定外の形式でリクエストされている
などです。
ただし、400 は意味が広すぎるため、もう少し理由を細かく区別したい場合は 422 を使うこともあります(後述します)。
401 Unauthorized
認証が必要なのに、認証が行われていない、または認証情報が無効な場合 に返します。
ポイントは、「誰かとしてログインしているかどうか」です。
- トークンがない
- トークンの有効期限が切れている
- 認証ヘッダの形式が不正
といった場合は 401 を返すのが自然です。
403 Forbidden
認証は済んでいるが、そのユーザーにはその操作を行う権限がない場合 に返します。
イメージを建物に例えると、次のようになります。
- 401:入口で身分証の確認に失敗した → そもそも建物に入れません
- 403:建物には入れたが、特定の部屋には入る権利がない → 「ここから先は関係者以外立ち入り禁止です」
この違いを意識すると、401 と 403 の使い分けがかなり整理されます。
404 Not Found
リソースが見つからない場合 に返します。
典型的には、指定されたIDのデータが存在しないときです。
例えば /users/99999 にアクセスされたが、そのIDのユーザーが存在しない場合、
HTTP/1.1 404 Not Foundを返します。
実務では、「アクセス権がないリソースに対して 403 を返すか、存在しないように見せるために 404 を返すか」という悩ましいケースもあります。
このあたりは後ほど「実務でのポイント」で改めて整理します。
409 Conflict
リソースの状態が他と競合していて処理できない場合 に使います。
具体例としては、
- 既に同じユーザー名が存在している
- バージョン番号を使った更新処理で、クライアントが持っているバージョンとサーバー側のバージョンが食い違っている
- 同じリソースを複数クライアントが同時に更新しようとしている
などがあります。
「内容は理解できるし、形式も正しいが、今の状態とは整合性が取れない」というイメージです。
422 Unprocessable Entity
リクエストの形式は正しいものの、ビジネスルール的に処理できない 場合に使います。
例えば、
- パスワードが短すぎる
- メールアドレス形式は正しいが、そのドメインは許可していない
- 「終了日時」が「開始日時」より前になっている
など、「JSON としては正しいが、内容に問題がある」という場面です。
400 と 422 の違いは迷いやすいですが、分けておくと API利用者に原因を伝えやすくなる ため、実務ではよく使われます。
5xx:サーバーエラー系ステータスコード
サーバー側に問題があるときに使います。
リクエストが悪いというより、「サーバーの都合で正常に処理できませんでした」という状態です。
500 Internal Server Error
もっとも代表的なサーバーエラーです。
予期しない例外が発生したり、アプリケーション内部で不整合が起きた場合などに返します。
外部にはあまり詳細を出さず、このコードだけ返しつつ、サーバー側のログで詳細を追いかける という運用が多いです。
503 Service Unavailable
サービスを一時的に利用できない場合に返します。
例えば、
- サーバーが高負荷で、処理を受け付けられない
- メンテナンス中でサービスを止めている
- 依存している外部サービスがダウンしている
といったケースです。
「しばらくしてからもう一度試してください」という状況を表すことが多く、
Retry-After ヘッダを組み合わせて、「何秒後ならリトライしても良いか」を示す場合もあります。
実務でのステータスコード運用ポイント

ここからは、実際の開発・運用の現場で迷いやすいポイントに絞って整理していきます。
ポイント1:とりあえず200で返す、は後で困ります
小さなAPIであれば、すべて 200 OK で返しても動いてしまいます。
しかし、実際に運用してみると
- クライアント側で原因を切り分けにくい
- ログを見ても、どんなエラーなのか一目で分からない
- 仕様書を書いたときに「結局成功なのか失敗なのか」が曖昧になる
といった問題が起きます。
HTTPステータスコードは、APIの挙動を圧縮して表現する大事な情報 です。
少し手間でも、「このパターンは 4xx にすべきか、5xx にすべきか」「このエラーは 400 か 422 か」といった考えを整理しておくと、長い目で見てかなり楽になります。
ポイント2:4xx と 5xx の境界は「原因がどちらにあるか」
エラーが発生したときにまず考えたいのは、「誰が原因を作っているのか」という視点です。
- 4xx:クライアント側の入力や操作の問題
- 5xx:サーバー側の内部的な問題
たとえば、バリデーションエラーの結果として DB 登録に失敗した場合は 4xx になります。
一方、DB 接続自体が落ちていて書き込みができない場合は 5xx の扱いが自然です。
「クライアントが入力を頑張っても改善しない問題かどうか」を基準に考えると、かなり整理しやすくなります。
ポイント3:400 と 422 の使い分け
実務でよく話題になるのが、400 と 422 のどちらを使うか という話です。
ざっくり整理すると次のようになります。
- 400 Bad Request → リクエスト形式が明らかにおかしくて、そもそも解釈できません 例:JSON が壊れている、必須フィールドが完全に抜けている
- 422 Unprocessable Entity → 形式は正しいが、ビジネスルール的に受け付けられません 例:規定より短いパスワード、開始日より前の終了日
これを人にたとえると、
- 400:何を言っているか聞き取れない
- 422:言っている日本語は分かるが、内容がおかしい
というイメージです。
APIのドキュメントを書くときも、この線引きができていると、
「このエラーは入力ミス」「このエラーはビジネスルール違反」という説明がしやすくなります。
ポイント4:401 と 403 の線引き
401 と 403 は、言葉だけ見るととても似ていますが、役割はかなり違います。
- 401 Unauthorized → 誰なのか分からないので、まずは名乗ってください(認証していません)
- 403 Forbidden → 誰なのかは分かっていますが、その人にはこの操作を許可していません(権限がありません)
たとえば社内の管理画面で、
ログインしていない状態のアクセスであれば 401、
一般ユーザーが管理者専用ページにアクセスした場合は 403 になります。
この違いを意識しておくと、権限まわりの仕様が整理しやすくなり、
フロントエンド側でも、「ログイン画面に戻すべきか」「権限エラーの画面を出すべきか」が判断しやすくなります。
ポイント5:404 と 403 どちらを返すか問題
APIを設計していると、「このケースは 403 にするべきか、それとも存在しないように見せるために 404 にするべきか」という場面が出てきます。
例えば、「他人の注文履歴」にアクセスするAPIを考えます。
IDとしては存在しているが、そのユーザーには見せてはいけないデータだとします。
- セキュリティ重視 の考え方 → 存在しているかどうかも漏らしたくないので、404 Not Found を返します 「そのようなリソースはありません」という態度を貫きます。
- 正確な意味の重視 の考え方 → 「リソースはあるが、あなたには見せられない」ので、403 Forbidden を返します
どちらが絶対に正しいというわけではありません。
大事なのは、サービス全体で方針を統一すること です。
- 認可エラーは基本的に 403 にする
- セキュリティ上見せたくないリソースは 404 に寄せる
など、チームの中でルールを決めておくと、あとから仕様を追う人が迷いにくくなります。
ポイント6:409 をうまく使うと、クライアントが実装しやすくなります
多くのプロジェクトでは、409 Conflict はあまり積極的に使われませんが、
状態の競合を表現するのに非常に便利なステータスコード です。
例えば、楽観的ロックを使った更新APIを考えます。
- クライアントは「バージョン1」のデータを取得
- ユーザーが編集している間に、別のクライアントが「バージョン2」に更新
- 最初のクライアントが「バージョン1」を元に更新リクエストを送る
このとき、「すでに新しいバージョンがあるので、あなたの更新は上書きできません」と伝えたい場合、
409 を返すと、「これは競合だ」と一目で分かります。
クライアント側も、
- 最新の状態を取得し直す
- 差分をマージする
- ユーザーに競合を知らせる
といった対処を実装しやすくなります。
一問一答:よくある迷いどころをサクッと整理
最低限おさえておくと便利なポイントを、短い一問一答形式でまとめます。
- POST と PUT の成功時はどのステータスを返すべきですか?
-
- POST で新規作成 → 201 Created(Location で新リソースのURLを返すと親切です)
- PUT で更新 → 200 OK(更新後の情報を返す) → または 204 No Content(ボディなし)
どちらもよく使われるため、プロジェクト内で統一しておくとよいです。
- DELETE の成功時はどのステータスがよいですか?
-
返すべき情報が特にない場合は、204 No Content が自然です。
もし「削除済みフラグ」や「削除結果の詳細」などを返したい場合は、200 OK でボディを返すこともあります。
- バリデーションエラーは 400 と 422 どちらですか?
-
- JSON 自体が壊れている、形式が大きく間違っている → 400 Bad Request
- JSON としては正しいが、入力内容がルールに反している → 422 Unprocessable Entity
という分け方が一般的です。
どちらかに寄せる場合でも、「このプロジェクトではこう使う」と決めておくと混乱しにくくなります。
- 内部エラーが起きたけれど、外に詳細は出したくない場合は?
-
その場合は 500 Internal Server Error を返し、
詳細はサーバー側のログに出力しておく運用が一般的です。
クライアント側には「内部で問題が発生した」とだけ伝え、
ログを元に開発者が原因を特定します。
まとめ:HTTPステータスコードの使い分けは「原因」と「状態」で考える
HTTPステータスコードは、最初は「数字がたくさんあって難しそう」に見えますが、
見方を少し変えると、そこまで複雑ではありません。
整理すると、次のポイントがおさえどころになります。
- まずは大分類(2xx / 3xx / 4xx / 5xx)で考える → 成功なのか、リダイレクトなのか、クライアント側の問題なのか、サーバー側の問題なのかを意識します。
- 4xx と 5xx の境界は「原因がどちらにあるか」で判断する → 入力や操作の問題なら 4xx、内部エラーなら 5xx です。
- 400 / 401 / 403 / 404 / 422 / 409 など、意味の違いをざっくり押さえる → 認証・権限・存在有無・ビジネスルール・競合など、伝えたい情報に合わせて選びます。
- プロジェクト全体で方針を統一する → どのパターンでどのコードを返すかを決めておくと、開発者同士の認識ずれが減ります。
ステータスコードの使い分けが整理されているAPIは、
- デバッグがしやすい
- 利用者が挙動を理解しやすい
- ドキュメントも書きやすい
というメリットがあります。
日々の開発の中で、「このケースはどのステータスコードがしっくりくるか」という視点を少しだけ意識してみると、
API設計の精度や読みやすさが、じわじわと上がっていきます。
必要なときに見返しながら、自分やチームの中での「ステータスコードの使い分けルール」を少しずつ育てていっていただければと思います。

