URL Decoder
Convert percent-encoded strings back to their original readable form. URL decoding transforms %XX codes into their corresponding characters.
How URL Decoding Works
| Encoded | Decoded | Description |
|---|---|---|
| %20 | (space) | Space character |
| %26 | & | Ampersand |
| %3D | = | Equals sign |
| %2F | / | Forward slash |
| %3F | ? | Question mark |
| %25 | % | Percent sign |
URL Decode Implementation
``javascript
// Built-in JavaScript decoding
function urlDecode(encodedString) {
try {
return decodeURIComponent(encodedString);
} catch (error) {
return decodeURIComponent(
encodedString.replace(/%(?![0-9A-Fa-f]{2})/g, '%25')
);
}
}
// Handle + as space (common in query strings)
function urlDecodeWithPlus(encodedString) {
return decodeURIComponent(encodedString.replace(/\+/g, ' '));
}
// Examples
urlDecode('Hello%20World'); // "Hello World"
urlDecode('%E4%B8%AD%E6%96%87'); // "δΈζ"
`
Decoding Different URL Parts
`javascript
// Parse and decode full URL
function parseEncodedUrl(url) {
const parsed = new URL(url);
return {
pathname: decodeURIComponent(parsed.pathname),
params: Object.fromEntries(parsed.searchParams)
};
}
`
Use this decoder to make URL-encoded strings readable.
Decoding, and Where It Goes Wrong
`javascript
decodeURIComponent('a%20b%26c'); // 'a b&c'
decodeURI('https://ex.com/a%20b'); // 'https://ex.com/a b'
`
Three failure modes worth knowing:
+ is not a space to decodeURIComponent. In application/x-www-form-urlencoded
bodies and many query strings, + means a space β but decodeURIComponent('a+b') returns
'a+b'. Replace + with %20 first, or use URLSearchParams, which handles it.
Malformed input throws. decodeURIComponent('%') raises a URIError. Any decode of
user input belongs in a try/catch.
Double-encoding. %2520 decodes to %20, which decodes again to a space. Decoding in
a loop until the string stops changing is a security hazard, not a fix β filters that decode
once and validate can be bypassed by input that decodes twice.
`javascript
// Handles + and does not throw on malformed input
new URLSearchParams('a=hello+world%26more').get('a'); // 'hello world&more'
`
Encoding Is Not Encryption
Base64 and percent-encoding both make data safe to *transport*. Neither makes it secret β
both are trivially reversible by design, with no key involved. A Base64 string in a URL, a
cookie or a header is readable by anyone who sees it.
| Purpose | Use |
|---|---|
| Safe transport of binary over text | Base64 |
| Safe transport of text in a URL | Percent-encoding |
| Confidentiality | AES-GCM, TLS |
| Integrity | HMAC, a digital signature |
| Password storage | bcrypt, scrypt, Argon2 |
Size Costs
Base64 expands data by exactly 4/3 β three bytes become four characters β plus padding. A
100 KB image becomes about 133 KB as a data URI, and it cannot be cached separately from the
document that carries it. Inline small icons; link everything else.
Percent-encoding expands unpredictably: an ASCII character that needs escaping becomes three
characters, and a non-ASCII character becomes three per UTF-8 byte. Γ© is %C3%A9 β six
characters for one letter.
UTF-8 Is the Only Sane Default
Every encoding decision on the modern web assumes UTF-8. Where it goes wrong:
btoathrows on non-Latin-1 input.Encode to UTF-8 bytes first:
btoa(String.fromCharCode(...new TextEncoder().encode(text))).
atobreturns Latin-1.Decode back withnew TextDecoder().decode(bytes).- A BOM breaks parsers. Excel writes one at the start of CSV exports; strip it before
parsing.
Length is ambiguous."π¨βπ©βπ§".lengthis 8 in JavaScript, 1 to a reader. Use
Intl.Segmenter` when the count is shown to a person.