URLで %20、%3A、%2F を見たことがありますか?これらはパーセントエンコードされた文字です — URLが特殊文字を安全に運ぶための仕組みです。このガイドではバイトレベルの仕組みから各言語の実用的なコード例まで解説します。
URLエンコーダー/デコーダーツールで即座にエンコード・デコード →
URLエンコーディング(パーセントエンコーディング)とは?
URLエンコーディング(正式名称:パーセントエンコーディング)は、RFC 3986で定義されたURIで許可されない文字や特別な意味を持つ文字を表現するメカニズムです。
URLにはASCII文字セットの限られた文字のみ使用できます。文字は予約文字(/、?、&のような構造的意味を持つ文字)と非予約文字(英数字、-、_、.、~)に分けられます。
スペース(ASCII 32、16進数 0x20)は %20 になります。コロン(ASCII 58、16進数 0x3A)は %3A になります。
// URL encoding in action
Original: https://example.com/search?q=hello world&lang=en
Encoded: https://example.com/search?q=hello%20world&lang=en
// Reserved characters and their encoded forms:
// space → %20 : → %3A / → %2F
// ? → %3F & → %26 = → %3D
// # → %23 + → %2B @ → %40URLエンコーディング文字リファレンス表
最もよく使われるパーセントエンコード文字のクイックリファレンスです。
| 文字 | エンコード | 名前 / 用途 |
|---|---|---|
(space) | %20 | スペース |
& | %26 | パラメータ区切り |
? | %3F | クエリ文字列開始 |
/ | %2F | パス区切り |
: | %3A | コロン(スキーム区切り) |
= | %3D | キーと値の区切り |
# | %23 | フラグメント識別子 |
+ | %2B | プラス(フォームではスペース) |
@ | %40 | アットマーク |
% | %25 | パーセント(エスケープ文字自体) |
! | %21 | 感嘆符 |
" | %22 | 二重引用符 |
< | %3C | 小なり |
> | %3E | 大なり |
{ | %7B | 左中括弧 |
} | %7D | 右中括弧 |
[ | %5B | 左角括弧 |
] | %5D | 右角括弧 |
| | %7C | パイプ |
\ | %5C | バックスラッシュ |
URLエンコーディングの仕組み(ステップバイステップ)
エンコードは3つのステップで行われます:(1) 文字を取得、(2) UTF-8バイト列に変換、(3) 各バイトを %XX でエンコード。
いくつかの例を見てみましょう:
// Step-by-step: How characters become percent-encoded
// Example 1: ASCII character (space)
// Character: " " (space)
// ASCII code: 32 → hex: 0x20
// Encoded: %20
// Example 2: ASCII character (ampersand)
// Character: "&"
// ASCII code: 38 → hex: 0x26
// Encoded: %26
// Example 3: Multi-byte UTF-8 (accented letter)
// Character: "é"
// Unicode: U+00E9
// UTF-8 bytes: 0xC3 0xA9 (2 bytes)
// Encoded: %C3%A9
// Example 4: Multi-byte UTF-8 (Chinese character)
// Character: "中"
// Unicode: U+4E2D
// UTF-8 bytes: 0xE4 0xB8 0xAD (3 bytes)
// Encoded: %E4%B8%AD
// Example 5: Multi-byte UTF-8 (emoji)
// Character: "🚀"
// Unicode: U+1F680
// UTF-8 bytes: 0xF0 0x9F 0x9A 0x80 (4 bytes)
// Encoded: %F0%9F%9A%80モダンなプログラミング言語は自動的に処理します。組み込み関数またはオンラインツールをご利用ください。
JavaScriptのencodeURI vs encodeURIComponent
JavaScriptには2つのURLエンコード関数があります。間違った方を選ぶとバグの原因になります。
encodeURI()は完全なURIをエンコードし、構造的な文字を保持します。
// encodeURI() — preserves URL structure
const url = 'https://example.com/path name?q=hello world';
encodeURI(url);
// → "https://example.com/path%20name?q=hello%20world"
// ✓ :// / ? = are NOT encoded (structure preserved)encodeURIComponent()はURIコンポーネントをエンコードし、& = + /などの構造的文字もエンコードします。
// encodeURIComponent() — encodes everything for use as a value
const value = 'price=100&discount=20%';
encodeURIComponent(value);
// → "price%3D100%26discount%3D20%25"
// ✓ = & % ARE encoded (they're data, not structure)
// Correct pattern: build URL piece by piece
const base = 'https://api.example.com/search';
const query = 'Tom & Jerry: The Movie';
const fullUrl = base + '?q=' + encodeURIComponent(query);
// → "https://api.example.com/search?q=Tom%20%26%20Jerry%3A%20The%20Movie"原則:クエリパラメータ値には常に encodeURIComponent() を使用してください。
// Comparison table — which characters get encoded?
//
// Character encodeURI() encodeURIComponent()
// ───────── ─────────── ────────────────────
// space %20 %20
// / / (kept) %2F (encoded)
// ? ? (kept) %3F (encoded)
// & & (kept) %26 (encoded)
// = = (kept) %3D (encoded)
// # # (kept) %23 (encoded)
// : : (kept) %3A (encoded)
// + + (kept) %2B (encoded)
// @ @ (kept) %40 (encoded)
// é %C3%A9 %C3%A9
// 中 %E4%B8%AD %E4%B8%AD各プログラミング言語でのURLエンコーディング
主要な言語にはURLエンコード関数が組み込まれています:
JavaScript
// JavaScript — encodeURIComponent / URLSearchParams
// Encode a query parameter value
encodeURIComponent('hello world&key=val');
// → "hello%20world%26key%3Dval"
// Decode
decodeURIComponent('hello%20world%26key%3Dval');
// → "hello world&key=val"
// URLSearchParams (auto-encodes, uses + for spaces)
const params = new URLSearchParams({ q: 'Tom & Jerry', page: '1' });
params.toString(); // → "q=Tom+%26+Jerry&page=1"Python
# Python 3 — urllib.parse
from urllib.parse import quote, quote_plus, unquote, urlencode
# Path encoding (spaces → %20)
quote('hello world/file') # → "hello%20world/file"
quote('hello world/file', safe='') # → "hello%20world%2Ffile"
# Query value encoding (spaces → +)
quote_plus('hello world&key=val') # → "hello+world%26key%3Dval"
# Build query string from dict
urlencode({'q': 'Tom & Jerry', 'page': '1'})
# → "q=Tom+%26+Jerry&page=1"
# Decode
unquote('%E4%B8%AD%E6%96%87') # → "中文"Java
// Java — URLEncoder (spaces → +)
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
String encoded = URLEncoder.encode(
"hello world&key=val", StandardCharsets.UTF_8
);
// → "hello+world%26key%3Dval"
String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
// → "hello world&key=val"Go
// Go — net/url package
package main
import "net/url"
// Query value encoding (spaces → +)
url.QueryEscape("hello world&key=val")
// → "hello+world%26key%3Dval"
// Path segment encoding (spaces → %20)
url.PathEscape("hello world/file")
// → "hello%20world%2Ffile"
// Build URL safely with url.Values
vals := url.Values{}
vals.Set("q", "Tom & Jerry")
vals.Encode() // → "q=Tom+%26+Jerry"PHP
<?php
// PHP — urlencode (spaces → +) / rawurlencode (spaces → %20)
urlencode('hello world&key=val');
// → "hello+world%26key%3Dval"
rawurlencode('hello world&key=val');
// → "hello%20world%26key%3Dval"
http_build_query(['q' => 'Tom & Jerry', 'page' => 1]);
// → "q=Tom+%26+Jerry&page=1"
urldecode('hello%20world'); // → "hello world"
?>Ruby
# Ruby — CGI / URI
require 'cgi'
require 'uri'
CGI.escape('hello world&key=val')
# → "hello+world%26key%3Dval"
URI.encode_www_form('q' => 'Tom & Jerry', 'page' => '1')
# → "q=Tom+%26+Jerry&page=1"
CGI.unescape('hello%20world') # → "hello world"よくあるURLエンコーディングのミス
1. 二重エンコード
既にエンコードされた文字列を再度エンコードすると発生します。%20 が %2520 になります。
// Double encoding — a very common bug
const value = 'hello world';
const encoded = encodeURIComponent(value); // "hello%20world"
// BUG: encoding again
encodeURIComponent(encoded);
// → "hello%2520world" (%20 → %25 + 20)
// Server decodes to "%20" (literal) instead of " " (space)
// FIX: encode raw values exactly once2. URL全体をエンコード
完全なURLを encodeURIComponent() に渡すとURL構造が壊れます。個別の値のみエンコードしてください。
// WRONG: encoding entire URL
encodeURIComponent('https://example.com/api?q=test');
// → "https%3A%2F%2Fexample.com%2Fapi%3Fq%3Dtest" (broken!)
// CORRECT: encode only the parameter value
'https://example.com/api?q=' + encodeURIComponent('test value');
// → "https://example.com/api?q=test%20value"3. スペース:+ vs %20
HTMLフォームは +、RFC 3986は %20 を使用します。APIでは %20 を推奨。
// Space encoding: + vs %20
// HTML form submission (application/x-www-form-urlencoded):
// "hello world" → "hello+world"
// RFC 3986 (URI standard):
// "hello world" → "hello%20world"
// JavaScript functions:
encodeURIComponent('hello world'); // → "hello%20world" (RFC 3986)
new URLSearchParams({q: 'hello world'}).toString(); // → "q=hello+world" (form)4. クエリパラメータ値の未エンコード
ユーザー入力値をエンコードしないのはセキュリティリスクであり、URLの破損を引き起こします。
// Missing encoding breaks URLs
const search = 'Tom & Jerry';
// WRONG: unencoded & splits the value
'/search?q=' + search;
// → "/search?q=Tom & Jerry"
// Server sees: q="Tom " and Jerry="" (two params!)
// CORRECT: encode the value
'/search?q=' + encodeURIComponent(search);
// → "/search?q=Tom%20%26%20Jerry"
// Server sees: q="Tom & Jerry" (one param)URLエンコーディングのベストプラクティス
ユーザー入力は必ずエンコードしてからクエリ文字列やパスセグメントに挿入してください。
手動置換ではなくライブラリ関数を使用してください。
特殊文字でテスト:& = ? / # + % と非ASCII文字。
バイナリデータにはURL安全なBase64を使用してください。
// Best practice: use URL / URLSearchParams API
const url = new URL('https://api.example.com/search');
url.searchParams.set('q', 'Tom & Jerry: The Movie');
url.searchParams.set('lang', 'en');
url.toString();
// → "https://api.example.com/search?q=Tom+%26+Jerry%3A+The+Movie&lang=en"
// All encoding handled automatically!
// URL-safe Base64 (avoids + and / in URLs)
// Standard: "SGVsbG8gV29ybGQ=" (may contain + / =)
// URL-safe: "SGVsbG8gV29ybGQ" (uses - _ instead)よくある質問
なぜスペースは%20にエンコードされるのですか?
スペースのASCIIコードは32で、16進数では0x20です。パーセントエンコーディングはバイトを % + 16進値で表します。
+と%20の違いは?
%20はRFC 3986由来。+はフォーム形式由来。%20がより汎用的です。
URL全体をエンコードする必要がありますか?
いいえ。個別のコンポーネントのみエンコードしてください。構造的文字はエンコードしないでください。
encodeURIとencodeURIComponentの違いは?
encodeURI()は構造的文字を保持。encodeURIComponent()はそれらもエンコード。パラメータ値には encodeURIComponent() を使用。
URLエンコードされた文字列をデコードするには?
JavaScript: decodeURIComponent()。Python: urllib.parse.unquote()。PHP: urldecode()。
URLエンコーディングはすべての開発者が理解すべき基本的なWeb概念です。このガイドをブックマークしてご活用ください。