本文へ移動
URL エンコード
クエリ値・日本語・絵文字をパーセント変換。component・full。
ブログ

URL エンコード実例: 値・URL 全体・+ の違い

URLを別のURLの値に入れるとき、%25は必要な場合があります。入れ子の復元と同じ値の重複変換を分け、component・full・+を再現例で確かめます。

値を試して比べる →
この記事のポイント3つ

2026-10-15 補足:%25だけで失敗と判断しません。入れ子URLの1層を戻した値と、渡す前の元の値を比べます。以前の+の訂正も本文に残しています。

  1. ①
    値ひとつなら component URLSearchParams.setには渡したい値そのものを入れます。URLを値にする場合も、先にcomponent変換したものを重ねて渡しません。
  2. ②
    クエリの + に注意 URLSearchParams("q=a+b").get("q") は "a b"。文字としての + は %2B で表します。
  3. ③
    入力と共有 URL は別 ツールへの貼り付け値はブラウザーで変換しますが、その値を URL に入れて開くとリクエストや記録に残り得ます。
布の上の紙に『なぜ値が途中で壊れる?』と書かれた、URL の値が崩れる原因を考える表紙。

検索 URL の値に & が入って別のパラメーターになったり、A+B が A B として読まれたりします。前者はエンコードする範囲、後者はクエリの読み方の問題です。サイトのツールとブラウザーの URL API で再現してみましょう。

component か full か、まず範囲を決める

JavaScript には URL エンコード関数が2つあります。違いは、予約文字に手を付けるかどうかです。

encodeURIComponent(component モード)は / ? # & = などの予約文字までパーセントエンコードします。値ひとつ、パス断片ひとつを扱うときに使います。encodeURI(full モード)は区切りを保持し、まだパーセントエンコードされていない URL テキストに使います。MDN も2つを用途で区別しています。2つを混同すると、クエリ値の境界が変わることがあります。

クエリ値に予約文字があれば component

再現しやすい例は、パラメータの値の中に & や = が入る場合です。

値として a=1&b=2 を入れるとしましょう。PiPi Worlds の URL エンコードツールで component でエンコードすると a%3D1%26b%3D2 が出ます。= と & がそれぞれ %3D・%26 に変わり、1つの値として安全に収まります。一方 full でエンコードすると a=1&b=2 のままです。これを ?x=a=1&b=2 のように付けると、サーバーは &b=2 を別のパラメータとして読み、データが壊れます。値には component が答えです。

未エンコードの URL テキスト全体なら full

逆の状況は、区切りを作ったものの、日本語などをまだパーセントエンコードしていない URL テキストです。

https://pipi-worlds.com/道?q=こんにちは を full でエンコードすると https://pipi-worlds.com/%E9%81%93?q=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF になります。://・/・?・= は残り、日本語をパーセントに変えます。component ならスキームの区切りも変換されます。同じ層のURLに encodeURI を繰り返し掛けないでください。 たとえば %20 が %2520 になり、同じURLとして扱うつもりだった値が変わります。一方、URL全体を別のURLのクエリ値に入れる場合は、外側で % を保護する必要があります。次の例のように、渡したい値そのものを searchParams.set に渡します。

URLを別のURLの値に入れるとき

%25 が見えたら、すぐに消すのではなく「何を1つの値として渡すのか」を確認します。 たとえば、次のURL文字列全体を別のURLの next という値に入れる、架空のデータ受け渡しを考えます。説明用の example.com のURLであり、開いたり送信したりする必要はありません。

https://example.com/search?q=A%2BB%20C&lang=ja

この内側のURLでは、q の値は A+B C、lang の値は ja です。%2B は文字の +、%20 は空白を表しています。このURL文字列そのものを外側の next で運ぶなら、次のようにします。WHATWG URL標準の値の直列化に任せ、先に encodeURIComponent は掛けません。

const inner = "https://example.com/search?q=A%2BB%20C&lang=ja";
const outer = new URL("https://example.com/inspect");
outer.searchParams.set("next", inner);
console.log(outer.search);
// ?next=https%3A%2F%2Fexample.com%2Fsearch%3Fq%3DA%252BB%2520C%26lang%3Dja
const restored = new URL(outer.href).searchParams.get("next");
console.log(restored === inner);
// true
console.log(new URL(restored).searchParams.get("q"));
// A+B C

外側で %2B が %252B、%20 が %2520 になるのは、内側の文字列にある % を守るためです。外側を解析して next を取り出すと、元のURL文字列に戻ります。その後で内側のURLを別に解析すると q が A+B C になります。単に同じ値を何度もデコードする手順とは違います。

事前変換を重ねると、何が残る?

比較する失敗例は、set("next", encodeURIComponent(inner)) のように先に変換した文字列を、さらに値として渡す場合です。外側から1回取り出しても https%3A%2F%2F... という変換済み文字列が残り、この例で渡したかった inner と一致しません。

外側のsetに渡すもの外側からnextを取り出した値
inner そのもの元のURL文字列と一致
encodeURIComponent(inner)変換済み文字列が残り、元のURL文字列とは不一致

ここでは「元のURL文字列を渡す」という取り決めで比較しています。実際の受信側が別の形式を明示している場合は、その仕様を確認してください。見た目が読めるようになるまで受信側で追加デコードする、という修正は勧めません。

手動で1層だけ戻す

URL エンコードツールで上の試験用URLを入力し、エンコード・Component (値) を選ぶと、次の値になります。これは next= を除いた、外側へ入れる値の部分です。この例では URLSearchParams の値の直列化と同じになりますが、すべての文字で両方式が同じになるという意味ではありません。

