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?

Base64 explained with a worked example: the 64-character alphabet, padding, why it is not encryption, URL-safe Base64, data URIs, MIME, and common decoding errors.

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? How Hash-Based Message Authentication Works

HMAC explained for developers: how it works, HMAC vs MAC, HMAC-SHA256 vs SHA-1, and how to verify signatures in your API.