まず「URL エンコード」で何を守りたいのか
URL エンコードは、「URL の中に入れてはいけない(入れると誤解される)文字を、安全な形に変換すること」です。
日本語やスペース、? や & などの記号を、そのまま URL に入れると、
ブラウザやサーバーが「区切り記号」と勘違いして、意味が壊れます。
だから、
本来は「データとしての文字」なのか
それとも「URL の構造を表す記号」なのか
を区別するために、「データ側」をエンコードしてあげる必要があります。
JavaScript で使う 2 つの基本関数
encodeURI と encodeURIComponent の違い
JavaScript には、URL エンコード用に代表的な 2 つの関数があります。
encodeURI("https://example.com/検索?q=テスト");
encodeURIComponent("検索");
JavaScriptざっくり言うと、こう使い分けます。
- encodeURI
→ 「URL 全体」をエンコードするときに使う(https://example.com/...みたいな形)。
→/や?や&など、「URL の構造に必要な記号」はそのまま残す。 - encodeURIComponent
→ 「URL の一部(パラメータの値など)」をエンコードするときに使う。
→/や?や&も含めて、ほとんど全部エンコードする。
ここを間違えると、
「URL 全体を encodeURIComponent して壊す」
「パラメータ値を encodeURI して足りない」
という典型的なバグになります。
encodeURIComponent を使った「クエリパラメータ」の作り方
パラメータ値は必ず encodeURIComponent
一番よくあるのは、検索画面などで「クエリパラメータ」を作る場面です。
const keyword = "JavaScript 入門";
const url = "/search?q=" + encodeURIComponent(keyword);
// "/search?q=JavaScript%20%E5%85%A5%E9%96%80"
JavaScriptここで重要なのは、keyword の部分だけを encodeURIComponent することです。
/search?q= という「URL の構造」はそのまま書き、
「値」の部分だけをエンコードします。
もし、エンコードしないとどうなるか。
const keyword = "A&B";
const url = "/search?q=" + keyword;
// "/search?q=A&B"
JavaScriptサーバー側から見ると、これは
q = "A"- 別パラメータ
B(値なし)
のように解釈されてしまう可能性があります。
正しくはこうです。
const keyword = "A&B";
const url = "/search?q=" + encodeURIComponent(keyword);
// "/search?q=A%26B"
JavaScript& が %26 に変わることで、「これはデータです、区切り記号ではありません」と伝えられます。
encodeURI は「URL 全体」を扱うときに使う
すでに構造が決まっている URL を安全にする
例えば、外部から渡された URL を、そのままリンクとして使いたいけれど、
日本語やスペースが混ざっているかもしれない、というケース。
const rawUrl = "https://example.com/検索?q=テスト";
const safeUrl = encodeURI(rawUrl);
// "https://example.com/%E6%A4%9C%E7%B4%A2?q=%E3%83%86%E3%82%B9%E3%83%88"
JavaScriptここで encodeURI がやっているのは、
- 日本語部分を
%E6...のような形に変換 - ただし、
https://や/や?や=はそのまま残す
ということです。
もし、ここで encodeURIComponent を使うとどうなるか。
encodeURIComponent("https://example.com/検索?q=テスト");
// "https%3A%2F%2Fexample.com%2F%E6%A4%9C%E7%B4%A2%3Fq%3D%E3%83%86%E3%82%B9%E3%83%88"
JavaScript: や / や ? や = まで全部エンコードされてしまい、
もはや「URL ではないただの文字列」になってしまいます。
URL 全体を扱うときは encodeURI、
URL の一部(特にパラメータ値)を扱うときは encodeURIComponent。
この切り分けがとても大事です。
実務でよくやる「クエリ文字列生成」ユーティリティ
オブジェクト → ?key=value&... を安全に作る
毎回 ? や & を手でつなぐのは面倒なので、
オブジェクトからクエリ文字列を作る小さなユーティリティを用意しておくと便利です。
function toQueryString(params) {
if (!params || typeof params !== "object") {
return "";
}
const parts = [];
for (const [key, value] of Object.entries(params)) {
if (value == null) continue; // null / undefined はスキップ
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(String(value));
parts.push(`${encodedKey}=${encodedValue}`);
}
if (parts.length === 0) {
return "";
}
return "?" + parts.join("&");
}
JavaScript使い方はこうです。
const qs = toQueryString({
q: "JavaScript 入門",
page: 2,
sort: "created_at desc",
});
// "?q=JavaScript%20%E5%85%A5%E9%96%80&page=2&sort=created_at%20desc"
const url = "/search" + qs;
JavaScriptここでのポイントは、
- key も value も 必ず encodeURIComponent する
- null / undefined はパラメータとして付けない
- 先頭に
?を付けるのはこの関数の責務にしてしまう
という設計にしておくことです。
設計として意識してほしいこと
「どこまでをユーティリティに任せるか」を決める
URL エンコードは、あちこちでバラバラに書き始めると、すぐに混乱します。
- ここでは encodeURI を使っている
- あそこでは encodeURIComponent を忘れている
- 別のところでは
replace(" ", "%20")だけしている
こうなると、「どこが安全でどこが危ないか」が分からなくなります。
なので、
export function toQueryString(params) { ... }
export function encodeQueryValue(value) {
return encodeURIComponent(String(value ?? ""));
}
JavaScriptのように、「パラメータ値をエンコードする場所」を一箇所に決めてしまうのがおすすめです。
「エンコードしすぎ」と「しなさすぎ」の両方を避ける
- URL 全体を encodeURIComponent して壊す
- パラメータ値をエンコードせずに
&や=を混入させる
どちらもよくある事故です。
ルールはシンプルで、
- URL の構造部分(パス・
?・&・=)は自分で書く - ユーザー入力や動的な値は、必ず encodeURIComponent してから埋め込む
これだけ守れば、かなりのトラブルを避けられます。
ちょっとだけ手を動かしてみる
コンソールで、次の順番で試してみてください。
encodeURIComponent("A&B");
encodeURIComponent("JavaScript 入門");
encodeURI("https://example.com/検索?q=テスト");
toQueryString({ q: "A&B", page: 1 });
JavaScript「どの文字が %xx 形式に変わるか」
「encodeURI と encodeURIComponent の違い」
を、自分の目で確かめてみてください。
そのうえで、自分のプロジェクトに
export function toQueryString(params) { ... }
JavaScriptのようなユーティリティを置いて、
「クエリ文字列を作るときは必ずここを通す」と決めてしまえば、
あなたの URL 周りのコードは、一気に“業務で安心して使えるレベル”に近づきます。

