URLエンコードとは何か
URLエンコード(パーセントエンコード)は、URL に含めてはいけない文字を URL で運ぶための方法です。URL で使えるのは、ごく一部の英字、数字、記号だけです。それ以外の文字、つまりスペース、日本語、絵文字、アラビア語やキリル文字などは、各バイトを % と16進数2桁で書き表します。
使用は許されていても意味を持つ文字にも同じ方法を使います。? はクエリの始まり、& はパラメーターの区切りです。カレー & ライス を検索するなら、& を %26 として送らないと、サーバーは1つのパラメーターを2つと解釈します。
役割はそれだけです。URL の意味を変えずに、値を安全に URL の中に入れること。圧縮でも暗号化でもセキュリティフィルターでもありません。
文字が %XX になる仕組み
エンコードは文字ではなくバイトに対して行います。まずテキストを UTF-8 のバイト列にし、エンコードが必要なバイトを % と16進数の値で書きます。
ASCII の文字は1バイトなので、スペース(バイト値32、16進数で20)は %20 になります。ASCII 以外の文字は UTF-8 で2〜4バイトを使い、バイトごとにエスケープされます。
あ→ バイト E3 81 82 →%E3%81%82円→ バイト E5 86 86 →%E5%86%86😀→ バイト F0 9F 98 80 →%F0%9F%98%80
デコードはその逆で、バイトを集めて UTF-8 として読みます。バイトが Shift_JIS など別の文字コードで作られていた場合、結果は文字化けします。最近のブラウザーやフレームワークはすべて UTF-8 を使っており、あなたもそうすべきです。
予約文字・非予約文字と文脈の重要性
RFC 3986 は URL の文字を2つのグループに分けています。
非予約文字(A–Z a–z 0–9 - . _ ~)はエンコードの必要がありません。エンコードしても構いませんが意味はなく、良いエンコーダーはそのまま残します。
予約文字(: / ? # [ ] @ ! $ & ' ( ) * + , ; =)は URL の構造を作ります。エンコードするかどうかは場所次第です。パスの区切りの / はスラッシュのままにし、パラメーターとして渡すファイル名の中の / は %2F にします。そのため「URL をエンコードする」唯一の正しい方法はなく、行き先に合わせて部分ごとにエンコードします。
encodeURIComponent と encodeURI
JavaScript には組み込み関数が2つあり、間違った方を選ぶのが URL のバグで最も多い原因です。
| 関数 | 用途 | エンコードしない文字 |
|---|---|---|
encodeURIComponent | 1つの値:パラメーター、パスの一部 | 非予約文字のみ |
encodeURI | そのまま使えるべき URL 全体 | 予約文字も |
a&b=c のような値に encodeURI を使うと、& と = が残り、1つのパラメーターが2つになります。URL 全体に encodeURIComponent を使うと、/ や : がすべてエスケープされ、リンクとして機能しなくなります。原則として、URL は部品から組み立て、値ごとに encodeURIComponent でエンコードするか、URLSearchParams に任せましょう。
ほかの言語にも同じ区別があります。Python の quote と quote_plus、PHP の rawurlencode と urlencode です。当サイトの URLエンコード・デコードツールは両方のモードを備えているので、手元の文字列で違いを確かめられます。
+ か %20 か:フォームの例外
パスではスペースは %20 で、+ はただのプラス記号です。ところが既定の application/x-www-form-urlencoded で送信される HTML フォームは、クエリ内のスペースを + にエンコードし、サーバーがそれをスペースに戻します。
問題は2つの決まりが混ざったときに起きます。+81 3-1234-5678 のような電話番号をエンコードせずにクエリへ入れると、サーバーが + をスペースと読むため 81 3-1234-5678 として届きます。解決策はプラスを %2B にエンコードすることで、フォームの規則に従うエンコーダーはそうします。相手がどちらの決まりを期待しているか分からないときは、スペースに %20、プラスに %2B を使えば常に安全です。
二重エンコードと %2520 のバグ
%25 は % 記号そのものをエンコードした形です。そのため URL に %2520 があれば、それは %20 がもう一度エンコードされたもの、つまりエンコード済みの値が再びエンコーダーを通ったということです。
たいていは境界で起こります。呼び出し側がすでにエンコードしたパラメーターをフレームワークがさらにエンコードしたり、リダイレクト先 URL を別の URL に入れるために一度エンコードし、ライブラリがもう一度エンコードしたりする場合です。症状としては、404、%20 という文字列そのものでの検索、% だらけのファイル名などが現れます。
2回デコードすれば元に戻りますが、本当の修正は2つ目のエンコーダーを見つけて取り除くことです。値を URL に入れるその時点で、ちょうど1回だけエンコードしましょう。
エンコードはエスケープでも暗号化でもない
パーセントエンコードは値を URL の中で 安全にするだけで、HTML や JavaScript、SQL には何の効果もありません。サーバーが %3Cscript%3E をデコードすれば、ごく普通の <script> に戻ります。出力は行き先に合わせてエスケープし、データベースのクエリにはパラメーターを使う必要があります。
秘密を守るものでもありません。URL は誰でもデコードでき、サーバーのログ、ブラウザー履歴、解析ツール、次のページの Referer ヘッダーに残ります。「ぐちゃぐちゃに見える」からといって、パスワード、トークン、個人情報をクエリに入れてはいけません。Base64 のガイドで説明しているとおり、Base64 も同じです。
デコードがうまくいかないとき
URL の問題の多くは次のいずれかです。
- 「URIError: malformed URI sequence」。
%の後に16進数2桁がないか、バイト列が正しい UTF-8 ではありません。% 記号そのものは%25として送る必要があります。 - 日本語が文字化けする、または � になる。ある文字コードで書いたバイトを別の文字コードで読んでいます。両側で UTF-8 を使っているか確認してください。
- パラメーターが & で途切れる。値をエンコードしていないか、
encodeURIComponentではなくencodeURIを使っています。 - プラス記号がスペースになる。フォームのデコードで
+がスペースとして扱われました。本物のプラスは%2Bにエンコードします。 - %2520 や %253D など。二重エンコードです。2つ目のエンコーダーを探しましょう。
URL をデコーダーに貼り付け、クエリパラメーターを1つずつ確認すれば、たいていは数秒で原因が分かります。
関連ツールとガイド:
- URLエンコード・デコード - テキストや URL 全体をパーセントエンコードし、%XX を元に戻して各パラメーターを確認。
- Base64 エンコーダー・デコーダー - テキストを Base64 に変換したり元に戻したり。URL セーフ出力と UTF-8 に対応。
- Base64 解説: エンコードとデコードの仕組み
よくある質問
URLエンコードとは何ですか?⌄
URLエンコード(パーセントエンコード)は、URL で使えない文字を、UTF-8 の各バイトごとに % と16進数2桁で書き表す方式です。スペースは %20、「あ」は %E3%81%82 になります。これにより、どんなテキストでも意味を変えずに URL に載せられます。
スペースが + のときと %20 のときがあるのはなぜ?⌄
application/x-www-form-urlencoded で送信される HTML フォームは、クエリ内のスペースを + にエンコードします。パスやほとんどの API など、それ以外の場所ではスペースは %20 で、+ はプラス記号そのものです。%20 は常に安全です。
encodeURI と encodeURIComponent のどちらを使うべき?⌄
クエリパラメーターやパスの一部など単一の値には、&、=、/、? もエンコードする encodeURIComponent を使います。encodeURI は構造を保つ必要がある URL 全体にだけ使います。
%2520 とは何ですか?⌄
二重にエンコードされたスペースです。%25 は % 記号なので、%2520 は %20 をもう一度エンコードしたものです。2回デコードすれば読めます。その後、値を2回エンコードしているコードを修正してください。
URLエンコードは安全ですか?⌄
いいえ。誰でも元に戻せて秘密は守られず、デコード後の入力にインジェクション攻撃が含まれることもあります。HTML には出力のエスケープ、データベースにはパラメーター化クエリを使い、URL に秘密情報を入れないでください。
Web 開発とセキュリティに 15 年以上携わってきた実務経験を持つ。実践的な Web セキュリティ、つまりサイトを安全・確実に保ち、トラブルを素早く解決できるようにすることに注力。BuildToolForge は、こうしたチェックを無料で、プライベートに、わかりやすく行えるようにするためのサイトです。ツールは可能な限りブラウザ内で動作し、ツールに入力した内容は保存されません。
ガイドの書き方: すべてのガイドは実務経験をもとに執筆し、公式の標準と照らし合わせ、実際のドメインで自社ツールを使って検証しています。標準やツールが変わればガイドも更新します。誤りを見つけたら contact@buildtoolforge.com までお知らせください。