パーセントエンコーディングとは
URLにそのまま書けるのは、英数字といくつかの記号だけです。日本語、スペース、絵文字、さらにURLの構造を表す記号をデータとして使いたい場合は、 文字をUTF-8のバイト列に直し、各バイトを「%」と16進数2桁で書き表します。これがパーセントエンコーディング(URLエンコード)です。 たとえば「あ」はUTF-8で3バイト(E3 81 82)なので %E3%81%82 になり、スペースは1バイト(20)で %20 になります。 アドレスバーに日本語を入力して検索できるのも、ブラウザが裏で同じ変換をしているからです。
規格はRFC 3986で、文字は3種類に分けられます。非予約文字(英数字と - . _ ~)は変換不要。予約文字は : / ? # [ ] @ のようにURLの区切りを担うものと、! $ & ' ( ) * + , ; = のように各部分の中で使うものがあり、区切りではなくデータとして使うときにエンコードが必要です。 それ以外の文字は常にエンコードします。
encodeURIComponentとencodeURIの違い
JavaScriptの標準関数は2つあり、選び間違いがリンク破損の典型的な原因です。encodeURIComponentは検索語1つ、パス1区間のような「データ1個分」向けで、英数字と - _ . ! ~ * ' ( ) 以外をすべて変換します。encodeURIは構造が完成したアドレス全体向けで、; , / ? : @ & = + $ # も残すため、日本語やスペースだけを変換します。 たとえば「A&B」をクエリにそのまま入れると & がパラメータの区切りと解釈されて値が壊れるため、値には必ずencodeURIComponentを使います。このツールの初期設定が値モードなのはそのためです。
| 文字 | encodeURI | encodeURIComponent | 厳密(RFC 3986) | URLSearchParams |
|---|---|---|---|---|
スペース ( ) | %20 | %20 | %20 | + |
スラッシュ (/) | / | %2F | %2F | %2F |
疑問符 (?) | ? | %3F | %3F | %3F |
アンパサンド (&) | & | %26 | %26 | %26 |
イコール (=) | = | %3D | %3D | %3D |
シャープ (#) | # | %23 | %23 | %23 |
プラス (+) | + | %2B | %2B | %2B |
パーセント (%) | %25 | %25 | %25 | %25 |
コロン (:) | : | %3A | %3A | %3A |
角括弧 ([) | %5B | %5B | %5B | %5B |
アポストロフィ (') | ' | ' | %27 | %27 |
感嘆符 (!) | ! | ! | %21 | %21 |
チルダ (~) | ~ | ~ | ~ | %7E |
上の表はページ作成時に実際の関数で計算した結果です。encodeURIComponentは ! ' ( ) * を残しますが、RFC 3986ではこれらは非予約文字ではなくサブ区切り文字なので、 厳密に揃えたいときは厳密モードを使います。またencodeURIは [ と ] もエンコードする点にも注意してください。
スペースは%20か+か
一般的なURLのルールではスペースは %20 です。+ がスペースを表すのは、HTMLフォーム送信などで使う application/x-www-form-urlencoded という別の形式で、そこでは本物のプラスは %2B と書きます。decodeURIComponentは+をスペースに戻さないため、a+bは a+b のままです。フォーム形式のデータを戻すときは、上のチェックボックスをオンにしてください。迷ったときは、どこでも通じる %20 が無難です。
バイト数と文字数
| 入力 | 文字数 | UTF-8バイト数 | encodeURIComponent | encodeURI |
|---|---|---|---|---|
| あ | 1 | 3 | %E3%81%82 | %E3%81%82 |
| 東京タワー | 5 | 15 | %E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC | %E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC |
| こんにちは | 5 | 15 | %E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF | %E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF |
| café | 4 | 5 | caf%C3%A9 | caf%C3%A9 |
| 😀 | 1 | 4 | %F0%9F%98%80 | %F0%9F%98%80 |
| 100% | 4 | 4 | 100%25 | 100%25 |
| https://example.com/search?q=a&b=c | 34 | 34 | https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Da%26b%3Dc | https://example.com/search?q=a&b=c |
1バイトが3文字になるので、日本語1文字は9文字、絵文字は12文字に伸びます。最後の行のように、アドレス全体を整えるならencodeURI、別のURLのパラメータとして丸ごと渡すならencodeURIComponentが適しています。
計算例
例1。「東京タワー」は %E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC になります。https://example.com/search?q= の後ろに付ければ検索リンクの完成です。
例2。「100%」は 100%25 です。%自体もエンコード対象で、そのままデコーダーに入れると形式エラーになります。
例3(二重エンコード)。「a b」を一度エンコードすると a%20b、さらにもう一度エンコードすると a%2520b です。デコード結果に再び%XXが残っていたら、二重エンコードを疑って、もう一度デコードしてください。
エラーと限界
- デコードエラー。%の後ろに16進数2桁がない、途中で切れている、またはUTF-8として読めない場合に起きます。古いサイトのShift_JISやEUC-JPでエンコードされたURL(例:
%82%A0)は、UTF-8では読めずエラーになります。 - 対のないサロゲート。壊れた絵文字などはエンコードできません。
- 長さ。処理自体は速くても、URLの長さには制限があるため、目安として2,000文字以内に抑えるのが安全です。
- 範囲外。これは文字列変換ツールで、URLの構文解析や、日本語ドメイン(Punycode)の変換は行いません。
プライバシーと安全性
変換はブラウザ内蔵の関数だけで行い、通信も保存もしません。ただしエンコードは暗号化ではなく、誰でもすぐ元に戻せます。URLに入れた値はブラウザ履歴やサーバーのログに残ることがあるため、パスワードや個人情報をクエリに載せないでください。 不審なリンクはデコードして本当の宛先ドメインを確認すると、フィッシングの見極めに役立ちます。
活用のしかた
API呼び出しURLの手組み、ログに残った%記号つきの文字列の確認、計測用タグに日本語のキャンペーン名を入れる、リダイレクト先を別のURLのパラメータに入れる、といった場面で使えます。 プログラム内では、文字列連結よりURLSearchParamsなどの標準機能を使い、エンコードは値がURLに入る地点で1回だけにしましょう。エンコード後のアドレスをQRコードにしたいときは、QRコード生成ツールが使えます。
よくある質問
URL全体をエンコードするべきですか?
通常は検索語などパラメータの値だけです。アドレス全体を値モードで変換すると : や / も変換され、リンクとして開けなくなります。日本語だけ整えたい完成済みのアドレスにはURL全体モードを使います。
デコードするとエラーになります。
%の後ろが不足している、文字列が途中で切れている、UTF-8以外(Shift_JISなど)でエンコードされている、のいずれかが多い原因です。%そのものを書きたかった場合は %25 にしてください。
+と%20はどちらを使いますか?
迷ったら%20です。パスでは%20のみが正しく、クエリではどちらも通用します。本物のプラス記号は常に%2Bで表します。
英数字もエンコードされますか?
英数字と - _ . ~ は変換されません。値モードでは ! ' ( ) * も残りますが、厳密モードをオンにすると変換されます。
入力内容はサーバーに送られますか?
送られません。変換はすべてお使いのブラウザ内で完了します。ただしURLに機密情報を入れると、ログなどに残るおそれがあります。
関連ツール
- Base64エンコーダー/デコーダー - バイト列をテキストで運ぶもう一つの方法
- QRコード生成ツール - エンコード後のURLをQRコードに
- 正規表現テスター - 文字列の検証や抽出
- JSON整形ツール - パラメータに入れるJSONの整形