URL Encode / Decode
Convert text with URL encode/decode in real time. Useful for checking query parameters and handling non-ASCII URLs.
Other Tools
Related articles
📖 Where people get stuck
Encodes and decodes text for URLs as you type, following encodeURIComponent, entirely in the browser. There is not one single thing called URL encoding — which characters need escaping depends on where in the URL the value goes. A path segment, a query value and a form submission follow different rules, and confusing them accounts for most of the bugs in this area.
| Case | What happens | What to do |
|---|---|---|
| Confusing encodeURI with encodeURIComponent | encodeURI exists to encode a whole URL, so it deliberately leaves the delimiters alone: /, ?, &, =, # and :. Use it on a URL you are passing as a query value and the & and = inside that value are read as delimiters and the parameters split apart — ?redirect=https://a.com/?x=1&y=2 arrives as two parameters, redirect and y. The symptom is a value truncated partway through, which testing with short values will never reveal. |
Always use encodeURIComponent for the parts of a URL — a query value, a single path segment, the contents of a fragment are all parts. encodeURI is appropriate only when passing an already-assembled URL through once, which comes up rarely in practice. More reliable still is not concatenating strings at all: use URLSearchParams or new URL() — write const u = new URL(base); u.searchParams.set("redirect", target); and the escaping decision disappears entirely. Treat any place where a URL is being assembled by string concatenation as a bug waiting to be found. |
| A plus sign turns into a space | There are two ways to represent a space. Percent-encoding for URIs uses %20, while the HTML form encoding application/x-www-form-urlencoded uses +. encodeURIComponent follows the former and produces %20, but if the receiving side parses it as form data, a genuine + inside the value is converted into a space. The damage is worst with email aliases: pass user+tag@example.com through a query string and it becomes user tag@example.com and never arrives. The standard Base64 alphabet also contains +, so tokens in URLs hit the same problem. |
Use URLSearchParams to build query strings. It escapes a + inside a value correctly as %2B and writes spaces as +, so the result stays consistent even when the receiver parses it as form data. If you must assemble it by hand, replace + with %2B explicitly wherever the value might contain one. For Base64 in a URL, use the URL-safe alphabet (- and _) from the start — more reliable than percent-encoding the standard one. Because this only breaks when a value happens to contain a +, make sure your test data includes one. |
| Double encoding leaves a trail of %25 | Encode an already-encoded string a second time and the % itself becomes %25 — %20 turns into %2520, and Japanese %E3%81%82 into %25E3%2581%2582. A receiver that decodes only once is left with the extra layer, and the literal text %20 appears on screen. The cause is that nobody decided which layer does the encoding, and the classic combination is a framework encoding automatically while the application encodes by hand as well. Removing either one fixes it, but which one to remove cannot be decided without following the code. |
Decide on one place to encode and write it down — stating that this function takes an already-encoded value, or that only this layer encodes, makes double encoding structurally impossible. And decode exactly once: a loop that says there are still % characters so decode again is a serious vulnerability. An attacker sends %252e%252e%252f; the first decode gives %2e%2e%2f and the second gives ../, so it slips past your path traversal check, which ran against the result of the first decode. Avoid the very instinct of decoding once more just to be safe. |
Domain names use Punycode, not URL encoding. An internationalised domain is converted to a form such as xn--r8jz45g.xn--zckzah before it goes to DNS — the browser shows it in the original script in the address bar, but that is a display courtesy; what is actually queried is the xn-- string. Because phishing using visually similar characters — homograph attacks — exists, browsers show the Punycode form outright under certain conditions, and treating a familiar domain that suddenly appears as xn-- with suspicion is a useful habit. One more thing: the fragment of a URL, everything after the #, is never sent to the server — it appears in neither access logs nor referrers, which makes it safer than a query string. It still lands in browser history, though, so the principle of keeping secrets out of URLs is unchanged.
📖 How to Use
-
1
Enter the text to encodePaste text containing Japanese, spaces, or special characters into the top textarea. It is encoded using encodeURIComponent in real time.
-
2
Enter encoded text to decodePaste a URL-encoded string like %E3%81%93%E3%82%93 into the lower textarea to decode it back to the original text in real time.
-
3
Copy the result and use itClick the Copy button at the top-right of each field to copy the result. Use it for query parameters, form data, or API requests.
❓ Frequently Asked Questions
What is the difference between encodeURIComponent and encodeURI?
What happens to Japanese characters in URLs?
Does the + symbol represent a space?
🐛 Found a bug or issue with this tool?
Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.
Thanks for your report!
Your report has been delivered to the operator and will be used to improve the tool.