About URL Encoder Decoder
Encode and decode URLs and special characters instantly. Free, no sign-up required.
How to use
- Paste raw text or a URL into the Input textarea. Anything goes — query parameters with embedded spaces, OAuth state values with quotes, JSON payloads with brackets, or URLs with already-encoded segments you want to verify.
- Click Encode to run encodeURIComponent on the input — every character outside the unreserved set ([A-Za-z0-9 - _ . ! ~ * ' ( )]) is percent-encoded. Spaces become %20, slashes become %2F, ampersands become %26, even valid-in-URL characters get encoded.
- Click Decode to reverse: percent-escapes turn back into their original characters. Decoding is forgiving — invalid percent sequences like %ZZ throw a URIError, which the tool surfaces as an error message instead of crashing.
- Click Swap to move the Result back into the Input field — useful for double-encoding (run Encode twice) or for inspecting what a value looks like after a round trip through encode-then-decode.
- Click Copy Result to push the encoded/decoded text to clipboard. The output is plain ASCII, safe to paste into a URL bar, an HTTP request body, or a stringified config value.
- Use Clear to wipe both panels when switching between unrelated values. The conversion runs locally — paste tokens, session IDs, or signed URLs without any of it leaving your browser.
Examples
Query parameter with spaces
Input: hello world & friends. Encoded: hello%20world%20%26%20friends. Decoded back: hello world & friends. The %26 (encoded &) is essential — leaving it raw would split the value across two query parameters when parsed.
Path with reserved characters
Input: /api/users/2026-04-30/orders. encodeURIComponent gives %2Fapi%2Fusers%2F2026-04-30%2Forders (slashes encoded). encodeURI would preserve the slashes — different functions for different contexts. The tool uses encodeURIComponent because that handles parameter values correctly.
UTF-8 multi-byte character
Input: café. Encoded: caf%C3%A9. The é is U+00E9 in Unicode, encoded as the two UTF-8 bytes 0xC3 0xA9, each percent-prefixed. All modern URL encoding is UTF-8-based per RFC 3986. Older percent-encoding (Latin-1) is wire-incompatible — you may see %E9 from legacy systems.
Frequently asked questions
What is the difference between encodeURI and encodeURIComponent?
encodeURI assumes the input is a complete URL and preserves structural characters: : / ? # [ ] @ ! $ & ' ( ) * + , ; = stay literal. encodeURIComponent encodes a component (a single parameter value) and percent-encodes everything except [A-Za-z0-9 - _ . ! ~ * ' ( )]. Rule of thumb: use encodeURIComponent on each individual query value before concatenating into a URL, never encodeURI on a value that contains an &. The tool uses encodeURIComponent.
Why does encodeURIComponent leave some characters alone?
RFC 3986 defines unreserved characters that have no special meaning anywhere in a URL: letters, digits, hyphen, period, underscore, tilde. Plus a small set encodeURIComponent additionally preserves for legacy compatibility (! ~ * ' ( )). All other ASCII (including reserved chars like &, =, ?) gets encoded. To force a more aggressive encoding (including the parens that some XSS filters care about), wrap in a custom function that re-encodes those after the fact.
How does form-urlencoded differ from URL component encoding?
application/x-www-form-urlencoded (used by HTML forms with method=POST and the default Content-Type) is similar to percent-encoding but with one critical difference: spaces become + instead of %20. So 'hello world' is 'hello+world' in form-encoded but 'hello%20world' in URL-component-encoded. JavaScript's URLSearchParams uses form-urlencoded; encodeURIComponent does not. When parsing form data, you must convert + to space first — otherwise the literal + character gets confused with encoded space.
What are reserved characters and when do they need encoding?
Reserved characters have structural meaning in URLs: : separates scheme; / separates path segments; ? begins query string; # begins fragment; & separates query parameters; = separates key from value; @ separates user-info from host; ! $ ' ( ) * + , ; = are 'sub-delims' that have meaning in some contexts. They MUST be encoded when used as data (e.g., a filename containing '?'), but MUST NOT be encoded when used structurally (the '?' that introduces the query). encodeURIComponent encodes them all because it assumes data context.
How are non-ASCII characters like é, 中, or 🎉 encoded?
RFC 3986 mandates UTF-8: convert the character to its UTF-8 byte sequence, then percent-encode each byte. é (U+00E9) is two bytes 0xC3 0xA9 → %C3%A9. 中 (U+4E2D) is three bytes → %E4%B8%AD. 🎉 (U+1F389, requires surrogate pair in UTF-16, four bytes in UTF-8) → %F0%9F%8E%89. encodeURIComponent does this automatically. Older systems may have encoded with Latin-1 or Windows-1252 — those URLs are technically broken on the modern web.
Should I encode a URL twice?
Almost never, and it is a common bug. Double-encoding turns %20 into %2520, which a single decode pass returns as %20 (literal text), not a space. This breaks API endpoints that expected the value to decode to a space. The exception: when an encoded value travels inside another encoded value (a URL passed as a query parameter to another URL), you DO need to encode twice — once to make the inner value URL-safe, once to make it parameter-value-safe. The Swap button helps verify by hand.
What characters does encodeURIComponent NOT encode that I might still want to encode?
encodeURIComponent leaves A-Z a-z 0-9 - _ . ! ~ * ' ( ) literal. The parens and asterisks can be problematic in some contexts: web app firewalls, XSS filters, regex parsing. To encode them additionally, post-process: encodeURIComponent(s).replace(/[!'()*]/g, c => '%' + c.charCodeAt(0).toString(16).toUpperCase()). This produces RFC 3986 strict output. The single quote and parentheses are also encoded by Python's urllib.parse.quote with safe='', another stricter alternative.
Part of ToolFluency’s library of free online tools for Developer Tools. No account needed, no data leaves your device.