
URLエンコードの完全ガイド — 知っておくべきすべてのこと
📷 Sarah Blocksidge / PexelsURLエンコードの完全ガイド — 知っておくべきすべてのこと
URLエンコード(パーセントエンコーディング)について、予約文字、UTF-8の扱い、よくある問題、実践例を含めて徹底解説。Webデベロッパー向けの完全リファレンス。
URLエンコードとは?
URLエンコード(パーセントエンコーディングとも呼ばれる)は、URLで安全に送信できる形式に文字を変換する仕組みです。URLはASCII文字セットの限られた文字しか使用できないため、それ以外の文字や、URL構文で特別な意味を持つ文字はすべてエンコードする必要があります。
URLに%20が含まれているのを見て何だろうと思ったことはありませんか?あるいは特殊文字が含まれるリンクが壊れてしまって困ったことは?このガイドを読めば、URLエンコードの仕組みとその重要性を深く理解できます。
URLのエンコード・デコードをすぐに試したい方は、URLエンコーダー/デコーダーツールをお使いください — すべてのエンコードルールを自動的に処理します。
URLエンコードが存在する理由
URLはインターネットの黎明期に、システムの文字セットサポートが限られていた時代に設計されました。元のURL仕様(1994年に公開されたRFC 1738)は、URLをASCII文字の小さなサブセットに制限していました。これは、異なるシステム、ネットワーク、プロトコル間でURLが機能するようにするための現実的な決定でした。
しかし現実の世界では、基本的なASCII以上のものが必要です。
- ファイル名のスペース:
my document.pdfはmy%20document.pdfとしてエンコードが必要 - 国際文字: 日本語、韓国語、アラビア語などはエンコードが必要
- データ内の特殊文字: クエリパラメータに
&、=、#などURLで意味を持つ文字が含まれる場合 - バイナリデータ: バイナリデータをURLに含める必要がある場合
URLエンコードはこれらすべての問題を解決する普遍的なエスケープ機構を提供します。
パーセントエンコーディングの仕組み
パーセントエンコードのアルゴリズムはシンプルです。
- エンコードする文字を取得する
- バイト表現に変換する(非ASCII文字にはUTF-8を使用)
- 各バイトに対して
%に続く2桁の16進数を記述する
基本例
| 文字 | UTF-8バイト | パーセントエンコード |
|---|---|---|
| スペース | 0x20 | %20 |
! | 0x21 | %21 |
# | 0x23 | %23 |
$ | 0x24 | %24 |
& | 0x26 | %26 |
+ | 0x2B | %2B |
/ | 0x2F | %2F |
= | 0x3D | %3D |
? | 0x3F | %3F |
@ | 0x40 | %40 |
マルチバイト文字
非ASCII文字はUTF-8で複数のバイトが必要なため、複数のパーセントエンコードシーケンスが生成されます。
| 文字 | UTF-8バイト | パーセントエンコード |
|---|---|---|
é(アクセント付き) | 0xC3 0xA9 | %C3%A9 |
| ユーロ記号 | 0xE2 0x82 0xAC | %E2%82%AC |
| 日本語(か) | 0xE3 0x81 0x8B | %E3%81%8B |
| 韓国語(한) | 0xED 0x95 0x9C | %ED%95%9C |
| 絵文字(笑顔) | 0xF0 0x9F 0x98 0x80 | %F0%9F%98%80 |
URLエンコーダーツールでこれらの文字を実際にエンコードしてみてください。
URL構造と予約文字
URLエンコードを正しく理解するには、URL構造を理解する必要があります。
https://user:pass@www.example.com:8080/path/to/page?key=value&foo=bar#section
|_____| |______| |_______________|____||___________|_________________|_______|
スキーム ユーザー情報 ホスト ポート パス クエリ フラグメント
予約文字
予約文字はURLで特別な意味を持ちます。区切り文字としてではなくデータとして使用したい場合は、パーセントエンコードが必要です。
| 文字 | URLでの役割 | エンコード形式 |
|---|---|---|
: | スキーム、ポート、ユーザー情報の区切り | %3A |
/ | パスセグメントの区切り | %2F |
? | クエリ文字列の開始 | %3F |
# | フラグメントの開始 | %23 |
@ | ユーザー情報とホストの区切り | %40 |
& | クエリパラメータの区切り | %26 |
= | クエリのキーと値の区切り | %3D |
+ | クエリ文字列でのスペース(旧来式) | %2B |
予約されていない文字
これらの文字はURLのどの部分でもエンコード不要です。
- 英字:
A-Zとa-z - 数字:
0-9 - ハイフン:
- - ピリオド:
. - アンダースコア:
_ - チルダ:
~
スペースの扱い: %20 vs +
スペースのエンコードはURLエンコードで最も混乱しやすい部分の一つです。
%20: スペース文字の正しいパーセントエンコーディングで、パスセグメントで使用+: スペースの代替エンコードですが、クエリ文字列内でのみ有効(application/x-www-form-urlencoded形式から)
パス: https://example.com/my%20documents/file%20name.pdf (正しい)
パス: https://example.com/my+documents/file+name.pdf (誤り - +はリテラル)
クエリ: https://example.com/search?q=hello+world (正しい)
クエリ: https://example.com/search?q=hello%20world (こちらも正しい)
ベストプラクティス: パスセグメントでは%20を使用し、クエリ文字列では+または%20のどちらでも可。迷ったら%20が常に安全です。
各プログラミング言語でのURLエンコード
JavaScript
JavaScriptはURLエンコードのための関数をいくつか提供しており、それぞれスコープが異なります。
// encodeURIComponent - URIコンポーネントをエンコード(クエリパラメータ値)
encodeURIComponent('hello world & goodbye')
// 結果: "hello%20world%20%26%20goodbye"
// encodeURI - 完全なURIをエンコード(URL構造文字を保持)
encodeURI('https://example.com/path with spaces?q=hello world')
// 結果: "https://example.com/path%20with%20spaces?q=hello%20world"
// decodeURIComponent - URIコンポーネントをデコード
decodeURIComponent('hello%20world%20%26%20goodbye')
// 結果: "hello world & goodbye"
encodeURIとencodeURIComponentの主な違い:
| 関数 | エンコードしない文字 | 用途 |
|---|---|---|
encodeURI | :, /, ?, #, &, =, @, + | 完全なURLのエンコード |
encodeURIComponent | 予約されていない文字のみ | クエリパラメータ値のエンコード |
URLSearchParams API
モダンなJavaScriptにはクエリ文字列を処理するURLSearchParamsがあります。
// クエリ文字列の作成
const params = new URLSearchParams();
params.set('name', '田中 太郎');
params.set('city', '東京');
params.set('interests', 'コーディング & デザイン');
console.log(params.toString());
// "name=%E7%94%B0%E4%B8%AD+%E5%A4%AA%E9%83%8E&city=%E6%9D%B1%E4%BA%AC&interests=%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0+%26+%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3"
// クエリ文字列の解析
const url = new URL('https://example.com/search?q=hello+world&page=2');
console.log(url.searchParams.get('q')); // "hello world"
console.log(url.searchParams.get('page')); // "2"
Python
from urllib.parse import quote, unquote, urlencode, parse_qs
# URLパスに使用する文字列をエンコード
quote('hello world/path') # 'hello%20world/path'(/はエンコードしない)
quote('hello world/path', safe='') # 'hello%20world%2Fpath'(すべてエンコード)
# パーセントエンコードされた文字列をデコード
unquote('hello%20world') # 'hello world'
# クエリ文字列の構築
params = {'q': 'hello world', 'category': 'books & media'}
urlencode(params) # 'q=hello+world&category=books+%26+media'
Java
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
// エンコード
String encoded = URLEncoder.encode("hello world & more", StandardCharsets.UTF_8);
// 結果: "hello+world+%26+more"
// デコード
String decoded = URLDecoder.decode("hello+world+%26+more", StandardCharsets.UTF_8);
// 結果: "hello world & more"
PHP
// URLエンコード(スペースを+として)
urlencode('hello world & more'); // "hello+world+%26+more"
// rawURLエンコード(スペースを%20として)
rawurlencode('hello world & more'); // "hello%20world%20%26%20more"
// クエリ文字列の構築
http_build_query(['q' => 'hello world', 'page' => 1]);
// "q=hello+world&page=1"
URLにおけるUTF-8と国際文字
IRI標準
国際化リソース識別子(IRI、RFC 3987で定義)はURLを拡張してUnicode文字をサポートします。ただし、ネットワーク経由で送信される際にはUTF-8パーセントエンコーディングを使用してURIに変換されます。
IRI: https://example.com/東京
URI: https://example.com/%E6%9D%B1%E4%BA%AC
IRI: https://example.com/search?q=東京タワー
URI: https://example.com/search?q=%E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC
国際化ドメイン名(IDN)
非ASCII文字を含むドメイン名はPunycodeエンコーディングを使用します。
Unicode: https://日本語.jp
Punycode: https://xn--wgv71a309e.jp
ブラウザが非ASCII URLを処理する方法
モダンなブラウザはアドレスバーにはIRI(Unicode版)を表示して読みやすくしますが、ネットワーク経由ではパーセントエンコードされたURIを送信します。
よくあるURLエンコードの問題と解決策
問題1: 二重エンコード
二重エンコードは、既にエンコードされたURLが再度エンコードされると発生します。
元のテキスト: hello world
1回目のエンコード: hello%20world
二重エンコード: hello%2520world (%25は%のエンコード)
解決策: エンコード前に入力が既にエンコードされているか確認します。
function safeEncodeURIComponent(str) {
try {
const decoded = decodeURIComponent(str);
if (decoded !== str) {
return str; // 既にエンコード済み
}
} catch (e) {
// デコードに失敗した場合は新たにエンコード
}
return encodeURIComponent(str);
}
問題2: URL全体をエンコードしてしまう
// 誤り: URL全体をエンコードする
const url = 'https://api.example.com/search?q=hello world';
const encoded = encodeURIComponent(url);
// "https%3A%2F%2Fapi.example.com%2Fsearch%3Fq%3Dhello%20world"
// これはURLとして完全に壊れています!
// 正しい: エンコードが必要なコンポーネントだけをエンコード
const baseUrl = 'https://api.example.com/search';
const query = encodeURIComponent('hello world');
const correctUrl = `${baseUrl}?q=${query}`;
// "https://api.example.com/search?q=hello%20world"
問題3: APIパラメータで特殊文字をエンコードしていない
// バグ: 値の中の&がクエリ文字列を壊す
const apiUrl = `https://api.example.com/search?q=Tom & Jerry&page=1`;
// これで3つのパラメータが作られる: q=Tom、Jerry、page=1
// 修正: パラメータ値をエンコードする
const apiUrl = `https://api.example.com/search?q=${encodeURIComponent('Tom & Jerry')}&page=1`;
// 正しい: q=Tom%20%26%20Jerry&page=1
URLエンコードのリファレンステーブル
よくエンコードされる文字の総合リファレンスです。
| 文字 | 十進数 | 16進数 | エンコード | 説明 |
|---|---|---|---|---|
| (スペース) | 32 | 20 | %20 | スペース文字 |
! | 33 | 21 | %21 | 感嘆符 |
" | 34 | 22 | %22 | ダブルクォート |
# | 35 | 23 | %23 | ハッシュ / フラグメント区切り |
$ | 36 | 24 | %24 | ドル記号 |
% | 37 | 25 | %25 | パーセント記号(エスケープ文字) |
& | 38 | 26 | %26 | アンパサンド / クエリ区切り |
/ | 47 | 2F | %2F | スラッシュ / パス区切り |
: | 58 | 3A | %3A | コロン |
= | 61 | 3D | %3D | 等号 |
? | 63 | 3F | %3F | 疑問符 / クエリ区切り |
@ | 64 | 40 | %40 | アットマーク |
まとめ
URLエンコードはWebアプリケーション開発における基本的な概念であり、URLを扱うすべてのアプリケーションに影響します。パーセントエンコーディングの仕組み、encodeURIComponentとencodeURIの使い分け、各プログラミング言語のURL処理方法を理解することで、微妙なバグやセキュリティ問題を防ぐことができます。
重要なポイント:
- JavaScriptでは**値には
encodeURIComponent、完全なURLにはencodeURI**を使用する - **スペースは
%20または+**のどちらでも可能 —%20は常に安全 - 非ASCII文字はUTF-8でエンコードしてからパーセントエンコードされる
- 二重エンコードに注意 — 最もよくあるURLエンコードのバグ
- JavaScriptではクエリ文字列を安全に構築するために**
URLSearchParamsを使用**する - インジェクション攻撃を防ぐため、URLに含めるユーザー入力は必ずエンコードする
URLの素早いエンコード・デコードには、URLエンコーダー/デコーダーツールをブックマークしてください。
関連リソース
- URLエンコーダー/デコーダーツール — URLを即座にエンコード・デコード
- Base64エンコーダー/デコーダー — Base64URLエンコードのツール
- JSONフォーマッター — URLデータを含むJSONの整形
- ハッシュジェネレーター — URL文字列のハッシュ生成