.htaccessで301リダイレクトを設定する方法|ページ・ディレクトリ・https・www統一の書き方

2025.07.11

.htaccessで301リダイレクトを設定する方法|ページ・ディレクトリ・https・www統一の書き方

ページのURLを変えたとき、サイトを別のドメインへ移転したとき、常時SSL化(https化)したときは、古いURLにアクセスした人を新しいURLへ自動で案内する「301リダイレクト」を設定します。Apacheのサーバーなら、.htaccessに数行書くだけで設定できます。

この記事では、301リダイレクトの基本から、ページ単位・ディレクトリ単位・別ドメインへの転送、httpsやwwwあり・なしの統一、一部だけ転送しない書き方、WordPressで使うときの注意、うまく動かないときの確認ポイントまでを解説します。

301リダイレクトとは

301リダイレクトは、「このページは新しいURLへ恒久的に移動しました」とブラウザや検索エンジンに伝えて、新しいURLへ転送する仕組みです。「301」はHTTPのステータスコードの番号です。主に次のような場面で使います。

  • ページやディレクトリのURLを変えた
  • サイトを別のドメインへ移転した
  • 常時SSL化して、httpからhttpsへ統一した
  • 「www.example.com」と「example.com」のどちらかに統一した

検索エンジンは301リダイレクトを見て、古いURLの評価を新しいURLへ引き継ぎます。URLを変えたのにリダイレクトを設定しないと、古いURLへのリンクやブックマークが「404 Not Found」になり、検索順位も一から積み直しになります。

302リダイレクトとの違い

301リダイレクト302リダイレクト
意味恒久的な移動一時的な移動
検索エンジンの扱い新しいURLを正式なURLとして扱う元のURLを正式なURLとして扱い続ける
ブラウザの扱い転送先を記憶し、次からはサーバーに問い合わせずに転送することがある毎回サーバーに問い合わせる
使いどころURLの変更、ドメイン移転、https化メンテナンス中の案内ページ、期間限定のキャンペーンページ

URLを恒久的に変えるときは301を使います。302を使い続けると、検索エンジンが新しいURLを正式なURLとして扱わないことがあります。

.htaccessでの2つの書き方

.htaccessでリダイレクトを書く方法は、大きく分けて2つあります。以下の例はすべて、サイトのいちばん上の階層(ドキュメントルート)に置く.htaccessに書く前提です。

Redirect(簡単な転送)

「このURLを、あのURLへ」と1行で書けます。ページやディレクトリを単純に移したときに向いています。

Apache
Redirect 301 /old-page.html https://example.com/new-page.html

1つ目のURLは「/」から始まるパスで、2つ目は転送先のURLです。?id=1 のようなクエリ文字列は、転送先にもそのまま引き継がれます。

RewriteRule(条件付きの転送)

「httpでアクセスされたときだけ」「このドメインでアクセスされたときだけ」のように、条件を付けて転送できます。https化やドメインの統一には、こちらを使います。

Apache
RewriteEngine On
RewriteCond 条件
RewriteRule 対象のパス 転送先 [R=301,L]
  • RewriteEngine On:書き換えの機能を有効にします。.htaccessの中で1回書けば十分です。
  • RewriteCond:転送する条件です。複数書くと、すべてを満たしたときだけ転送します。[OR] を付けると「どちらか一方」になります。
  • RewriteRule:対象のパス(正規表現)と転送先を書きます。R=301 は301で転送する、L はここで処理を終える、という意味です。R だけだと302になるので、必ず R=301 と書きます。

よく使うリダイレクトの書き方

特定のページを転送する

Apache
Redirect 301 /about.html https://example.com/company/

ディレクトリ以下をすべて転送する

Redirect にディレクトリを指定すると、その下のページもまとめて、同じ名前のページへ転送されます。たとえば次の例では、/blog/2025/post.html は /column/2025/post.html へ転送されます。

Apache
Redirect 301 /blog/ https://example.com/column/

ディレクトリの区切りで判定されるので、/blogs/ のような似た名前のディレクトリは対象になりません。

ページの対応が取れず、ディレクトリ以下のページをすべて1つのページへ集めたいときは、RedirectMatch を使います。

Apache
RedirectMatch 301 ^/campaign/ https://example.com/

別のドメインへ転送する

サイトを olddomain.com から newdomain.com へ移転した場合は、旧ドメインの.htaccessに次のように書きます。パスはそのまま引き継がれ、olddomain.com/about.html は newdomain.com/about.html へ転送されます。

Apache
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^ https://newdomain.com%{REQUEST_URI} [R=301,L]

%{HTTP_HOST} はアクセスされたドメイン名、%{REQUEST_URI} はドメインより後ろのパスです。[NC] は大文字・小文字を区別しない、という意味です。

httpからhttpsへ転送する

Apache
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

httpでアクセスされたときだけ、同じドメイン・同じパスのhttpsへ転送します。

wwwあり・なしを統一する(https化と同時に)

「www.example.com」と「example.com」の両方で同じページが開けると、検索エンジンに別のページとして扱われることがあります。https化と合わせて、どちらか一方へ統一しましょう。

wwwなしに統一する場合は、次のように書きます。httpでアクセスされたとき、またはwwwありでアクセスされたときに、「https://」+「wwwを除いたドメイン」へ転送します。

Apache
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]

wwwありに統一する場合は、2行目と最後の行を次のように変えます。

Apache
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]

%1 には、3つ目の RewriteCond の ( ) の部分、つまりwwwを除いたドメイン名が入ります。1回の転送で、httpsとwwwの両方が統一されます。

