Why URLs Need Encoding
A URL is both a human-readable address and a structured protocol format. That structure is useful, but it means some characters have special jobs. A question mark starts the query string. An ampersand separates query parameters. A slash separates path segments. A hash starts the fragment.
When one of those characters appears as data, it must be encoded so the browser does not treat it as syntax. That is why a search query like Jane Doe & Sons should become Jane%20Doe%20%26%20Sons before it is placed inside a URL parameter.
Percent-Encoding in Plain English
Percent-encoding represents bytes as a percent sign followed by two hexadecimal digits. A space is byte 20 in ASCII, so it becomes %20. The ampersand character is byte 26, so it becomes %26. Non-ASCII text is first encoded as UTF-8 bytes, then each byte is percent-encoded.
That last detail matters. Korean, Japanese, accented Latin characters, and emoji do not map to a single old ASCII byte. Correct URL encoding works at the byte level, not the character-count level.
encodeURI vs encodeURIComponent
JavaScript gives you two related functions:
encodeURIis for an already-formed URL. It leaves URL syntax characters such as:,/,?, and&alone.encodeURIComponentis for a single component, such as one query value. It encodes syntax characters because they should be treated as data.
Most bugs happen when a developer uses encodeURI on a query value. If the value contains &, the server may read it as a second parameter.
Query String Example
Suppose you want to build this search:
term=Jane Doe & Sons
city=Seoul
The safe query string is:
term=Jane%20Doe%20%26%20Sons&city=Seoul
Only the value was encoded. The = and & that define the query structure remain readable because they are syntax, not data.
Common Production Bugs
Double encoding is one of the most common issues. If %20 is encoded again, it becomes %2520. The %25 part represents a literal percent sign, so the receiving system sees the wrong value.
Double decoding is the opposite problem. It can turn a value that intentionally contains %25 into a broken escape sequence. Decode once at the boundary where data enters your application, then keep the value as normal text internally.
Another frequent issue is mixing form encoding with URI component encoding. Web forms often encode spaces as +, while encodeURIComponent uses %20. Many servers understand both in query strings, but not all contexts treat plus signs as spaces.
Real-World Places URL Encoding Breaks
Encoding bugs are common because URLs are often assembled across several systems: browser code, backend code, reverse proxies, email links, OAuth providers, analytics tools, and redirect handlers.
OAuth and login callbacks
OAuth login flows usually include a redirect_uri parameter. That value is itself a URL, so it must be encoded as a query value inside another URL.
If the nested callback URL is not encoded, the provider may read the callback's own ? and & as part of the outer URL. The result is a confusing login failure: the first parameter works, but everything after the nested ampersand disappears or becomes a separate parameter.
The practical rule is simple: when a full URL becomes a query parameter value, encode it with encodeURIComponent.
Search filters and user-entered text
Search boxes often accept spaces, plus signs, ampersands, slashes, Korean text, and emoji. If the frontend builds a URL by concatenating strings, a query like R&D tools can accidentally become two parameters: q=R and D tools.
This is why URL constructors and URLSearchParams are safer than manual string concatenation.
Signed URLs
Signed URLs are sensitive to exact bytes. If a path, query value, or signature is encoded differently between signing and verification, the signature may fail even though the URL looks visually similar.
Common causes include:
- Encoding once before signing and again before sending.
- Decoding a value before signature verification.
- Reordering query parameters when the signature expects the original order.
- Treating
+as a space in one layer but as a literal plus sign in another.
Analytics links and UTM parameters
Marketing and analytics links often contain campaign names, Korean text, spaces, and nested destination URLs. A broken encoded value can make analytics split one campaign into several variants or drop part of the original destination.
When comparing campaign data, decode the URL first and check whether utm_campaign, utm_source, and utm_content are actually what you intended.
Safer JavaScript Patterns
Prefer structured APIs over string concatenation:
const url = new URL("https://example.com/search");
url.searchParams.set("q", "Jane Doe & Sons");
url.searchParams.set("city", "Seoul");
console.log(url.toString());
For path segments, encode the segment itself:
const filename = "release notes 2026/07.md";
const url = `/files/${encodeURIComponent(filename)}`;
Do not use encodeURI for a single query value. It intentionally leaves characters such as & and ? alone.
Debugging Checklist
- Decide whether you are encoding a full URL, a path segment, or a query value.
- Encode data values, not structural separators.
- Watch for
%25, which often indicates double encoding. - Decode logs before comparing values with what a user typed.
- Be careful with nested redirect URLs and OAuth callback parameters.
- Use
URLandURLSearchParamswhen building URLs in JavaScript. - Confirm whether the server treats
+as a space or a literal plus sign. - For signed URLs, verify the exact string used for signing before changing encoding.
Use the Tool
Try the URL Encoder/Decoder to encode values, decode log output, and inspect query parameters without sending anything to a server.