URL encoding — also called percent-encoding — is something every web developer encounters. An & in a query parameter value breaks your URL. A space in a file path breaks your download link. A + that should be decoded as %2B gets decoded as a space instead. These bugs are subtle and annoying, and they’re all rooted in not understanding which characters are safe in which context.
This guide explains the two encoding modes, when to use each, and the practical scenarios where URL encoding matters.
Why URLs Need Encoding
URLs can only contain a subset of ASCII characters. The allowed characters are letters, digits, and a small set of special characters: -, ., _, ~, :, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ;, =.
Everything else — spaces, accented characters, Unicode, and characters with structural meaning in URLs — must be percent-encoded.
Percent-encoding represents a byte as a % followed by two hexadecimal digits:
| Character | Percent-encoded |
|---|---|
| Space | %20 |
& | %26 |
= | %3D |
+ | %2B |
# | %23 |
/ | %2F |
? | %3F |
The Two Modes: Component vs. Full URL
JavaScript exposes two functions, and understanding the difference is essential:
encodeURIComponent — Component mode
This encodes everything that isn’t a letter, digit, or one of: - _ . ! ~ * ' ( )
It encodes: : / ? # [ ] @ ! $ & ' ( ) * + , ; =
Use this when encoding a single value that will be part of a URL — a query parameter value, a path segment, a fragment identifier.
Example:
Input: "Hello World & Friends"
Encoded: "Hello%20World%20%26%20Friends"
If you include this in a URL as ?message=Hello%20World%20%26%20Friends, the %26 ensures the & is treated as part of the value, not as a query parameter separator.
encodeURI — Full URL mode
This encodes only characters that are definitely invalid in a URL. It does not encode characters that have structural meaning in URLs: : / ? # [ ] @ ! $ & ' ( ) * + , ; =
Use this when encoding an entire URL that you want to remain navigable.
Example:
Input: "https://example.com/search?q=hello world&lang=en"
Encoded: "https://example.com/search?q=hello%20world&lang=en"
The & between query parameters is preserved (it’s structural). The space in the query value is encoded. The URL remains a valid, navigable URL.
The + vs. %20 Problem
This is one of the most common sources of URL encoding bugs. In HTML form submissions with application/x-www-form-urlencoded (the default form encoding), spaces are encoded as + — not %20.
So if you receive a query string value like name=John+Doe:
- In
application/x-www-form-urlencodedcontext:+means space →John Doe - In a URL path context:
+is a literal plus sign →John+Doe
encodeURIComponent encodes spaces as %20, which is unambiguous. If you’re building query strings manually, use %20 for spaces to avoid this ambiguity.
The +-for-space convention is a legacy of HTML forms and should not be used for new API design.
When to Encode Which Parts of a URL
| URL part | Use | What to encode |
|---|---|---|
| Query parameter value | encodeURIComponent | The value, not the = or & |
| Path segment | encodeURIComponent | The segment, not the / |
| Fragment identifier | encodeURIComponent | The value after # |
| Full URL for display | encodeURI | The full string |
| Full URL for embedding | encodeURIComponent | The full URL (if it’s a value in another URL) |
The common mistake: using encodeURI on a query parameter value.
encodeURI("key=val&ue")
→ "key=val&ue" ← & is NOT encoded! This breaks the query string
encodeURIComponent("key=val&ue")
→ "key%3Dval%26ue" ← Correct: = and & are encoded
Practical Scenarios
Building a search URL with user input
const query = "C++ programming & data structures";
const url = `https://example.com/search?q=${encodeURIComponent(query)}`;
// → https://example.com/search?q=C%2B%2B%20programming%20%26%20data%20structures
Without encodeURIComponent, the + and & would break the URL structure.
Passing a URL as a query parameter
A redirect URL containing a return path:
const returnUrl = "https://app.example.com/dashboard?tab=settings";
const loginUrl = `https://auth.example.com/login?returnTo=${encodeURIComponent(returnUrl)}`;
// → https://auth.example.com/login?returnTo=https%3A%2F%2Fapp.example.com%2Fdashboard%3Ftab%3Dsettings
Here the entire URL is treated as a value and fully encoded, because ? and = and & inside it must not be interpreted as structure in the outer URL.
File names in URLs
Linking to a file with spaces or special characters in the name:
File: "Project Report (Q4 2025).pdf"
URL path: /files/Project%20Report%20(Q4%202025).pdf
The ( and ) are technically allowed in URLs but can cause problems in some contexts. Encoding them is safer.
OAuth redirect URIs
OAuth requires that redirect URIs be registered and exactly match. Encoding the URI consistently (with encodeURIComponent for the URI as a value in the authorization request) prevents mismatches. For working with the JWT tokens issued at the end of an OAuth flow — decoding claims, checking expiry, and verifying HMAC signatures — the JWT Decoder guide covers the full inspection workflow.
Decoding
The tool also decodes percent-encoded strings back to their original form. Common decode use cases:
Reading a log entry. Server logs often contain percent-encoded URLs. Paste the raw log line and decode it to see what the actual request was.
Debugging a query string. If you receive a malformed query string and you can’t tell which values contain encoded characters, decode it to see the original values.
Understanding an API endpoint. Some APIs return URLs in responses. If the URL is encoded, decode it to understand the structure.
Handling malformed encoded strings. The tool returns a readable error for invalid percent sequences (e.g., %GG) rather than throwing a cryptic exception.
URL Encoding vs. Base64
A common question: when should you Base64-encode a value in a URL vs. percent-encode it?
Percent-encoding is always the right choice for values you control. It’s URL-native, compact (only encodes the characters that need it), and universally understood by URL parsers.
Base64 in a URL (Base64URL format, using -_ instead of +/) is used in specific contexts where:
- The data is binary (bytes, not a string)
- The value is long and compact encoding matters
- The application has chosen to use Base64URL as a convention (JWTs do this)
For everyday query parameter values — names, IDs, search terms, filter values — percent-encoding is correct. Use Base64URL only when you have binary data or a specific protocol that requires it. For a complete explanation of Base64 and the Base64URL variant, see the Base64 guide.
The Hint Bar
The URL encoder shows a contextual hint explaining which encoding is appropriate for the current mode. If you’re unsure whether to use Component or Full URL mode, read the hint — it describes exactly which characters are preserved and which are encoded in each mode.
URL encoding is one of those areas where guessing usually works until it doesn’t. Understanding the two modes and applying encodeURIComponent for values and encodeURI for complete URLs will prevent the subtle bugs that appear only with user inputs containing special characters.