You've seen %20 in a URL and probably assumed it just means "space" without thinking much further. That's correct, but it's worth understanding the actual mechanism — because the moment you're building a search feature, a redirect URL, or a form that submits special characters, getting encoding wrong produces bugs that are genuinely annoying to debug (a query that silently truncates at an &, a redirect that breaks because of an unescaped ?).
Why URLs restrict characters at all
A URL has structural syntax — characters like /, ?, &, #, and = aren't just data, they're delimiters that separate the path from the query string, one query parameter from another, and so on. If your actual data — say, a search term like "cats & dogs" — contains one of those characters unescaped, the URL parser can't tell whether that & is part of your search term or the start of a new query parameter. Spaces are disallowed for a more basic reason: URLs were designed to be safely passed around in contexts (early email clients, command lines, printed text) where a bare space could get silently stripped, wrapped, or misread.
Percent-encoding (also called URL encoding) solves this by giving every character outside a small "safe" set a way to be represented using only characters a URL can always carry unambiguously: letters, digits, and a handful of reserved punctuation marks.
The %XX mechanism
Percent-encoding represents any character as a % followed by its byte value in two-digit hexadecimal. A space (ASCII 32, which is 20 in hex) becomes %20. An ampersand (ASCII 38, 26 in hex) becomes %26. A character outside the basic ASCII range — say, an emoji or a non-Latin character — first gets converted to its UTF-8 byte sequence, and each byte of that sequence gets its own %XX encoding, which is why encoding non-ASCII text can produce several %XX groups for a single character.
You might also see + used to represent a space instead of %20 — that's a convention specific to the application/x-www-form-urlencoded format used by HTML form submissions, not a general URL rule. Outside form bodies, a literal + means a literal plus sign, and spaces should be %20.
encodeURIComponent vs encodeURI — the distinction that actually matters
JavaScript gives you two built-in functions for this, and mixing them up is a very common source of bugs:
encodeURIComponent() escapes everything except letters, digits, and a small set of characters (- _ . ! ~ * ' ( )). Critically, this includes escaping /, ?, &, =, and # — the characters that have structural meaning in a URL. Use this when you're encoding a single piece of data that will be inserted into a URL — a query parameter value, a path segment — because you want every character in your data treated as literal data, not as URL syntax.
encodeURI() escapes far less — it assumes you're passing in an entire, already-structured URL and leaves the structural characters (/ ? : @ & = + $ #) alone, only encoding things like spaces and genuinely unsafe characters. Use this only when you have a complete URL you want to make safe for transmission without breaking its existing structure.
The bug this distinction causes constantly: someone uses encodeURI() on a query parameter value that itself contains an & (say, a search term "rock & roll"), expecting it to be escaped — but encodeURI() leaves & alone, because it assumes you're passing a full URL where & is meant to separate parameters. The result: the server sees two parameters instead of one value, and the second half silently disappears or breaks parsing. The fix is almost always to use encodeURIComponent() for individual values and only use encodeURI() (or build the URL from already-encoded pieces) when handling a complete URL string.
Real case — encoding a search query
Building a search URL like https://example.com/search?q=rock & roll bands needs the query value encoded before insertion:
const query = "rock & roll bands";
const url = "https://example.com/search?q=" + encodeURIComponent(query);
// https://example.com/search?q=rock%20%26%20roll%20bands
Note both the space (%20) and the ampersand (%26) are escaped — exactly what you want, since both would otherwise be misread as URL structure.
Real case — a redirect URL passed as a query parameter
A very common real-world pattern: after login, redirect the user back to where they came from, passed as a query string value: /login?redirect=https://example.com/dashboard?tab=billing. Without encoding, the inner URL's own ? and = get misread as part of the outer query string, and the server sees a malformed or truncated redirect target. Encode the inner URL first:
const redirectTo = "https://example.com/dashboard?tab=billing";
const loginUrl = "/login?redirect=" + encodeURIComponent(redirectTo);
// /login?redirect=https%3A%2F%2Fexample.com%2Fdashboard%3Ftab%3Dbilling
Real case — form submission
When a browser submits an HTML form with method="GET" or a standard (not multipart) POST, it automatically percent-encodes every field value using the application/x-www-form-urlencoded convention — spaces as +, special characters as %XX. This happens for you, but it's worth knowing it's happening, especially when you're manually reconstructing a similar request in code (via fetch or an API client) and need to replicate the same encoding yourself.
Encode or decode anything quickly
Our URL Encoder/Decoder supports both modes directly — toggle between encodeURIComponent (encode everything, for a single value) and encodeURI (keep URL structure intact, for a complete URL) depending on which case you're in, and decode an encoded string back to readable text.