ブラウザーの開発者ツールを開いたら、ネットワークの一覧に「307」の文字が並んでいた。あるいは、プログラムのログに「307 Temporary Redirect」と出力されていた。そんな場面で「サーバーエラーが起きているのでは」と不安になった方は多いはずです。

結論から言うと、307 はエラーではありません。「このリソースは、いまは別の URL にあります。そちらへ同じ要求を送り直してください」というサーバーからの案内です。HTTP のステータスコードは番号の先頭の数字で大まかな性格が分かれていて、3 で始まるものはリダイレクト(転送)を表します。エラーを表すのは 4 で始まるもの(クライアント側の問題)と、5 で始まるもの(サーバー側の問題)です。

分類

3xx のリダイレクト。エラーではなく、転送の案内です。

意味

いまは別の URL にあります。元の URL は今後も使い続けてください。

最大の特徴

要求メソッドと本文を変えずに、移動先へ送り直させます。

定義

RFC 9110 の 15.4.8 に定められています(確認日: 2026年10月9日)。

「エラー」と呼ばれがちな 307 が、本当に困る場面

307 そのものは正常な応答ですが、実際の現場では「307 のせいで困った」という相談が絶えません。困りごとは、おおむね次の 3 つに分かれます。

1 つ目は、リダイレクトが終わらない問題です。移動先からさらに別の場所へ、そして元の場所へと転送が続くと、ブラウザーは途中で通信をあきらめ、「リダイレクトが多すぎます」といったエラー画面を表示します。このとき画面に出るのはエラーですが、原因は 307 という応答そのものではなく、転送の設定の組み合わせにあります。

2 つ目は、API やスクリプトからの通信で、転送先に要求が届かない問題です。HTTP クライアントの中には、リダイレクトを自動では追いかけない設定のものがあります。その場合、307 が返ってきた時点で処理が止まり、呼び出し側からは「失敗した」ように見えます。

3 つ目は、開発者ツールに 307 が大量に並び、サーバーが不具合を起こしているように見える問題です。これはブラウザーが自分で作り出した転送の記録であることが多く、後述するように、実際にはサーバーへ要求が出ていない場合もあります。

つまり、困りごとの大半は「307 を誤解していた」か「転送の設定が噛み合っていなかった」のどちらかです。仕組みを正しく押さえておけば、慌てる必要はありません。

307 が伝えていること

HTTP の標準仕様である RFC 9110 は、307 を次のように位置づけています。対象のリソースは一時的に別の URI にあり、ユーザーエージェント(ブラウザーなどのクライアント)が自動でリダイレクトを行う場合は、要求メソッドを変更してはならない。転送は時間とともに変わりうるので、クライアントは今後も元の URI を使い続けるべき、という内容です。

ここには 2 つの重要な約束事があります。

約束その 1: メソッドを変えない

たとえば、フォームの内容を POST で送信したとします。サーバーが 307 で別の URL を案内したら、クライアントは移動先にも POST で、同じ本文を送り直します。GET に切り替えたり、本文を捨てたりしてはいけません。

約束その 2: 元の URL は今後も有効

307 は「一時的な」移動です。クライアントは、次回以降も最初の URL にアクセスします。移動先の URL を覚えて、次からそちらへ直接行く、という動きは想定されていません。恒久的に移ったことを伝えたいときは、301 や 308 の役割になります。

サーバーが添える Location ヘッダー

307 の応答には、移動先を示す Location ヘッダーを付けるのが基本です。RFC 9110 でも、サーバーは Location を含めるべきとされています。クライアントは、その値を元の要求の URL に対して解決した結果へ移動します。つまり、Location には絶対 URL だけでなく、相対的な指定も書けます。

実際のやり取りは、次のようになります。

clientserver

POST /orders HTTP/1.1
HTTP/1.1 307 Temporary Redirect
Location: https://shop.example.com/orders
クライアントは、移動先にも POST で同じ本文を送り直します
POST https://shop.example.com/orders
HTTP/1.1 201 Created

最初の応答が 307 でも、最終的な結果は 201 のような成功のステータスになります。この流れを知っていれば、ログに 307 が見えること自体は、まったく心配いりません。

307 が生まれた歴史的な理由

307 という番号がなぜ必要になったのかは、歴史を知ると腑に落ちます。

初期の HTTP では、一時的な移動を表す 302 は「メソッドを変えてはならない」前提で作られていました。ところが現実には、多くのブラウザーが 302 を受け取ると、POST を GET に切り替えて移動先へ向かう実装になっていきました。1999 年 6 月に公開された RFC 2616(HTTP/1.1)には、この状況がそのまま書かれています。以前の仕様では 302 でメソッドを変えることを禁じていたが、既存のユーザーエージェントの多くは 302 を 303 のように扱っている、という趣旨の注記です。

実装が先に進んでしまった以上、302 の意味を後から固定することはできません。そこで RFC 2616 は、サーバーが期待する動作を曖昧にさせないために、303 と 307 を追加しました。「GET で取得し直してほしい」場合は 303、「メソッドを保ったまま送り直してほしい」場合は 307、という役割分担です。

その後の RFC 9110(2022 年に公開された、現在の HTTP の意味論の仕様)も、301 と 302 では POST から GET への変更を認めたうえで、メソッドを保ちたいなら 307 や 308 を使うよう案内しています。つまり 307 は、長年の実装の揺れを整理するために生まれた、意図をはっきり伝えるための番号なのです。

3xx の仲間のなかでの位置づけ

リダイレクトを表すステータスコードは、一つではありません。主なものを並べると、307 の立ち位置が分かりやすくなります。

