Back to Blog
EncodingWebURLs

URL Encoding Explained: Percent-Encoding, encodeURI vs encodeURIComponent

April 2, 2026 · 5 min read

A URL can only contain a limited set of ASCII characters. Spaces, non-ASCII characters, and several punctuation marks are not allowed in raw form. URL encoding — also called percent-encoding — converts these characters into a safe format that any system can transmit without ambiguity.

How Percent-Encoding Works

Each unsafe character is replaced by a percent sign followed by the two-digit hexadecimal code of the character's UTF-8 byte value:

Space  →  %20
/      →  %2F
:      →  %3A
@      →  %40
?      →  %3F
#      →  %23
&      →  %26
=      →  %3D
café   →  caf%C3%A9

The characters A–Z, a–z, 0–9 and - _ . ~ are "unreserved" and are never encoded.

Reserved vs Unreserved Characters

RFC 3986 divides URL characters into two categories:

CategoryCharactersMeaning
UnreservedA–Z a–z 0–9 - _ . ~Safe in any part of a URL, never encoded
Reserved: / ? # [ ] @ ! $ & ' ( ) * + , ; =Have special meaning in URL structure — encode if used as data

JavaScript: encodeURI vs encodeURIComponent

JavaScript has two built-in encoding functions, and choosing the wrong one is a very common bug.

encodeURI()

Encodes a complete URL. It does NOT encode characters that have a structural role in a URL — : / ? # @ & = — because doing so would break the URL structure.

encodeURI("https://example.com/search?q=hello world&lang=en")
// "https://example.com/search?q=hello%20world&lang=en"
// Note: ? & = are NOT encoded — they keep their structural meaning

encodeURIComponent()

Encodes a component of a URL (a query parameter value, a path segment). It encodes everything except unreserved characters — including : / ? # @ & =.

encodeURIComponent("hello world & more")
// "hello%20world%20%26%20more"

// Build a query string safely:
const q = encodeURIComponent("C++ & Java");
const url = `https://example.com/search?q=${q}`;
// "https://example.com/search?q=C%2B%2B%20%26%20Java"

The rule

Use encodeURI() for a full URL. Use encodeURIComponent() for individual parameter values. When in doubt, use encodeURIComponent() — it's safer.

Python

from urllib.parse import quote, quote_plus, urlencode

# Encode a path segment (/ is safe)
quote("/path/to résumé")      # "/path/to%20r%C3%A9sum%C3%A9"

# Encode a query parameter value (/ is encoded too)
quote("hello world", safe="") # "hello%20world"

# Build a query string
urlencode({"q": "hello world", "lang": "en"})
# "q=hello+world&lang=en"  (note: + for spaces in query strings)

Space: %20 vs +

Spaces can be encoded as either %20 or + depending on context:

EncodingWhen to use
%20In URL paths and most modern contexts. Always correct.
+In application/x-www-form-urlencoded query strings (HTML forms). Not valid in paths.

Try It

Use the Text Tools on io9.me to URL-encode and decode strings instantly — including both standard and form-encoded modes.