DevToolBoxFREE
BlogAdvertise

URLエンコード&デコード完全ガイド:パーセントエンコーディング解説

10分by DevToolBox

URLエンコーディングパーセントエンコーディングとも呼ばれる)は、Web開発における最も基本的なメカニズムの一つです。フォームの送信、クエリパラメータ付きリンクのクリック、REST APIの呼び出しのたびに、URLエンコードとURLデコード操作が行われています。この包括的なガイドでは、RFC 3986仕様からJavaScript、Python、Bash、PHP、Javaの実践的なコード例まで、すべてをカバーします。

無料オンラインURLエンコード/デコードツールをお試しください。

URLエンコーディング(パーセントエンコーディング)とは?

URLエンコーディングはRFC 3986で定義されており、安全でない文字をパーセント記号(%)と2桁の16進数に置き換えます。例えば、スペースは%20になります。

URLには限られたASCII文字セットしか含められません。エンコード不要なURL安全文字は:英字、数字、4つの特殊文字-_.~です。その他すべての文字はエンコードが必要です。

&=?#などの文字はURLで構造的な意味を持ちます。適切なURLエンコードがなければ、URLは破損したり誤って解釈されたりします。

URLエンコーディングの仕組み

URLエンコードプロセスはシンプルなアルゴリズムに従います:

  1. 文字をUTF-8バイトに変換
  2. 各バイトに対して%の後に16進数値を記述。
  3. 非予約文字はそのまま。
  4. 予約文字は曖昧な場合のみエンコード。

Hello World!Hello%20World%21になります。

UTF-8マルチバイト例:非ASCII文字は複数のパーセントエンコードされたバイトを生成します。

URLエンコーディング参照テーブル

よくエンコードされる文字の参照テーブル:

CharacterEncodedDescription
(space)%20Space
!%21Exclamation mark
#%23Hash / Fragment
$%24Dollar sign
%%25Percent sign
&%26Ampersand
'%27Apostrophe
(%28Left parenthesis
)%29Right parenthesis
*%2AAsterisk
+%2BPlus sign
,%2CComma
/%2FForward slash
:%3AColon
;%3BSemicolon
=%3DEquals sign
?%3FQuestion mark
@%40At sign
[%5BLeft bracket
]%5DRight bracket
{%7BLeft brace
}%7DRight brace
|%7CPipe
<%3CLess than
>%3EGreater than
"%22Double quote

スペースのエンコーディング:%20 vs +

URLでスペースをエンコードする方法は2つあります:

%20:URIのRFC 3986標準エンコーディング。

+application/x-www-form-urlencoded(HTMLフォーム)で使用。

どちらを使う?プログラムでURLを構築する場合は%20を使用。+はフォームデータで自動的に使用されます。

// Space encoding comparison

// RFC 3986 (URI standard) — space = %20
"hello world"  →  "hello%20world"
// Used in: URL paths, API endpoints, general URIs

// application/x-www-form-urlencoded — space = +
"hello world"  →  "hello+world"
// Used in: HTML form submissions, URLSearchParams

// JavaScript comparison:
encodeURIComponent("hello world")  // "hello%20world"  (%20)
new URLSearchParams({q: "hello world"}).toString()  // "q=hello+world"  (+)

// Python comparison:
urllib.parse.quote("hello world")      # "hello%20world"  (%20)
urllib.parse.urlencode({"q": "hello world"})  # "q=hello+world"  (+)

// PHP comparison:
rawurlencode("hello world")  // "hello%20world"  (%20)
urlencode("hello world")     // "hello+world"    (+)

URLエンコード/デコードのコード例

JavaScript URLエンコード/デコード

JavaScriptはencodeURIComponentencodeURIを提供しています。それぞれの使い分けの理解が重要です:

// ===== encodeURIComponent vs encodeURI =====

// encodeURIComponent — encodes EVERYTHING except: A-Z a-z 0-9 - _ . ~
// Use for: individual query parameter values, path segments
encodeURIComponent("hello world & goodbye");
// "hello%20world%20%26%20goodbye"

encodeURIComponent("price=100&category=books");
// "price%3D100%26category%3Dbooks"

