URL Encoding Explained: encodeURI vs encodeURIComponent
· Cosyslabs
URL encoding converts characters that are not allowed in URLs into percent-encoded equivalents using the format %XX where XX is the hexadecimal ASCII code. Use encodeURIComponent to encode individual query parameter values and path segments. Use encodeURI only when encoding a complete URL while preserving its structural characters.
Why URL Encoding Exists
URLs can only contain a limited set of ASCII characters. Characters outside this set — including spaces, Unicode characters, and many punctuation marks — must be percent-encoded before being placed in a URL.
The allowed characters without encoding are:
- Letters:
A–Z,a–z - Digits:
0–9 - Unreserved symbols:
-,_,.,~ - Reserved structural characters:
:,/,?,#,[,],@,!,$,&,',(,),*,+,,,;,=
Everything else requires percent-encoding.
How Percent-Encoding Works
A percent-encoded character is written as % followed by two uppercase hex digits representing the byte value:
Space → %20
@ → %40
/ → %2F
? → %3F
= → %3D
& → %26
+ → %2B
# → %23
For multi-byte UTF-8 characters, each byte is encoded separately:
é → %C3%A9 (UTF-8: 0xC3 0xA9)
中 → %E4%B8%AD (UTF-8: 0xE4 0xB8 0xAD)
encodeURIComponent vs encodeURI
JavaScript provides two encoding functions that differ in which characters they leave unencoded.
encodeURIComponent
Encodes everything except: A–Z a–z 0–9 - _ . ! ~ * ' ( )
Use this for encoding values that go inside a URL — query parameter values, path segments that contain special characters.
encodeURIComponent("hello world"); // "hello%20world"
encodeURIComponent("user@example.com"); // "user%40example.com"
encodeURIComponent("price=10&qty=2"); // "price%3D10%26qty%3D2"
encodeURIComponent("https://example.com"); // "https%3A%2F%2Fexample.com"
encodeURI
Encodes everything except: A–Z a–z 0–9 - _ . ! ~ * ' ( ) plus : / ? # [ ] @ ! $ & ' ( ) * + , ; =
Use this for encoding a complete URL where you want to preserve structural characters.
encodeURI("https://example.com/path with spaces?q=hello world");
// "https://example.com/path%20with%20spaces?q=hello%20world"
// But it does NOT encode & = ? / : which are structural
encodeURI("https://example.com?a=1&b=2");
// "https://example.com?a=1&b=2" (unchanged — & and = preserved)
The Key Difference
const search = "coffee & cake";
// Wrong: encodeURI does not encode & so it breaks query string parsing
const wrongUrl = `https://example.com/search?q=${encodeURI(search)}`;
// https://example.com/search?q=coffee%20&%20cake ← & splits the param!
// Correct: encodeURIComponent encodes & to %26
const rightUrl = `https://example.com/search?q=${encodeURIComponent(search)}`;
// https://example.com/search?q=coffee%20%26%20cake ← correct
Building URLs Correctly
Manual String Concatenation (avoid)
// Fragile — easy to forget encoding
const url = `https://api.example.com/search?q=${query}&lang=${lang}`;
Using URLSearchParams (recommended)
const params = new URLSearchParams({
q: "coffee & cake",
lang: "en",
page: 1,
});
const url = `https://api.example.com/search?${params.toString()}`;
// https://api.example.com/search?q=coffee+%26+cake&lang=en&page=1
Note: URLSearchParams uses + for spaces (application/x-www-form-urlencoded format) rather than %20. Both are valid in query strings.
Using the URL API (most robust)
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "coffee & cake");
url.searchParams.set("lang", "en");
url.pathname = `/users/${encodeURIComponent(username)}/profile`;
console.log(url.toString());
// https://api.example.com/users/john%40doe/profile?q=coffee+%26+cake&lang=en
Common Mistakes
Encoding the Entire URL with encodeURIComponent
// Wrong — encodes the : and / making the URL invalid
const url = encodeURIComponent("https://example.com/path?q=hello");
// "https%3A%2F%2Fexample.com%2Fpath%3Fq%3Dhello" ← broken URL
// Correct — encode only the value
const value = encodeURIComponent("hello world");
const url = `https://example.com/path?q=${value}`;
Double-Encoding
// Wrong — already encoded string gets encoded again
const encoded = "hello%20world";
const doubleEncoded = encodeURIComponent(encoded);
// "hello%2520world" ← %25 is the encoding of %
// Check before encoding
function safeEncode(str) {
try {
// If decoding succeeds without error, it may already be encoded
const decoded = decodeURIComponent(str);
return decoded === str ? encodeURIComponent(str) : str;
} catch {
return encodeURIComponent(str);
}
}
Forgetting to Encode Path Segments
// Wrong — / in username breaks the path
const username = "john/doe";
const url = `https://example.com/users/${username}`;
// https://example.com/users/john/doe ← "doe" becomes a separate segment
// Correct
const url = `https://example.com/users/${encodeURIComponent(username)}`;
// https://example.com/users/john%2Fdoe
Using + as Space Outside Query Strings
The + character represents a space only in application/x-www-form-urlencoded content (HTML form submissions). In URL paths, + is a literal plus sign, not a space.
Path: /search/hello+world → "hello+world" (literal +, wrong)
Path: /search/hello%20world → "hello world" (correct)
Query: ?q=hello+world → "hello world" (valid in query strings)
Query: ?q=hello%20world → "hello world" (also valid)
Decoding
decodeURIComponent("hello%20world"); // "hello world"
decodeURIComponent("user%40example.com"); // "user@example.com"
decodeURIComponent("%E4%B8%AD"); // "中"
// Always wrap in try/catch — malformed sequences throw URIError
try {
const decoded = decodeURIComponent(userInput);
} catch (e) {
console.error("Invalid percent-encoding:", e);
}
Try It Now
Encode and decode URLs instantly with the URL Encoder/Decoder Tool — choose between full URL encoding and component encoding modes.
More Tools from Cosyslabs
- Unit Convert All — Convert measurement values before embedding them in query parameters (e.g., temperature, weight, distance). Handles the unit conversion step so you only need to percent-encode the final value.
- PDF Convert All — Process and convert PDFs online. PDF download links often require URL-encoded filenames — this context is a practical example of
encodeURIComponentin action. - Rough Estimator — Estimate development time and cost for web projects, including tasks like implementing URL-safe routing in SPAs.
- Cosyslabs — The studio behind Dev Tools !, Routine Toolkit, Astrilio, CastFleet, and more.