You've seen %20 in URLs. You've seen & in HTML. You might have wondered why these exist and when you need to use them. This guide explains URL encoding from the ground up — what it is, why it matters, and how to use it in code.

What is URL encoding?

URL encoding (also called percent encoding) converts characters that aren't allowed in URLs into a safe format. The format is a % sign followed by two hexadecimal digits representing the character's ASCII code.

Space   → %20
&       → %26
=       → %3D
?       → %3F
#       → %23
/       → %2F
+       → %2B
@       → %40

Why does URL encoding exist?

URLs can only contain a limited set of characters: letters (A–Z, a–z), digits (0–9), and a few special characters (-, _, ., ~). Every other character must be percent-encoded.

This rule exists because URLs travel through many different systems — web servers, proxies, browsers, routers — each with its own character restrictions. Percent encoding is the universal safe format.

Why %20? Where does the 20 come from?

The 20 is the hexadecimal ASCII code for a space character. Space = ASCII 32 decimal = 20 hexadecimal. So %20 literally means "the character with ASCII code 0x20".

Space: ASCII 32 → hex 20 → %20
&:     ASCII 38 → hex 26 → %26
=:     ASCII 61 → hex 3D → %3D

%20 vs + for spaces

You'll see spaces encoded two ways:

  • %20 — standard percent encoding, works everywhere
  • + — HTML form encoding (application/x-www-form-urlencoded), only valid in query strings

Use %20 for paths. Either works for query strings, but %20 is safer and more consistent.

encodeURI vs encodeURIComponent

JavaScript has two encoding functions — knowing which to use is critical:

const url = "https://example.com/search?q=hello world&lang=en";

encodeURI(url)
// "https://example.com/search?q=hello%20world&lang=en"
// Preserves: : / ? & = # @ (URL structural characters)

encodeURIComponent("hello world&lang=en")
// "hello%20world%26lang%3Den"
// Encodes EVERYTHING except letters, digits, - _ . ~

Rule: Use encodeURIComponent() for individual query parameter values. Use encodeURI() for complete URLs.

URL encoding in different languages

// JavaScript
encodeURIComponent("hello world")  // "hello%20world"
decodeURIComponent("hello%20world") // "hello world"

// Python
from urllib.parse import quote, unquote
quote("hello world")               # "hello%20world"
unquote("hello%20world")           # "hello world"

// PHP
urlencode("hello world")           // "hello+world"
urldecode("hello+world")           // "hello world"
rawurlencode("hello world")        // "hello%20world"

// Go
import "net/url"
url.QueryEscape("hello world")     // "hello+world"
url.PathEscape("hello world")      // "hello%20world"

Common URL encoding mistakes

Double encoding

// ✗ Encoding an already-encoded URL
encodeURIComponent("hello%20world")
// Results in: "hello%2520world" (% itself gets encoded to %25)

// ✓ Decode first, then encode
encodeURIComponent(decodeURIComponent("hello%20world"))

Not encoding query parameters

// ✗ Will break if value contains & or =
const url = \`https://example.com?q=\${userInput}\`;

// ✓ Always encode query values
const url = \`https://example.com?q=\${encodeURIComponent(userInput)}\`;

Try it free — URL Encoder & Decoder

Encode and decode URLs instantly. Supports both encodeURI and encodeURIComponent modes.

Open tool →