https%3A%2F%2Fexample.com%2Fsearch%3Fq%3DA%252BB%2520C%26lang%3Dja

この結果を入力欄に戻してデコード・Component (値) で1回戻すと、上の元のURL文字列になります。「クエリ・フォームの + を空白に」はオフにして比較します。出力にはまだ内側の %2B・%20 が残りますが、この段階では正しい結果です。ツールは入れ子を自動判定せず、next も自動で取り出しません。

2026年10月15日 補足: 以前の「変換済みURLは再エンコードしない」という注意を、同じ層の反復と入れ子の受け渡しに分けました。元の値との一致はこの例の確認方法であり、リンク先の安全性・受信サーバーの処理・署名付きURLの有効性は保証しません。秘密のトークンや実際の顧客URLではなく、上の試験値だけで確認してください。

’+’ が空白になる罠

デコードで人を惑わせるのが + です。同じ a+b が、出所によって違うふうに解釈されます。

+ の意味は「URL かどうか」だけでは決まりません。URL のクエリ文字列を URLSearchParams で読む場合、form-urlencoded 規則で生の + は空白になります。HTML フォームだけの話ではありません。

decodeURIComponent("a+b")                 // "a+b"
new URLSearchParams("q=a+b").get("q")   // "a b"
new URLSearchParams("q=a%2Bb").get("q") // "a+b"
const url = new URL("https://example.com/search");
url.searchParams.set("q", "A+B & C");
url.searchParams.get("q")                // "A+B & C"
// 直列化した q の + は %2B、空白は +、& は %26

手作業で q=A+B を組み立て、文字としての + を残したいなら %2B が必要です。より確実なのは URL.searchParams.set にエンコード前の値を渡すことです。本サイトの「+ を空白に」はComponent モードでクエリ・フォームの値を一つだけ手動で戻す場合に使います。Full URL モードはパスを変えないよう、すべての + を保持します。URL 内のクエリは URLSearchParams で読むか、その値だけを Component にコピーしてください。

ツールで確認するときとリンクを作るとき

PiPi Worlds の URL エンコードツール は component/full と + の解釈を比べる手動変換器です。full の encodeURI は &、#、? などの区切りを残すため、新しいクエリ値を安全に組み立てる機能ではありません。 新しいリンクには上記の URL と searchParams.set を使ってください。変換入力はブラウザー内で処理しますが、ページ解析のビコンは別に動く場合があります。値を含む URL を実際に開くと、そのアドレスはリクエストや記録に残り得ます。途中で切れた % はエラーとして表示します。

よくある質問

encodeURIComponent と encodeURI は何が違いますか?
encodeURIComponent は `/ ? # & =` なども変換するため、クエリ値やパスの一部に使います。encodeURI は区切りを残し、まだパーセントエンコードされていない URL テキストに使います。同じ層のURLにencodeURIを繰り返さないでください。一方、そのURL全体を別のクエリの値に入れるなら外側のエンコードが必要です。%25だけで誤りと判断しません。
クエリパラメータの値にはどちらを使いますか?
encodeURIComponent です。値の中に `&` や `=` があると encodeURI はそのまま残すため、パラメータの境界が壊れます。たとえば `a=1&b=2` を値として入れると、encodeURIComponent は `a%3D1%26b%3D2` にエンコードして1つの値として安全に渡します。
デコードしたら '+' が空白になりました。なぜ?
URLSearchParams などでクエリ文字列を読むと、form-urlencoded 規則により + は空白になります。q=a+b は a b、q=a%2Bb は a+b です。一方 decodeURIComponent("a+b") は + を保持します。このツールでクエリ・フォームの値を手動で戻す場合だけ「+ を空白に」をオンにしてください。
日本語や絵文字を URL に入れるとどうなりますか?
UTF-8 のパーセント列にエンコードされます。たとえば「あ」は `%E3%81%82` になります。デコードすれば元の文字に正確に戻り、途中で切れた `%` のような壊れた列は文字化けではなくエラーとして表示されます。
入力した値はサーバーに送信されますか?
貼り付けた値そのものを、変換のためにサーバーへ送る処理はありません。一方、Cloudflare Web Analytics はページ表示や性能情報を別途処理する場合があります。値を URL に入れて開く・共有すると、クエリがリクエストやログ、履歴に残り得ます。秘密情報は入れないでください。

出典

確認記録: Codex AI による WHATWG URL 標準・MDN・サイト実装の技術確認。外部専門家による監修や全ブラウザー検証ではありません。

今回の確認範囲 — 入れ子URL・同じ層の重複変換と現行変換関数の再現確認。既存の+説明とMDN出典の確認日は2026-09-28のまま。全ブラウザー・受信サーバー・安全なリダイレクト設計の検証ではありません。

確認内容と限界を開く

2026-10-15: WHATWG URL標準の値の直列化・解析とECMAScriptのencodeURIを確認し、入れ子URLの復元、事前変換を重ねた失敗、手動Component変換をNode.jsと現行変換関数で再現しました。今回の追記は日本語のこの記事だけです。例のURLは開かず、受信サーバー・署名・外部業務処理は検証していません。以前の記録: 2026-09-28にencodeURIComponent・encodeURI・URLSearchParamsの+をNode.jsとツールのテストで再現し、3言語の説明を確認しました。古いMDN出典を本日再確認したという意味ではありません。

この記事で加えたこと — URLSearchParams と本サイトのツールで + の扱いを再現します。URLを別のURLのnext値に入れる架空例では、外側に必要な%25と、事前変換を重ねた誤りを復元文字列の一致で区別します。既存の範囲選択・入力処理の説明も残します。

確認記録は記載された確認内容であり、独立した正確性の保証ではありません。

ツールに戻る →