You've built a search feature, passed a query string in a URL, and watched it silently break because someone typed an ampersand or a space. Or you've hit an API endpoint and gotten a 400 error because a parameter value had a slash in it. URL encoding — or the lack of it — is the culprit almost every time.
The URL Encoder/Decoder at DevToolShack encodes and decodes any string instantly, right in your browser. But understanding why encoding is needed will save you hours of debugging.
Why URLs Need Encoding
URLs are restricted to a specific set of ASCII characters. Characters outside this safe set — spaces, accented letters, emoji, most punctuation — must be converted into a format the URL can safely carry. Without encoding, these characters either get stripped, misinterpreted, or cause the URL to be parsed incorrectly.
The mechanism is called percent-encoding: each unsafe character is replaced by a % followed by its two-digit hexadecimal ASCII code.
space → %20
& → %26
= → %3D
+ → %2B
/ → %2F
? → %3F
# → %23
@ → %40
Safe vs Unsafe Characters
| Category | Characters | Encoding needed? |
|---|---|---|
| Unreserved (always safe) | A-Z a-z 0-9 - _ . ~ | Never |
| Reserved (structural) | : / ? # [ ] @ ! $ & ' ( ) * + , ; = | When used as data, not structure |
| Everything else | Spaces, accents, emoji, symbols | Always |
The reserved characters are the tricky ones. A / in a URL path is structural — it separates path segments. But if your data contains a slash (a file path, a date like 2025/10/13), you must encode it as %2F or it will be treated as a path separator.
The Two Functions You Need in JavaScript
JavaScript has two pairs of encoding functions and it matters which you use:
// encodeURI — encodes a full URL, leaves structural characters alone
encodeURI("https://example.com/search?q=hello world&lang=en");
// "https://example.com/search?q=hello%20world&lang=en"
// Note: & and = are NOT encoded — they're part of the URL structure
// encodeURIComponent — encodes a value, including structural characters
encodeURIComponent("hello world & more");
// "hello%20world%20%26%20more"
// Note: & IS encoded — this is for encoding parameter VALUES
encodeURI on a query parameter value. Because it doesn't encode & and =, any value containing those characters will corrupt your query string. Always use encodeURIComponent for parameter values.Building Query Strings Safely
The safest way to build query strings in JavaScript is with URLSearchParams — it handles encoding automatically:
const params = new URLSearchParams({
q: "hello world & more",
category: "dev/tools",
page: 1
});
const url = `https://example.com/search?${params}`;
// "https://example.com/search?q=hello+world+%26+more&category=dev%2Ftools&page=1"
Note that URLSearchParams encodes spaces as + (application/x-www-form-urlencoded format) rather than %20. Most servers accept both, but if your API requires %20, use encodeURIComponent manually.
Decoding URLs
To decode, use the matching decode functions:
decodeURI("https://example.com/search?q=hello%20world");
// "https://example.com/search?q=hello world"
decodeURIComponent("hello%20world%20%26%20more");
// "hello world & more"
When debugging a broken URL — especially one you've received from a third party or pulled from a log file — paste it into the URL Encoder/Decoder to instantly see the decoded form. Much faster than reading percent-codes manually.
Common Encoding Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| Query parameter value gets truncated | Unencoded & in value starts a new parameter | encodeURIComponent(value) |
Space in URL becomes + or breaks | Spaces are not URL-safe | Encode as %20 or + |
| Path segment treated as directory | Unencoded / in data | Encode as %2F |
| Fragment ignored | Unencoded # in parameter value | Encode as %23 |
| Non-ASCII characters cause 400 errors | Accented letters, emoji not encoded | encodeURIComponent() handles all of these |
URL Encoding in Other Languages
# Python
from urllib.parse import quote, quote_plus, urlencode
quote("hello world & more") # 'hello%20world%20%26%20more'
quote_plus("hello world & more") # 'hello+world+%26+more'
# Building a full query string
urlencode({"q": "hello world", "page": 1})
# 'q=hello+world&page=1'
# PHP
urlencode("hello world & more"); // 'hello+world+%26+more'
rawurlencode("hello world & more"); // 'hello%20world%20%26%20more'
# Building query strings
http_build_query(["q" => "hello world", "page" => 1]);
// 'q=hello+world&page=1'