「index.html」を付けないURLに統一する

https://example.com/index.html と https://example.com/ を、/ で終わるURLに統一します。

Apache
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/(.*/)?index\.html[\s?]
RewriteRule ^(.*/)?index\.html$ /$1 [R=301,L]

%{THE_REQUEST} は、ブラウザから届いたリクエストそのものです。これを条件にすることで、ブラウザが「index.html」を付けてアクセスしたときだけ転送します。サーバーが内部で / を index.html に読み替えたときには転送しないので、無限ループになりません。

一部のページだけ転送しない(除外する)

ディレクトリ以下をまとめて転送しつつ、特定のページだけは残したいときは、RewriteCond に「このページではない」という条件を足します。! は「〜ではない」という意味です。

Apache
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog/archive\.html$
RewriteCond %{REQUEST_URI} !^/blog/images/
RewriteRule ^blog/(.*)$ https://example.com/column/$1 [R=301,L]

この例では、/blog/ 以下を /column/ へ転送しますが、/blog/archive.html と /blog/images/ 以下は転送しません。

転送先にクエリ文字列(? 以降)を引き継ぎたくないときは、[R=301,L,QSD] のように QSD を足します。

WordPressで使うときの注意

WordPressの.htaccessには、WordPressが自動で書き換える「# BEGIN WordPress」から「# END WordPress」までの部分があります。リダイレクトは、必ずこの部分より前に書いてください。

Apache
# リダイレクト(ここに書く)
Redirect 301 /old-page/ https://example.com/new-page/

# BEGIN WordPress
(WordPressが書き込んだ部分)
# END WordPress

WordPressの部分には、「実在しないファイルへのアクセスは、すべてWordPress(index.php)に渡す」という設定が入っています。WordPressの記事や固定ページのURLは実在するファイルではないので、リダイレクトを後ろに書くと、その前でWordPressに処理が渡ってしまい、転送されません。また、「# BEGIN WordPress」の中に書くと、パーマリンクの設定を保存したときに消えてしまいます。

転送するURLが多い場合や、.htaccessを直接編集できない場合は、「Redirection」などのプラグインを使う方法もあります。管理画面から設定でき、転送の記録も残せます。

リダイレクトの確認方法

設定した後は、ステータスコードが301になっているか、転送先が正しいかを確認します。curlコマンドを使える場合は、次のように実行します。

ShellScript
curl -I http://example.com/old-page.html

結果に HTTP/1.1 301 Moved Permanently と、転送先が書かれた Location: の行があれば成功です。

ブラウザで確かめる場合は、デベロッパーツール(ChromeはF12キー)の「Network」タブを開き、「Preserve log」にチェックを入れてから古いURLにアクセスします。一覧の最初の行の「Status」が301になっていれば成功です。

リダイレクトが効かないときの確認ポイント

設定を変えたのに、前の転送先に飛ぶ

ブラウザは301の転送先を記憶するので、.htaccessを書き換えても、前の転送先へ飛び続けることがあります。シークレットウィンドウで開くか、ブラウザのキャッシュを削除してから確認してください。

転送先が正しいか自信がないうちは、まず R=302(302リダイレクト)で試し、問題がないことを確かめてから R=301 に変えると安全です。

「リダイレクトが繰り返し行われました」と表示される

転送先がもう一度同じ条件に当てはまり、転送が無限に続いています(リダイレクトループ)。たとえば Redirect 301 / https://example.com/ を同じサイトに書くと、転送先の / もまた転送の対象になります。

  • 転送先が、転送の条件に当てはまらないか確認する
  • CDNやロードバランサーを経由している環境では、サーバーまでの通信がhttpのため、httpsでアクセスしても %{HTTPS} が常に off になることがあります。その場合は、サーバー会社のマニュアルでhttps化の書き方を確認してください。
  • レンタルサーバーの管理画面に「常時SSL化」などの転送設定がある場合、.htaccessの設定と二重になっていないか確認する

まったく転送されない、500エラーになる

  • 書く位置:WordPressなど、ほかの書き換えの設定より前に書いているか確認します。
  • RewriteEngine On:RewriteRule の前に書いているか確認します。
  • サーバーの設定:RewriteRule は、mod_rewrite が有効で、.htaccessでの設定が許可されたサーバーでしか使えません。使えないと500エラーになります。サーバー会社のマニュアルを確認してください。
  • 書き間違い:Redirect の1つ目は「/」から始まるパスで書きます。転送先を「/」や「http」で始めないと、500エラーになります。

「#」付きのURLを転送したい

page.html#section2 の「#」以降は、ブラウザの中だけで使われ、サーバーには送られません。そのため、.htaccessで「#」以降を条件にした転送はできません。ページ単位で転送し、ページ内の位置はJavaScriptで調整するなどの方法を検討してください。

まとめ

  • URLを恒久的に変えるときは301リダイレクトを使い、一時的な転送には302を使う
  • 単純な転送は Redirect、条件付きの転送は RewriteRule で書く
  • https化とwwwあり・なしの統一は、1回の転送でまとめて行える
  • WordPressでは「# BEGIN WordPress」より前に書く
  • まず302で試してから301に変えると、ブラウザのキャッシュで困らない

.htaccessでは、リダイレクトのほかにもアクセス制限を設定できます。特定のIPアドレスだけに公開する方法は「.htaccessでIP制限をかける方法」、パスワードで保護する方法は「.htpasswd を使ったベーシック認証の完全ガイド」「Basic認証を特定のディレクトリだけにかける方法」で解説しています。

PAGE TOP