Skip to main content
WHATWG URL Standard §4.4 IETF RFC 3986 Unicode 17.0 UTF-8 Byte-Based %HH Format

URL Encoding & Percent-Encoding Reference

Percent-encoding represents arbitrary octets as a percent sign (%) followed by two hexadecimal digits. Non-ASCII characters are converted to UTF-8 bytes before being percent-encoded according to the specific URL component's percent-encode set.

Percent-Encoding Inspector

Target URL Context:

Safely encodes any value to be embedded into a URL part. Equivalent to WHATWG Component Set and JavaScript encodeURIComponent().

11 chars
Percent-Encoded Output
Valid
hello%20world

UTF-8 Byte Pipeline: How Characters Become Percent-Encoded

WHATWG URL §4.4 & Unicode 17.0

Percent-encoding operates strictly on 8-bit byte octets, not on Unicode characters directly. When a non-ASCII character is entered into a URL, it is first serialized into its UTF-8 octets, and each resulting octet is then represented as a percent sign (%) followed by two uppercase hexadecimal digits.

Step 1 Character Glyph Euro Sign
Step 2 Unicode Code Point U+20AC Scalar Value
Step 3 UTF-8 Octets
E2 82 AC
3 bytes
Step 4 URL Percent-Encoded %E2%82%AC 3 Triplet Pairs (%HH)
Do NOT encode code points directly:

A common technical mistake is assuming that U+20AC becomes %20AC. That produces a space (%20) followed by the literal letters AC! In standards-conforming URL processing, every non-ASCII character must be mapped to UTF-8 bytes first.

Space Handling: When to Use %20 vs +

Critical Disambiguation

One of the most frequent sources of developer confusion is whether spaces in URLs should be encoded as %20 or +. The answer is strictly context-dependent:

Standard URL Specification

Path, Fragment & Component Encoding

Space is encoded as %20

Input: hello world
Result: hello%20world
Literal +: a+b → a+b (preserved)
  • Used by encodeURIComponent() and encodeURI().
  • Required in URL paths (e.g. /articles/my%20story/).
  • In this context, + represents a literal plus sign, not a space.
HTML Form Specification

application/x-www-form-urlencoded

Space is encoded as +

Input: hello world
Result: hello+world
Literal +: a+b → a%2Bb (escaped!)
  • Used by HTML form submissions (POST/GET) and URLSearchParams.
  • Used in query strings formatted as form data (e.g. ?q=my+search).
  • Because + means space, a literal plus sign must be encoded as %2B.
The "C++" Search Trap:

If a user searches for C++ in a query parameter formatted with application/x-www-form-urlencoded, sending ?q=C++ causes the server to receive C (two spaces)! To preserve the plus signs, the client must serialize it as ?q=C%2B%2B.

Context-Aware Character Reference Table

Standards Matrix

Unlike static tables that show a single value, this reference matrix displays how reserved delimiters and special characters are encoded across different URL components:

Char Name & Code Point UTF-8 Octets Component (encodeURIComponent) Form Data (URLSearchParams) Path Segment Structural Role in URLs
Space
Space U+0020
20 %20 + %20 Delimiter in HTTP headers, illegal unencoded in URIs
&
Ampersand U+0026
26 %26 %26 %26 Separates parameter pairs in query string and form data
+
Plus Sign U+002B
2B %2B %2B %2B Represents space in form-urlencoded; literal plus must be %2B
/
Forward Slash (Solidus) U+002F
2F %2F %2F %2F Hierarchical segment delimiter in URI path
?
Question Mark U+003F
3F %3F %3F %3F Introduces query string component
#
Number Sign (Hash) U+0023
23 %23 %23 %23 Introduces fragment/anchor identifier
=
Equals Sign U+003D
3D %3D %3D %3D Separates parameter name from value in query string
%
Percent Sign U+0025
25 %25 %25 %25 Introduces percent-encoded byte triplets (%HH)
:
Colon U+003A
3A %3A %3A %3A Terminates scheme; separates userinfo and port number
@
At Sign U+0040
40 %40 %40 %40 Separates userinfo credentials from host authority
Euro Sign U+20AC
E2 82 AC %E2%82%AC %E2%82%AC %E2%82%AC Requires 3 UTF-8 bytes (E2 82 AC) before percent-encoding
é
Latin Small Letter E with Acute U+00E9
C3 A9 %C3%A9 %C3%A9 %C3%A9 Requires 2 UTF-8 bytes (C3 A9) before percent-encoding
😀
Grinning Face Emoji U+1F600
F0 9F 98 80 %F0%9F%98%80 %F0%9F%98%80 %F0%9F%98%80 Requires 4 UTF-8 bytes (F0 9F 98 80) before percent-encoding

