URLエンコードで特殊文字を正しく扱う方法
URL全体とクエリ値を区別し、空白、プラス、パーセントなどを二重エンコードせず安全に変換・確認する手順を解説します。
公開日: 2026-08-10 · 更新日: 2026-08-10
URL全体と値を分けて考える
URLにはスキーム、ホスト、パス、クエリ、フラグメントなど、役割の異なる部分があります。URL全体を一つの値としてエンコードすると、https:// の : や /、クエリを始める ? まで変換され、そのまま移動先URLとして使えなくなります。
たとえば検索語 red + blue & 50% を q の値として渡す場合、エンコードする単位は検索語だけです。
input value: red + blue & 50%
encoded value: red%20%2B%20blue%20%26%2050%25
complete URL: https://example.com/search?q=red%20%2B%20blue%20%26%2050%25
既存URLを部品ごとに変更できる環境では、文字列連結よりURL APIやクエリパラメータ用APIを使う方が、どの部分をエンコードするか明確になります。App MuseumのURLエンコード・デコードツールへは、URLへ埋め込む値だけを入力するのが基本です。
特殊文字が問題になる理由
空白はパーセントエンコードでは通常 %20 になります。一方、application/x-www-form-urlencoded 形式では空白を + として表すため、元からあるプラス記号は %2B と区別する必要があります。
& はクエリ項目の区切り、= は名前と値の区切り、# はフラグメントの開始として解釈される場合があります。値にこれらを含めるなら、それぞれ %26、%3D、%23 とすることでデータとして保持できます。% は % と2桁の16進数からなるエンコード表記を始めるため、文字として渡す場合は %25 になります。
raw value: plan=a¬e=#1
encoded: plan%3Da%26note%3D%231
よくある失敗は、フォーム形式の + を常にプラス記号としてデコードすること、または値の中の & を未変換のまま連結して別パラメータにしてしまうことです。利用先が通常のURLコンポーネントとフォーム形式のどちらを期待するか確認してください。
二重エンコードを見分ける
すでにエンコード済みの %20 をもう一度エンコードすると、% が %25 になり %2520 へ変わります。受信側で一度デコードしても %20 が残り、期待した空白へ戻らないのが典型的な兆候です。
original: a b
once: a%20b
twice: a%2520b
decode once from twice: a%20b
入力が生の文字列か、すでにエンコード済みかを処理境界で決め、同じ値へ複数の層でエンコードをかけないでください。% の後ろに16進数2桁が繰り返し現れるだけでは二重エンコードと断定できないため、元の値と往復結果を比較します。不完全な % や不正なUTF-8列はデコードエラーになることがあります。
encodeとdecodeを往復して確認する
- 実在データではなく、同じ種類の特殊文字を含むテスト値を用意します。
- URLエンコード・デコードツールで値をEncodeします。
- 出力を新しい入力としてDecodeします。
- デコード結果が最初の文字列と文字単位で一致するか確認します。
- 完成URLでは、値が一つのクエリ項目内に収まり、意図しないフラグメントや追加項目が生じていないか確認します。
東京 + café なら、エンコード後に非ASCII文字と空白と + が変換され、デコード後はアクセント記号を含む元の文字列へ戻ることを確認します。見た目が似るUnicode文字もあるため、必要ならコードポイントや文字列長も確認してください。
秘密情報を使わずにテストする
署名付きURL、パスワードリセットURL、OAuthの認証URL、APIキーやセッショントークンを含むURLは、コピー履歴、画面共有、ログなどから漏れる可能性があります。App Museumの処理はブラウザ内で完結しますが、テストには https://example.com/ と架空の値を使い、実在する秘密情報を貼り付けないでください。
参考資料
このガイドで使えるアプリ
- URLに含める文字列をパーセントエンコード、またはエンコード済み文字列をデコード。ブラウザ内で完結。