コード 名称 恒久/一時 自動転送でのメソッド
301 Moved Permanently 恒久 POST が GET に変わることがある
302 Found 一時 POST が GET に変わることがある
303 See Other 一時 GET(または HEAD)で取得し直す
307 Temporary Redirect 一時 変えない
308 Permanent Redirect 恒久 変えない

RFC 9110 は、301 と 302 について、ユーザーエージェントが POST を GET に変えてもよい(MAY)と書いています。これは、仕様が整う前に実装が先行した歴史的な経緯によるものです。メソッドを確実に保ちたい場合の選択肢として、一時的な転送には 307、恒久的な転送には 308 が用意されました。

違いをさらに詳しく知りたい場合は、301・302・303・307・308 の違いと、307 と 302 の違いも合わせてご覧ください。

一時的な移動を、正しく伝えられる強み

ここからは、307 を理解しておくことで得られる利点です。

利点 1: 書き込み系の通信を安全に転送できる

GET だけのページであれば、301 でも 302 でも大きな差は出ません。しかし、フォーム送信や API の更新処理のように、POST・PUT・DELETE を使う通信では話が変わります。メソッドが勝手に GET へ変わると、更新が実行されないまま「成功したように見える」事態も起こりえます。307 を使えば、仕様上、メソッドと本文が維持されるため、転送の前後で処理の意味が変わりません。

利点 2: 「いつか元に戻す」移動に向いている

メンテナンス中だけ別のサーバーへ振り向ける、一時的に負荷分散先を切り替える、障害時に代替の場所へ案内する、といった用途です。307 は「元の URL を今後も使ってほしい」という意思表示そのものなので、あとで元に戻したときに、クライアント側に古い転送先が残りにくい設計になっています。

利点 3: キャッシュの扱いが明確

RFC 9110 は、300・301・308 を、明示的な指定がなくても保存してよい(ヒューリスティックにキャッシュ可能な)応答として扱っています。302 や 307 は、そこに含まれていません。サーバーが Cache-Control や Expires で保存期間を明示した場合にだけ、キャッシュの対象になります。何も指定しなければ、一時的な転送がいつまでも残る心配は小さくなります。

利点 4: 検索エンジンにも「一時」と伝わる

Google 検索セントラルの文書では、307 は 302 と同等に扱われ、リダイレクト先を正規 URL とする弱いシグナルとして処理されます。一時的な移動を伝える目的に合っています。詳しくは検索エンジンとの関係で解説します。

ブラウザーが作る「307 Internal Redirect」も知っておく

開発者ツールで、サーバーに要求を出していないのに 307 が表示されることがあります。これは、ブラウザーが HSTS(HTTP Strict Transport Security)の設定にしたがって、http の URL を https に自分で書き換えた記録です。Chromium のソースコードでは、このとき状態コードに 307 を使う理由を「メソッドを保つことで、POST 要求が正しく動くようにするため」と説明しています。

この場合の 307 は、サーバーが返したものではありません。サーバー側の設定を直す必要はなく、むしろ HSTS が正しく働いている証拠です。詳しくは307 Internal Redirect と HSTSで説明しています。

307 を見かけたときの確認ポイント

実務で 307 に出会ったら、次の順に確認すると、原因の切り分けが進みます。

  1. 移動先(Location)を確認する。 意図した URL に向いているか、同じ場所へ戻っていないかを見ます。
  2. 転送の回数を確認する。 1 回で最終ページに着くなら正常です。何度も続くなら、設定の組み合わせを疑います。
  3. 要求メソッドを確認する。 POST が移動先でも POST のままなら、307 の約束どおりに動いています。
  4. サーバーが返したものか、ブラウザーが作ったものかを見分ける。 後者なら、サーバー側の対処は不要です。

コマンドラインなら、curl -i で応答ヘッダーを確認できます。リダイレクトを追いかけながら最終地点まで見るなら curl -iL です。curl は -L を付けると転送を自動で追いますが、POST は 301・302・303 では GET に変わり、それ以外の 3xx(307 や 308 を含む)では元のメソッドが保たれます。

手元で 307 の応答を確かめる

自分のサイトが返している応答を確かめるなら、次のようにヘッダーだけを取得するのが手軽です。-I を使うと HEAD 要求になるため、POST の動きを確かめたいときは -i と -X POST を組み合わせます。

# 応答ヘッダーを表示(転送は追わない)
curl -i https://example.com/old

# 転送を追いかけ、最終的な URL と転送回数だけを表示
curl -sL -o /dev/null -w '%{url_effective} %{num_redirects}\n' https://example.com/old

1 つ目のコマンドでは、HTTP/2 307 と location: の行が見えれば、サーバーが 307 を返しています。2 つ目のコマンドは、最終地点と転送回数を一行で確認できます。回数が想定より多いときは、転送の途中に余計な設定が挟まっているサインです。

307 は「正しく使えば頼れる案内役」

ここまでの要点を整理します。

  • 307 はエラーではなく、「いまは別の URL にあります」という一時的な転送の案内です。
  • 最大の特徴は、メソッドと本文を変えずに移動先へ送り直させる点です。
  • 恒久的な移動には 301 か 308、POST の後に結果画面へ移すには 303 と、役割に応じて使い分けます。
  • 開発者ツールに表示される「307 Internal Redirect」は、多くの場合ブラウザーによる HSTS の処理で、サーバーの不具合ではありません。

困ったときに疑うべきは 307 という番号そのものではなく、転送の行き先や回数、そして組み合わせです。次は、301・302・303・307・308 の違いを押さえておくと、リダイレクトの設計と原因調査の両方が、ぐっと楽になります。サーバーで 307 を返したい場合は、nginx、Apache、PHP それぞれの設定例が役立ちます。