Differences Between URL Encoding (Percent-Encoding) and HTML Entity Encoding
When you copy a search URL from your browser's address bar and paste it into a chat window, non-ASCII characters often turn into sequences like %EC%84%9C%EC%9A%B8. Meanwhile, viewing the HTML source of a web forum shows sequences like < and &. While both mechanisms transform special characters into safe ASCII representations, URL Encoding (Percent-Encoding) and HTML Entity Encoding operate in completely different parsing contexts and solve completely different problems. Confusing the two leads to broken query strings, double-escaped text, or Cross-Site Scripting (XSS) vulnerabilities. This article compares both encodings with concrete JavaScript examples and highlights common production mistakes.
1. URL Encoding (Percent-Encoding, RFC 3986)
The syntax of Uniform Resource Identifiers (URIs/URLs) is governed by RFC 3986. Inside a URL, certain characters serve as structural delimiters (reserved characters): `?` starts the query string, `&` separates key-value pairs, `=` separates a key from its value, `/` separates path segments, and `#` introduces a fragment identifier. Furthermore, spaces and non-ASCII characters (such as Korean, Japanese, or emojis) are not permitted directly in standard URI syntax.
Percent-encoding converts a character into its UTF-8 byte sequence and represents each byte as a percent sign (`%`) followed by two hexadecimal digits. Under RFC 3986, only alphanumeric characters (`A–Z`, `a–z`, `0–9`) and four unreserved marks (`-`, `.`, `_`, `~`) remain unencoded everywhere:
- Space (` `) →
%20(or+inside `application/x-www-form-urlencoded` query strings) - Ampersand (`&`) →
%26 - Korean character `"가"` (UTF-8 bytes `EA B0 80`) →
%EA%B0%80
Example: Safely Passing a Search Query Containing `&`
Suppose a user searches for Seoul Weather & Dust. If you concatenate that string directly into `?q=Seoul Weather & Dust`, the server's query parser will treat `&` as the start of a brand-new query parameter named `Dust` and truncate `q` to `"Seoul Weather "`. Encoding the parameter value prevents delimiter collision:
encodeURIComponent("Seoul Weather & Dust");
// "Seoul%20Weather%20%26%20Dust"
// Using the standard URL / URLSearchParams API handles encoding automatically:
const url = new URL("https://example.com/search");
url.searchParams.set("q", "Seoul Weather & Dust");
url.href;
// "https://example.com/search?q=Seoul+Weather+%26+Dust"
Notice that `URLSearchParams` encodes spaces as `+` instead of `%20` because it follows the HTML form serialization spec (`application/x-www-form-urlencoded`). While almost all query parsers treat both `+` and `%20` as spaces inside `?query=...`, `+` inside a URL path segment (`/files/a+b.txt`) is treated as a literal plus sign—so always use `encodeURIComponent()` for path segments.
2. HTML Entity Encoding (Output Escaping & XSS Defense)
Inside an HTML document, `<` opens an element tag, `>` closes a tag, `&` begins a character reference, and `"` or `'` closes an attribute value. If untrusted user input is interpolated directly into HTML markup without escaping, the browser's HTML parser cannot distinguish user text from executable `