// encodeURI — preserves URL structure characters: : / ? # & = @ + $
// Use for: encoding a complete URL
encodeURI("https://example.com/search?q=hello world&lang=en");
// "https://example.com/search?q=hello%20world&lang=en"

// WARNING: Do NOT use encodeURIComponent on full URLs!
encodeURIComponent("https://example.com/path");
// "https%3A%2F%2Fexample.com%2Fpath"  ← BROKEN URL!

// ===== Decoding =====
decodeURIComponent("hello%20world%20%26%20goodbye");
// "hello world & goodbye"

decodeURI("https://example.com/search?q=hello%20world");
// "https://example.com/search?q=hello world"

// ===== URLSearchParams (handles form encoding automatically) =====
const params = new URLSearchParams({
  query: "cats & dogs",
  page: "1",
  filter: "price > 50"
});
params.toString();
// "query=cats+%26+dogs&page=1&filter=price+%3E+50"
// Note: spaces become + (form encoding), & in values becomes %26

// Parse query string
const parsed = new URLSearchParams("?q=hello+world&lang=en");
parsed.get("q");  // "hello world" (+ decoded to space)
parsed.get("lang");  // "en"

// ===== Building URLs with the URL API =====
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "hello world & more");
url.searchParams.set("limit", "10");
url.toString();
// "https://api.example.com/search?q=hello+world+%26+more&limit=10"

Python URLエンコード/デコード

Pythonのurllib.parseモジュールは包括的なURLエンコード関数を提供します:

import urllib.parse

# ===== quote / unquote (RFC 3986 percent-encoding) =====

# Encode a string (spaces become %20)
urllib.parse.quote("hello world & goodbye")
# "hello%20world%20%26%20goodbye"

# By default, / is NOT encoded (safe="/")
urllib.parse.quote("/path/to/file name.txt")
# "/path/to/file%20name.txt"

# Encode everything including /
urllib.parse.quote("/path/to/file", safe="")
# "%2Fpath%2Fto%2Ffile"

# Decode
urllib.parse.unquote("hello%20world%20%26%20goodbye")
# "hello world & goodbye"

# ===== urlencode (for query strings, uses + for spaces) =====
params = {"q": "cats & dogs", "page": 1, "filter": "price > 50"}
urllib.parse.urlencode(params)
# "q=cats+%26+dogs&page=1&filter=price+%3E+50"

# ===== quote_plus (form encoding, spaces become +) =====
urllib.parse.quote_plus("hello world")
# "hello+world"

urllib.parse.unquote_plus("hello+world")
# "hello world"

# ===== With the requests library =====
import requests

# requests handles URL encoding automatically
response = requests.get(
    "https://api.example.com/search",
    params={"q": "hello world", "lang": "en"}
)
# Actual URL: https://api.example.com/search?q=hello+world&lang=en

# For path segments, encode manually
username = "john@example.com"
url = f"https://api.example.com/users/{urllib.parse.quote(username, safe='')}"
# "https://api.example.com/users/john%40example.com"

Bash / curl URLエンコード

curlの--data-urlencodeフラグが最も簡単な方法です:

# ===== curl --data-urlencode =====

# GET request with URL-encoded query parameter
curl -G "https://api.example.com/search" \
  --data-urlencode "q=hello world & more" \
  --data-urlencode "lang=en"
# Request URL: /search?q=hello%20world%20%26%20more&lang=en

# POST with form-encoded body
curl -X POST "https://api.example.com/submit" \
  --data-urlencode "name=John Doe" \
  --data-urlencode "message=Hello! How are you?"

# ===== Pure Bash URL encoding (using printf) =====
urlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""
  local pos c o
  for (( pos=0 ; pos<strlen ; pos++ )); do
    c=${string:$pos:1}
    case "$c" in
      [-_.~a-zA-Z0-9]) o="${c}" ;;
      *) printf -v o '%%%02X' "'$c" ;;
    esac
    encoded+="${o}"
  done
  echo "${encoded}"
}

urlencode "hello world & goodbye"
# "hello%20world%20%26%20goodbye"