JavaScript & Web API Comparison: Which Function Should You Use?

Developer Guide

Choosing the wrong encoding function in JavaScript is one of the most common causes of broken URLs and security vulnerabilities. Below is the authoritative standards comparison:

encodeURIComponent() JavaScript (ECMAScript)
Best Used For: Individual query values, path segments, header values
Spaces ( ): %20
Slashes (/): Encoded as %2F
Delimiters: Encodes &, =, ?, #, +, /
encodeURI() JavaScript (ECMAScript)
Best Used For: Complete URL strings where structural delimiters should remain
Spaces ( ): %20
Slashes (/): Preserved as /
Delimiters: Preserves :, /, ?, #, &, =, +
URLSearchParams Web Standards API (Browser & Node.js)
Best Used For: Query string serialization and form submission data
Spaces ( ): + (plus sign)
Slashes (/): Encoded as %2F
Delimiters: Encodes &, =, +, #; serializes key=value pairs joined with &
new URL(href) WHATWG URL Standard (Browser & Node.js)
Best Used For: Full URL parsing, resolution, and normalized serialization
Spaces ( ): %20 in path and hash; + in searchParams
Slashes (/): Preserves structural path separators
Delimiters: Parses scheme, username, password, host, port, path, query, and hash

Recommended Modern Implementation Pattern

// 1. Parameter Value Encoding (Safe for query values)
const rawParam = "hello/world & co";
const encodedParam = encodeURIComponent(rawParam);
// → "hello%2Fworld%20%26%20co"

// 2. Query String Construction with URLSearchParams (Best practice)
const params = new URLSearchParams({ search: "C++ language", filter: "active" });
// → "search=C%2B%2B+language&filter=active" (Note: + for space, %2B for literal plus)

// 3. Complete URL Building with new URL()
const url = new URL("https://example.com/api/search");
url.search = params.toString();
// → "https://example.com/api/search?search=C%2B%2B+language&filter=active"

Edge Cases: Malformed Escapes & Double-Encoding Traps

Security & Parsing

Malformed Percent Sequences

Under the WHATWG URL Standard §4.4, if a percent sign (%) is not followed by two ASCII hexadecimal digits, it is preserved as a literal character rather than throwing a fatal error.

Malformed Input WHATWG Decoding Validator Warning
100% 100% Lone percent sign; should be encoded as %25 if literal data
%2 %2 Incomplete escape; missing second hex digit
%GG %GG Non-hexadecimal characters following %
%20 (double encode) %2520 % encoded as %25; double encoding alters data meaning

Double-Encoding Security Trap

Because the percent sign is itself encoded as %25, encoding an already-encoded string changes its meaning:

Original Text: hello world
→ First Encode →
Encoded (%20): hello%20world
→ Second Encode →
Double-Encoded (%2520): hello%2520world
The Strict Single-Pass Invariant:

Decoders must execute strictly one decode pass per action to prevent security vulnerabilities like directory traversal (%252E%252E%252F → %2E%2E%2F).

Normative Standards & Source Provenance

Verified Baseline

All percent-encoding algorithms, context rules, and byte representations on this page are verified against official living specifications:

  • WHATWG URL Living Standard§4.4 Percent-encoded bytes & §5 application/x-www-form-urlencoded (Official Specification)
    SHA-256 Checksum: c4987042a9b2b5883ef59c9b139a04a5bf4d39f75e985ba5740ea5002b8d4f40
  • IETF RFC 3986§2 Characters, §2.1 Percent-Encoding, §2.2 Reserved, §2.3 Unreserved (Official Specification)
    SHA-256 Checksum: 2c7921ba101684c8a2b53683a31c586ec6f376fdf243859eaec2b55f69c5e7b5
  • WHATWG HTML Living Standard§4.10.22.6 Form submission (application/x-www-form-urlencoded) (Official Specification)
  • The Unicode Standard, Version 17.0Section 3.9 Unicode Encoding Forms (UTF-8) (Official Specification)