Every developer has hit this bug: you pass a search query to an API, and it works perfectly until someone searches for "Tom & Jerry." The ampersand splits your query parameter in half. The server receives q=Tom and a mysterious second parameter called Jerry.

URL encoding exists to prevent exactly this kind of chaos.

1. The Anatomy of a URL

Before we can understand encoding, we need to understand what a URL is made of. RFC 3986 defines the structure:

https://api.example.com:8080/v2/search?q=hello+world&lang=en#results
\___/   \_______________/\___/\________/ \__________________/ \_____/
scheme       host        port   path        query string      fragment

Each part has its own rules about which characters are allowed. The ? separates the path from the query. The & separates query parameters. The # marks the fragment. The / separates path segments.

These characters are called reserved characters. If your data contains one of them, the URL parser can't tell the difference between structure and content. That's where percent-encoding comes in.

2. How Percent-Encoding Works

Percent-encoding replaces unsafe characters with a % followed by two hexadecimal digits representing the character's ASCII (or UTF-8) byte value.

  • Space → %20 (ASCII 32 = hex 20)
  • &%26 (ASCII 38 = hex 26)
  • =%3D (ASCII 61 = hex 3D)
  • #%23 (ASCII 35 = hex 23)
  • /%2F (ASCII 47 = hex 2F)

So "Tom & Jerry" in a query parameter becomes Tom%20%26%20Jerry. The URL parser now sees the %26 as data, not as a parameter separator.

What About the + Sign?

In HTML form submissions (application/x-www-form-urlencoded), spaces are encoded as + instead of %20. Both are valid, but they belong to different specs. %20 is the RFC 3986 standard. + is the HTML form convention. Most servers accept both, but it's a common source of double-encoding bugs.

3. encodeURI vs. encodeURIComponent

JavaScript gives you two encoding functions, and using the wrong one is one of the most common web development mistakes.

encodeURI()

Encodes a full URL. It leaves structural characters alone (: / ? # & =) because it assumes they're part of the URL's structure.

encodeURI("https://example.com/path?q=hello world")
// "https://example.com/path?q=hello%20world"
// ✅ The :// and ? are preserved

encodeURIComponent()

Encodes a single value within a URL. It encodes everything except letters, digits, and - _ . ~ .

encodeURIComponent("hello world&foo=bar")
// "hello%20world%26foo%3Dbar"
// ✅ The & and = are escaped because they're DATA, not structure

The Golden Rule

Building a full URL from scratch? Use encodeURI(). Inserting a user-provided value into a query parameter? Always use encodeURIComponent().

// ❌ WRONG: encodeURI won't escape the & in the user's input
const url = encodeURI(`https://api.com/search?q=${userInput}`);

// ✅ RIGHT: encode just the value
const url = `https://api.com/search?q=${encodeURIComponent(userInput)}`;

4. Unicode and Internationalized URLs

ASCII only covers 128 characters. What happens when someone searches for "café" or "日本語"?

The character is first converted to its UTF-8 byte sequence, and then each byte is percent-encoded individually:

  • "é" → UTF-8 bytes: C3 A9%C3%A9
  • "日" → UTF-8 bytes: E6 97 A5%E6%97%A5

Modern browsers hide this complexity by displaying decoded Unicode in the address bar while sending the encoded version over the wire. But if you're logging URLs or building them manually, you need to be aware of this multi-byte encoding.

5. Common Pitfalls

Double Encoding

If you encode a value that's already encoded, %20 becomes %2520 (the % itself gets encoded to %25). The server receives a literal %20 string instead of a space. Always encode raw values, never pre-encoded strings.

Forgetting to Encode Path Segments

Most developers remember to encode query parameters but forget that path segments can contain special characters too. A file named my report (final).pdf needs encoding in the path:

/files/my%20report%20(final).pdf

API Keys in URLs

If your API key contains + or / (common in Base64-encoded keys), they must be percent-encoded when placed in a URL. Otherwise the / creates a false path segment and the + becomes a space.

Conclusion

URL encoding is invisible when it works and catastrophic when it doesn't. The rules are simple: encode values with encodeURIComponent(), never double-encode, and test with special characters like & = + # / and Unicode.

Need to debug a messy URL? Use our URL Encoder to encode, decode, and parse query strings instantly in your browser.