URL エンコード / デコード

URL やクエリ文字列をパーセントエンコーディングで変換します。コンポーネント / 完全 URI / フォームデータの 3 モードに対応し、入力と同時に双方向変換します。

テキストを URL 用にパーセントエンコードし、元に戻します。 どちらの欄に入力しても、もう一方が即座に更新されます。値を使う場所に合わせてモードを選んでください。クエリパラメータ 1 個か、URL 全体か、HTML フォームの送信かで正解が変わります。

パーセントエンコーディングを正しく理解する

URL にエンコードが必要な理由

URL は自由なテキストではありません。?#&/= といった文字は予約文字であり、パスの終わりとクエリの始まりを示したり、パラメータ同士を区切ったりする構造上の意味を持ちます。送りたい値の中にこれらの文字が含まれていると、受信側のパーサーは URL を読み違えます。パーセントエンコーディングは、問題のバイトを % と 2 桁の 16 進数に置き換えることでこれを解決します。値の中の &%26 として運ばれ、区切り文字と誤認される余地がなくなります。

非予約文字・予約文字・その他

RFC 3986 は文字空間を 3 つに分けています。

  • 非予約文字A-Z a-z 0-9 - . _ ~。エンコードは不要で、そのまま残すべきです。エンコードしても違法ではありませんが、URL が見づらくなり、素朴な文字列比較が壊れることがあります。
  • 予約文字: / ? # [ ] @ ! $ & ' ( ) * + , ; =。構造として機能する位置でのみ安全で、値の中に現れる場合は必ずエンコードします。
  • それ以外 — 空白、制御文字、すべての非 ASCII テキスト。常にエンコードが必要です。

非 ASCII と UTF-8

パーセントエンコーディングは文字ではなくバイトに対して働くので、まずテキストをバイト列に変換します。現代的な答えは常に UTF-8 です。 は UTF-8 で 3 バイト(E2 82 AC)なので %E2%82%AC になります。古いシステムはページ自身の文字セットを使うことがあり、Latin-1 や GBK でエンコードされた文字化け URL に今でも出くわすのはそのためです。本ツールは一貫して UTF-8 を使い、ブラウザや現行のサーバーフレームワークの前提に合わせています。

3 つのモードと、それぞれの誤用

encodeURIComponent は安全な既定値で、予約文字をすべてエスケープします。URL の中に値を差し込むときは常にこれを使ってください。encodeURI は完全な URL を壊さないよう予約文字を意図的に残します。組み立て済みの URL を整えるときだけに使い、個々のパラメータには絶対に使わないでください。値の中の & をそのまま残し、クエリ文字列を壊してしまいます。

フォームモードは例外的な存在です。現代の URL 仕様より古い application/x-www-form-urlencoded の直列化では、空白は %20 ではなく + になります。クエリ文字列ではどちらも正しく、サーバーも両方受け付けますが、POST のボディを手作業で組み立てるならフォームの慣習に合わせるべきです。

+ の曖昧さ

フォームエンコードでは + に特別な意味があるため、フォーム値の中のリテラルなプラス記号は %2B としてエンコードしなければなりません。これは実務で最も多いエンコードのバグです。base64 文字列や国際形式の電話番号がそのまま渡され、受信側がすべての + を空白に変えてしまいます。データにプラス記号が入りうるなら、明示的にエンコードするかフォームモードを避けてください。

二重エンコード

エンコード済みの文字列をもう一度エンコードすると、各 %%25 になり、%20%2520 に変わります。これはたいていバグで、アプリ側でエンコードしたものをフレームワークやプロキシがもう一度エンコードすると起こります。リテラルなパーセント記号を意図していない場所に %25 が見えたら、二重エンコードされた値です。2 回デコードすれば元に戻りますが、本当の修正はエンコード処理を 1 つ取り除くことです。

オープンソースに関する注記:標準 JavaScript の encodeURIComponentencodeURIdecodeURIComponentdecodeURI で実装しています。サードパーティライブラリは使用していません。

よくある質問

空白は %20 と + のどちらを使うべきですか?
クエリ文字列ではどちらも有効です。どこでも通用する 1 つの表現がほしいなら %20 を使ってください。パスセグメントでは + はリテラルなプラス記号を意味します。+ は application/x-www-form-urlencoded データを作るときだけ使います。
プラス記号が空白になってしまうのはなぜですか?
経路のどこかで値がフォームデータとして解釈されており、そこでは + が空白を表すためです。送信前にリテラルなプラス記号を %2B にエンコードしてください。
スラッシュはエンコードが必要ですか?
パス区切りではなく値の一部である場合だけ必要です。スラッシュを含むファイル名は %2F で送らないと、サーバーはディレクトリが 1 階層増えたと解釈します。なお、ディレクトリトラバーサル対策として %2F を既定で拒否するサーバーもあります。
エンコードは大文字小文字を区別しますか?
16 進数の桁は大文字でも小文字でもよく、デコード結果は同じですが、RFC 3986 は大文字を推奨しています。%2F と %2f は同じ文字で、%2F が正規の書き方です。
デコードが失敗するのはなぜですか?
パーセント記号の後ろには 16 進数がちょうど 2 桁必要です。単独の % や %zz のような形式は不正で、デコーダーは例外を投げます。テキストに本当にパーセント記号が含まれるなら、それは %25 としてエンコードされているはずです。
データはどこかに送信されますか?
いいえ。エンコードもデコードもブラウザ内蔵の URI 関数でローカルに実行され、何もアップロードされません。