文字列を URL エンコードする方法
- テキストまたは URL にテキストを入力するか貼り付けます。出力は入力に合わせて更新されます。
- エンコード の下でモードを選びます。
- コンポーネント(encodeURIComponent):クエリの値 1 つ、フォームのフィールド、パスのセグメント 1 つに。
- URL 全体(encodeURI):スペースや非 ASCII 文字を含む完全な URL に。
- フォームデータ(空白を + に):
application/x-www-form-urlencodedのボディや、HTML フォームと同じ方式で作るクエリ文字列に。 - すべての文字:英字も含めすべてのバイトをパーセントエンコードします。デコーダーのテスト用です。
- 受け取る側のシステムがレガシーなエンコードを想定していない限り、文字コード は UTF-8 のままにしてください。
- 値のリストをまとめてエンコードするには 1 行ずつ処理 にチェックを入れ、出力をコピー します。入れ替え を押すと結果がデコーダーに送られ、往復変換を確認できます。
完全な URL を入力すると、スキーム、ホスト、パス、各クエリパラメータ、フラグメントにも分解され、入出力欄の下の表に表示されます。
encodeURIComponent、encodeURI、フォームエンコードの違い
同じ入力 a b&c=d/é?#+ を、よく使われる 3 つの方式で比べます。
| モード | 出力 | 用途 |
|---|---|---|
コンポーネント(encodeURIComponent) | a%20b%26c%3Dd%2F%C3%A9%3F%23%2B | URL 内の値 1 つ |
URL 全体(encodeURI) | a%20b&c=d/%C3%A9?#+ | すでに正しく組み立てられた URL 全体 |
フォームデータ(URLSearchParams) | a+b%26c%3Dd%2F%C3%A9%3F%23%2B | HTML フォームの送信、多くのクエリ文字列ライブラリ |
コンポーネント でエスケープされないのは A–Z a–z 0–9 - _ . ! ~ * ' ( ) だけです。URL 全体 はさらに ; / ? : @ & = + $ , # も残します。これらは URL の構造を作る文字なので、それを含む値は保護できません。フォームデータ が残すのは英字、数字、- _ . * だけで、スペースは + と書きます。
典型的なバグは、URL 全体 のエンコードで URL を組み立てることです。?q=C++ & Go では + と & が残り、サーバーは q=C と余計なパラメータを受け取ります。値は コンポーネント でエンコードしてください:?q=C%2B%2B%20%26%20Go。
スペース、プラス記号、その他の問題児
| 文字 | エンコード後 | 注意点 |
|---|---|---|
| スペース | %20 または + | + がスペースを意味するのはクエリ文字列とフォームボディの中だけ |
+ | %2B | エンコードしないと多くのサーバーがスペースに変える:+49 30 1234567 が 49 30 1234567 になる |
& | %26 | 新しいクエリパラメータの開始 |
= | %3D | 名前と値の区切り。標準の Base64 はこれで終わる |
/ | %2F | パスのセグメントを区切る。パス内の %2F を拒否するサーバーもある |
# | %23 | フラグメントの開始。フラグメントはサーバーに送られない |
% | %25 | これ自体もエンコードが必要。でないとデコーダーが壊れたエスケープとして読む |
€ | %E2%82%AC | UTF-8 で 3 バイト、エスケープも 3 つ |
URL に入れる Base64 は、+、/、= の問題がよく起こるケースです。コンポーネントとしてパーセントエンコードするか、これらの文字を使わない Base64URL に切り替えてください。
UTF-8 以外の文字コード
パーセントエンコーディングはバイト単位で働くので、結果は文字コードで決まります。é は UTF-8 なら %C3%A9、Windows-1252 や ISO-8859-1 なら %E9 です。最近のブラウザや API は UTF-8 を使いますが、古い PHP アプリケーション、一部の決済ゲートウェイ、レガシーな社内システムは今も Latin-1 や Windows-1252 を想定しており、日本のサイトでは Shift_JIS のこともあります。文字コード で相手に合わせてください。選んだ文字コードに存在しない文字は表現できないので、出力にそうした文字がないか確認してください。
コードでの URL エンコード
encodeURIComponent("a b&c") // "a%20b%26c"
new URLSearchParams({ q: "C++ & Go" }).toString() // "q=C%2B%2B+%26+Go"
from urllib.parse import quote, quote_plus, urlencode
quote("/files/a b.txt") # '/files/a%20b.txt' (keeps / by default)
quote("/files/a b.txt", safe="") # '%2Ffiles%2Fa%20b.txt'
quote_plus("a b&c") # 'a+b%26c'
urlencode({"q": "C++ & Go"}) # 'q=C%2B%2B+%26+Go'
Python の quote は、safe="" を渡さない限り / を残します。値をエンコードするときによく驚かされる点です。ほかの言語では、PHP の rawurlencode は %20、urlencode は + を使います。Java の URLEncoder.encode は + を使うフォームエンコードです。Go には url.PathEscape(%20)と url.QueryEscape(+)があります。encodeURIComponent は ! ' ( ) * をそのまま残すので、RFC 3986 に厳密に従った出力が必要なら、後から置き換えてください。
const strict = s => encodeURIComponent(s).replace(/[!'()*]/g,
c => "%" + c.charCodeAt(0).toString(16).toUpperCase());
JavaScript 側については JavaScript の Base64 のページ で詳しく解説しています。逆変換には URL デコーダー を使ってください。
よくある質問
URL エンコードとは何ですか?
URL エンコード(パーセントエンコーディング)は、URL で使えない文字や特別な意味を持つ文字を、% と各バイトの16進数 2 桁に置き換えるものです。スペースは %20、& は %26、UTF-8 の é は %C3%A9 になります。
URL のスペースは %20 と + のどちらでエンコードすべきですか?
%20 はどこでも使えます。+ がスペースを意味するのは、フォームエンコードの規則に従うクエリ文字列とフォームボディの中だけで、パスでは文字どおりのプラス記号です。迷ったら %20 を使ってください。
URL 全体を URL エンコードすべきですか?
いいえ。値を URL に入れる前に、値ごとにエンコードしてください。URL 全体を コンポーネント でエンコードすると :、/、?、& もエスケープされ、URL が壊れます。URL 全体 モードならこれらの構造上の文字は残し、スペースと非 ASCII テキストだけを直します。
エンコードした文字列に %25 が含まれるのはなぜですか?
%25 はエンコードされたパーセント記号です。つまり、すでにエンコード済みの入力がもう一度エンコードされています。a%20b は a%2520b になります。生のテキストを一度だけエンコードしてください。
パーセントエンコーディングの16進数は大文字と小文字のどちらですか?
RFC 3986 は %2F と %2f を同じものとして扱い、大文字を推奨しています。16進数を小文字で にチェックを入れるのは、署名の比較など、小文字を出力するシステムに合わせる場合だけにしてください。