# ===== Using Python one-liner in Bash =====
python3 -c "import urllib.parse; print(urllib.parse.quote('hello world'))"
# "hello%20world"

# ===== Decode URL-encoded strings =====
python3 -c "import urllib.parse; print(urllib.parse.unquote('hello%20world'))"
# "hello world"

PHP URLエンコード/デコード

PHPはurlencode()rawurlencode()を提供しています:

<?php
// ===== urlencode / urldecode =====
// Uses + for spaces (application/x-www-form-urlencoded)

echo urlencode("hello world & goodbye");
// "hello+world+%26+goodbye"

echo urldecode("hello+world+%26+goodbye");
// "hello world & goodbye"

// ===== rawurlencode / rawurldecode =====
// Uses %20 for spaces (RFC 3986)

echo rawurlencode("hello world & goodbye");
// "hello%20world%20%26%20goodbye"

echo rawurldecode("hello%20world%20%26%20goodbye");
// "hello world & goodbye"

// ===== When to use which? =====
// urlencode()    → for query string values (form-style)
// rawurlencode() → for URL path segments (RFC 3986)

// Building a URL with encoded path and query
$path = rawurlencode("my file.pdf");
$query = urlencode("search term & more");
$url = "https://example.com/files/{$path}?q={$query}";
// "https://example.com/files/my%20file.pdf?q=search+term+%26+more"

// ===== http_build_query (encode arrays as query strings) =====
$params = [
    "q" => "cats & dogs",
    "page" => 1,
    "tags" => ["php", "url encoding"]
];
echo http_build_query($params);
// "q=cats+%26+dogs&page=1&tags%5B0%5D=php&tags%5B1%5D=url+encoding"
?>

Java URLエンコード/デコード

JavaのURLEncoderURLDecoderクラスがURLエンコードを処理します:

import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// ===== URLEncoder.encode (uses + for spaces) =====

// Always specify UTF-8 charset!
String encoded = URLEncoder.encode(
    "hello world & goodbye", StandardCharsets.UTF_8
);
// "hello+world+%26+goodbye"

// Decode
String decoded = URLDecoder.decode(
    "hello+world+%26+goodbye", StandardCharsets.UTF_8
);
// "hello world & goodbye"

// ===== Convert + to %20 for RFC 3986 compliance =====
String rfc3986 = URLEncoder.encode("hello world", StandardCharsets.UTF_8)
    .replace("+", "%20");
// "hello%20world"

// ===== Java 11+ URI encoding =====
import java.net.URI;

URI uri = URI.create("https://example.com/search");
// For building URLs with encoded parameters:
String query = "q=" + URLEncoder.encode("hello world", StandardCharsets.UTF_8);
URI fullUri = URI.create("https://example.com/search?" + query);
// https://example.com/search?q=hello+world

// ===== Encoding path segments =====
String pathSegment = URLEncoder.encode("my file.pdf", StandardCharsets.UTF_8)
    .replace("+", "%20");
String url = "https://example.com/files/" + pathSegment;
// "https://example.com/files/my%20file.pdf"

一般的なURLエンコーディングの間違い

避けるべき最も一般的な落とし穴:

二重エンコーディング:既にエンコードされた文字列を再度エンコード。%20%2520になります。

// Double encoding example — a common bug!

const value = "hello world";

// Correct: encode once
const correct = encodeURIComponent(value);
// "hello%20world" ✓

// Bug: encode twice
const doubleEncoded = encodeURIComponent(encodeURIComponent(value));
// "hello%2520world" ✗  (%25 is the encoded form of %)

// How to detect double encoding:
// If you see %25 in your URLs, you likely have a double encoding issue
// %2520 = double-encoded space (%25 = %, 20 = space)
// %253A = double-encoded colon (%25 = %, 3A = :)

URL全体をエンコード:完全なURLにencodeURIComponent()を使用するとURL構造が壊れます。

// Encoding the entire URL — WRONG!
const url = "https://example.com/path?q=hello world";

// WRONG: breaks URL structure
encodeURIComponent(url);
// "https%3A%2F%2Fexample.com%2Fpath%3Fq%3Dhello%20world"

// CORRECT option 1: use encodeURI for full URLs
encodeURI(url);
// "https://example.com/path?q=hello%20world"

