Encoding

URL Encoding Explained: Percent-Encoding for Web Developers

Understanding URL encoding (percent-encoding): why special characters need encoding, how it works, and common pitfalls when building URLs and query strings.

HandyUtils January 14, 2026 5 min read

Ever wondered why your browser shows %20 instead of spaces, or why your carefully crafted URL broke when you added a search query? Welcome to the world of URL encoding, also known as percent-encoding.

What is URL Encoding?

URL encoding is a mechanism for representing characters that have special meaning in URLs, or characters that aren't allowed in URLs at all. It works by replacing problematic characters with a % followed by two hexadecimal digits representing the character's ASCII value.

For example:

  • Space → %20
  • Ampersand (&) → %26
  • Question mark (?) → %3F

Why URLs Need Encoding

URLs have strict rules about which characters they can contain. The URL specification (RFC 3986) defines two types of characters:

Reserved Characters

These characters have special meanings in URLs:

  • : separates scheme from path (https:)
  • / separates path segments
  • ? begins the query string
  • # begins the fragment
  • & separates query parameters
  • = assigns values to parameters
  • @ separates user info from host
  • And more: ! $ ' ( ) * + , ;

Unreserved Characters

These are always safe and never need encoding:

  • Letters: A-Z and a-z
  • Digits: 0-9
  • Special: - _ . ~

Everything else—including spaces, non-ASCII characters, and reserved characters used as data—must be percent-encoded.

The Percent-Encoding Algorithm

Encoding a character is straightforward:

  1. Determine the character's byte representation (usually UTF-8)
  2. Convert each byte to its hexadecimal value
  3. Prefix with %

For ASCII characters, it's simple:

Space (ASCII 32) → 32 in hex is 20 → %20
& (ASCII 38) → 38 in hex is 26 → %26

For non-ASCII characters (like emoji or accented letters), you get multiple percent-encoded bytes:

é (UTF-8: 0xC3 0xA9) → %C3%A9
🎉 (UTF-8: 0xF0 0x9F 0x8E 0x89) → %F0%9F%8E%89

Characters That Must Be Encoded

Always encode these when they appear in data (not as URL structure):

Character Encoded Reason
Space %20 Not allowed in URLs
" %22 Can break HTML attributes
< %3C Security (XSS prevention)
> %3E Security (XSS prevention)
# %23 Fragment identifier
% %25 Encoding escape character
%7B %7D Not allowed
| %7C Not allowed
\ %5C Not allowed
^ %5E Not allowed
~ %7E Sometimes encoded

Characters That Should NOT Be Encoded

Don't encode characters that are part of the URL structure:

  • The :// after the scheme
  • The / separating path segments (unless it's data)
  • The ? starting query strings
  • The # starting fragments
  • The & and = in query parameters

Encoding these breaks the URL's meaning.

Common Mistakes

1. Double Encoding

This happens when you encode an already-encoded string:

Original: Hello World
First encoding: Hello%20World
Double encoding: Hello%2520World  ← WRONG!

The % got encoded to %25, so %20 became %2520. This is a frequent bug when building URLs programmatically.

2. Encoding Entire URLs

Don't do this:

// WRONG
const url = encodeURIComponent('https://example.com/search?q=hello world');
// Result: https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Dhello%20world

This breaks the URL structure. Only encode the values:

// CORRECT
const query = encodeURIComponent('hello world');
const url = `https://example.com/search?q=${query}`;

3. Space: + vs %20

There's historical confusion here:

  • %20 is the standard URL encoding for space
  • + means space only in application/x-www-form-urlencoded (HTML forms)

In query strings from HTML forms, you might see either:

?name=John+Doe
?name=John%20Doe

Both are valid, but %20 is more universally understood. Use + only when specifically working with form data.

Query String Encoding

Query strings have their own rules:

https://example.com/search?name=John%20Doe&city=New%20York
  • Parameter names and values are encoded
  • & separates parameters (not encoded)
  • = assigns values (not encoded)

If your value contains & or =, they must be encoded:

const filter = 'status=active&type=user';
const encoded = encodeURIComponent(filter);  // status%3Dactive%26type%3Duser
const url = `https://api.example.com/search?filter=${encoded}`;

Path vs Query Encoding Differences

Path segments and query strings have slightly different rules:

Path encoding (more strict):

  • Spaces should be %20
  • + is a literal plus sign
  • Some characters like @ and : might need encoding

Query encoding (form-style):

  • Spaces can be + or %20
  • + is sometimes space (context-dependent)

When in doubt, use %20 for spaces everywhere.

JavaScript: encodeURI vs encodeURIComponent

JavaScript provides two functions with different purposes:

encodeURI()

Encodes a complete URL, preserving structural characters:

encodeURI('https://example.com/path with spaces?query=value')
// "https://example.com/path%20with%20spaces?query=value"

Safe characters: : / ? # [ ] @ ! $ & ' ( ) * + , ; =

encodeURIComponent()

Encodes a URL component (like a query value), encoding most special characters:

encodeURIComponent('hello?world&foo=bar')
// "hello%3Fworld%26foo%3Dbar"

Rule of thumb: Use encodeURIComponent() for individual values, encodeURI() for complete URLs (though building URLs by hand is better).

Modern URL Building

The best practice is using the URL API:

const url = new URL('https://example.com/search');
url.searchParams.set('query', 'hello world');
url.searchParams.set('filter', 'a=1&b=2');
console.log(url.href);
// "https://example.com/search?query=hello+world&filter=a%3D1%26b%3D2"

The URLSearchParams class handles encoding automatically and correctly.

Decoding URLs

To decode, use the inverse functions:

decodeURI('https://example.com/path%20with%20spaces')
// "https://example.com/path with spaces"

decodeURIComponent('hello%3Fworld')
// "hello?world"

Summary

URL encoding ensures special characters don't break your URLs:

  • Use encodeURIComponent() for query parameter values
  • Use encodeURI() for complete URLs (sparingly)
  • Prefer the URL and URLSearchParams APIs for building URLs
  • Watch out for double encoding
  • Remember: + for spaces is form-specific; %20 is universal

Need to encode or decode a URL? Try our URL Encoder/Decoder tool!

Related Topics
url encoding percent encoding encodeURIComponent query string special characters
Share this article

Continue Reading

Encoding
What is Base64 Encoding and When Should You Use It?

A complete guide to Base64 encoding: how it works, why it exists, and practical use cases for developers including data URIs, API authentication, and email attachments.

Encoding
Understanding Character Encoding: ASCII, Unicode, and UTF-8

From ASCII to Unicode to UTF-8: how computers represent text, why encoding matters, and how to avoid the dreaded mojibake (garbled text).

Security
What is HMAC? Message Authentication for Developers

Understanding HMAC (Hash-based Message Authentication Code): how it works, why it's more secure than plain hashes, and implementing it in your APIs.