Back to all guides

URL Encoding & Query Strings: RFC 3986 Percent-Encoding Developer Guide

Learn how special characters, spaces, and Unicode characters are escaped in web addresses, and how to avoid broken HTTP requests.

DK
Dipanshu Kumar
Founder & Software Architect at Tool Yaar
Updated: 2026-11-067 min read

Anatomy of a Uniform Resource Identifier (URI)

Every web request begins with a Uniform Resource Identifier (URI). Standardized under RFC 3986, a full URL consists of five distinct syntactic components: scheme (http/https), authority (host and port), path (/products/search), query string (?q=laptop&sort=asc), and optional fragment identifier (#reviews).

Because URLs must be transmitted across heterogeneous network hardware, protocols, and proxies, the permissible character set is strictly constrained to a small subset of 7-bit US-ASCII characters. Characters outside this set (such as spaces, punctuation, or non-Latin Unicode scripts) must be escaped through percent-encoding.

Reserved vs Unreserved Characters Under RFC 3986

RFC 3986 categorizes characters into two distinct classes:

โ€ข Unreserved Characters: Characters that never require encoding. These include uppercase letters (Aโ€“Z), lowercase letters (aโ€“z), decimal digits (0โ€“9), hyphen (-), underscore (_), period (.), and tilde (~).

โ€ข Reserved Characters: Characters that serve structural delimiting purposes within a URI. These include `:` `/` `?` `#` `[` `]` `@` `!` `$` `&` `'` `(` `)` `*` `+` `,` `;` `=`

If a reserved character is used for its structural role (such as `?` separating path from query), it remains bare. If it is used as literal data inside a parameter value (such as a password containing `&` or `#`), it MUST be percent-encoded to prevent breaking URI parsing logic.

How Percent-Encoding Transforms Bytes into Hex

Percent-encoding operates at the byte level. To encode a non-allowed character:

1. Convert the character into its UTF-8 byte sequence.

2. Express each byte as a two-digit hexadecimal number.

3. Prefix each hexadecimal pair with the percent symbol (%).

For example, the literal ampersand (&) has ASCII code 38, which equals 26 in hexadecimal; hence it encodes as `%26`. The Hindi letter "เค…" consists of three UTF-8 bytes (0xE0, 0xA4, 0x85) and encodes as `%E0%A4%85`.

The Great Space Debate: %20 vs Plus (+)

One of the most persistent confusions in web development is whether a space should be encoded as `%20` or `+`:

โ€ข In URI paths: Spaces MUST be encoded as `%20` (e.g., `/my%20documents/file.pdf`). A `+` in a path represents a literal plus character.

โ€ข In Query Strings: Under legacy HTML form submissions (`application/x-www-form-urlencoded`), spaces are frequently serialized as `+`. However, modern RFC 3986 standards recommend `%20` uniformly across both path and query parameters to avoid ambiguity.

encodeURI() vs encodeURIComponent() in JavaScript

JavaScript developers frequently cause bugs by choosing the wrong encoding function:

โ€ข `encodeURI()`: Encodes a complete URL. It preserves structural delimiters like `:`, `/`, `?`, and `&`, only escaping spaces and Unicode characters. Use this when you have a complete URL string that needs basic encoding.

โ€ข `encodeURIComponent()`: Encodes a specific query parameter value. It aggressively encodes all reserved delimiters (including `&`, `=`, and `/`). Use this on individual variable values before appending them to a query string.

The Query String Rule

Always use `encodeURIComponent()` on individual query values. Using `encodeURI()` will fail to escape `&` and `=` inside parameter values, splitting your query into corrupted keys.

Common URL Encoded Characters Reference Table

Frequently used percent-encoding character replacements:

CharacterASCII / UTF-8 HexPercent-Encoded ValueCommon Role in URLs
Space0x20%20 (or + in forms)Separator in text
Ampersand (&)0x26%26Separates query parameters
Question Mark (?)0x3F%3FInitiates the query string
Equals (=)0x3D%3DBinds key to value in query
Hash (#)0x23%23Initiates client-side fragment
Forward Slash (/)0x2F%2FSeparates path hierarchy
Colon (:)0x3A%3ASeparates scheme and port

Frequently Asked Questions

Q:What happens if a URL contains an unencoded # inside a query parameter?

The browser treats everything after the # as an internal page anchor (fragment identifier), completely stripping it from the HTTP request sent to the server.

Q:How do you decode a percent-encoded URL in JavaScript?

Use `decodeURIComponent(encodedString)` to decode parameter values, or `decodeURI(encodedUrl)` to decode a full web address.

Q:Can URLs contain emojis?

Yes, but emojis are multi-byte UTF-8 sequences. For example, the rocket emoji (๐Ÿš€) encodes into four hex bytes: `%F0%9F%9A%80`.

Q:Is URL encoding case-sensitive?

The percent-encoded hexadecimal digits themselves are case-insensitive (%2f is identical to %2F), but standard RFC conventions strongly prefer uppercase hexadecimal letters.

Interactive Tools

Try the Free Tools Mentioned in this Guide

DK
About the Author

Dipanshu Kumar

Dipanshu is the founder and lead software architect of Tool Yaar. He designs high-performance client-side web utilities, WebAssembly engines, and offline Android tools focused on zero-upload user privacy and universal digital accessibility.