// CORRECT option 2: encode only the value
const base = "https://example.com/path";
const query = encodeURIComponent("hello world");
const fullUrl = base + "?q=" + query;
// "https://example.com/path?q=hello%20world"

UTF-8の忘れ:URLエンコーディングには常にUTF-8を使用してください。

パスセグメントのエンコード漏れ:スペースを含むパスもエンコードが必要です。

+記号の誤処理+はフォームではスペースを意味しますが、通常のURLではリテラルです。

APIでのURLエンコーディング

APIでの正しいURLエンコーディングは重要です:

クエリパラメータ:各パラメータ名と値を個別にエンコードする必要があります。

パスパラメータ:URLパスに埋め込まれた値もエンコードが必要です。

フォームデータapplication/x-www-form-urlencodedはスペースに+を使用します。

JSONペイロード:リクエストボディのJSONコンテンツはURLエンコード不要です。

// API URL encoding examples

// Query parameters — encode each value individually
const searchTerm = 'price > 100 & category = "electronics"';
const apiUrl = `https://api.example.com/search?q=${encodeURIComponent(searchTerm)}&limit=10`;
// "https://api.example.com/search?q=price%20%3E%20100%20%26%20...&limit=10"

// Path parameters — encode values embedded in paths
const username = "john@example.com";
const profileUrl = `https://api.example.com/users/${encodeURIComponent(username)}/profile`;
// "https://api.example.com/users/john%40example.com/profile"

// Form data (POST) — uses + for spaces
const formBody = new URLSearchParams({
  username: "john doe",
  password: "p@ss w0rd!"
}).toString();
// "username=john+doe&password=p%40ss+w0rd%21"

// JSON as query parameter — encode the entire JSON string
const filters = JSON.stringify({ price: { min: 10, max: 100 } });
const url = `/api/products?filters=${encodeURIComponent(filters)}`;
// "/api/products?filters=%7B%22price%22%3A%7B%22min%22%3A10%2C%22max%22%3A100%7D%7D"

よくある質問

URLエンコーディングとは何ですか?なぜ必要ですか?

URLエンコーディングは、安全でない文字をパーセント-16進数シーケンスに置き換えてURLで安全に送信するためのプロセスです。&、=、?、#などの特殊文字は構造的な意味を持ち、データとして使用する場合はエンコードが必要です。

encodeURIとencodeURIComponentの違いは?

encodeURI()はURL構造文字(:、/、?、#)を保持します。encodeURIComponent()は非予約文字以外のすべてをエンコードします。個別のパラメータ値にはencodeURIComponentを使用してください。

スペースには%20と+のどちらを使うべき?

URL(RFC 3986)には%20を使用。application/x-www-form-urlencodedにのみ+を使用。迷った場合は%20がより安全な選択です。

URLエンコーディングはすべての開発者が日常的に遭遇する基本的なWebスキルです。無料オンラインツールで即座にエンコードとデコードを行えます。

無料オンラインツールでURLを即座にエンコード・デコード。

𝕏 Twitterin LinkedIn
この記事は役に立ちましたか?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Partner Picks

Sponsor this article

Place your product next to this developer topic with tracked clicks.

Ask about article sponsorship

Related Articles

URLエンコード特殊文字:完全リファレンステーブル&例

URLパーセントエンコーディングの完全リファレンス。全特殊文字の一覧表、encodeURIComponentとencodeURIの使い分け。

Base64エンコード&デコード完全ガイド:コード例付き

無料のBase64エンコーダー&デコーダー。JavaScript、Python、Bash、PowerShellでの変換方法を詳しく解説。

URL エンコーダ/デコーダ オンラインガイド:パーセントエンコーディング、RFC 3986、ベストプラクティス

URL エンコーディング(パーセントエンコーディング)の完全ガイド。RFC 3986、encodeURIComponent vs encodeURI、Python urllib.parse、Java URLEncoder、一般的なエンコード文字、フォームエンコーディング、API クエリパラメータ、二重エンコーディングのデバッグ。

This site uses cookies for analytics and to display ads. By continuing to browse, you agree. Privacy Policy