URL Decoder
Turn percent-encoded URLs and parameters back into readable text, with the plus-sign rule handled correctly.
Encoded URL or value
Decoded text
Percent-encoded URLs are unreadable by design, and you meet them at exactly the moments when you most need to read them: an analytics report full of %3F and %26, a redirect chain in a browser network tab, an OAuth error whose state parameter contains another encoded URL, a log line where a search query has become a wall of hex. Decoding turns that back into text you can reason about.
The decoding itself is straightforward — each %XX becomes the byte it names, and the bytes are read as UTF-8 so accents and emoji come back correctly. The judgement call is the plus sign. In a form-encoded query string + means a space; in a URL path it is a literal plus. This decoder converts + to a space only when the input looks form-encoded — when it contains a ?name= style parameter, or when it has no slash at all and so is clearly a bare value. A path-shaped input keeps its plus signs, and the output tells you which interpretation was applied.
How to use the url decoder
- 1
Paste the encoded URL or value
A whole URL, a single parameter value, or a bare encoded fragment all work. Surrounding whitespace is trimmed; nothing else is altered before decoding.
- 2
Read the decoded output and the notes
Below the result you may see two notes. One tells you that
+was treated as a space because the input looked form-encoded. The other warns that the result still contains percent-encoding, which means the value was encoded more than once. - 3
Decode again if a layer remains
Double-encoded values need one pass per layer. Feed the output back into the input pane and decode again until no
%XXsequences remain and the note disappears.
The plus sign is genuinely ambiguous
This trips up almost every naive decoder, in both directions. RFC 3986 treats + as an ordinary reserved character with no special meaning. The separate application/x-www-form-urlencoded specification — the format HTML forms submit and the one most query strings follow — says a space is encoded as +. Both are correct in their own context, and a URL can contain both contexts at once.
So /files/c++/notes.txt contains two literal plus signs that are part of a directory name. Blindly converting them to spaces produces a path that does not exist. Meanwhile ?q=hello+world almost certainly means the two words with a space between them, because that is what a browser submitted.
The rule applied here: if the input contains a ?key= or &key= pattern, or contains no slash at all, it is treated as form-encoded and + becomes a space. Otherwise plus signs are left alone. When the substitution happens, it is reported in the notes so you are never guessing about what the tool did.
If you disagree with the call for a particular string, the workaround is direct: to force literal plus signs, replace them with %2B before decoding. To force spaces, replace them with %20. Both are unambiguous in every context, which is why a well-behaved encoder emits them.
Malformed and double-encoded input
A % must be followed by exactly two hexadecimal digits. When it is not, decoding fails and the error reports the position of the offending percent sign, counted from the start of the trimmed input, so you can find it in a long string without scanning by eye. The usual cause is a literal percent character that was never encoded — a value like 50% off pasted straight into a URL, where the % should have been written %25.
The other frequent failure is a truncated escape at the end of a string, where a log or a database column cut the value off mid-sequence. Nothing can recover the missing digits; you need the untruncated source.
Double encoding is more insidious because it does not fail — it just gives you the wrong answer, quietly. When a value is encoded twice, %20 becomes %2520, and one decode pass returns %20 rather than a space. If the output still contains %XX sequences you are told so explicitly, because that leftover encoding is a signal about the pipeline: some component encoded a value that was already encoded. Common sources are a proxy that re-encodes, a client library that encodes a URL its caller had already encoded, and a redirect URL stored encoded and then encoded again when placed in a parameter.
Decoding repeatedly until nothing changes is fine for inspection, but do not build it into an application. Servers that decode more than once are vulnerable to path-traversal filters being bypassed: %252e%252e%252f passes a check looking for ../ and then becomes it after a second pass. Decode exactly once at each boundary.
Reading URLs after decoding
Once decoded, a long URL is readable but still dense. A few things to look for:
- Nested URLs. Parameters named
redirect,redirect_uri,return_to,next,continueorstateusually contain a whole second URL, which will have its own encoded parameters inside. Decode the outer URL first, then paste the inner one back in and decode again. - Tracking parameters.
utm_source,utm_medium,utm_campaign,gclid,fbclidare analytics noise and can normally be ignored when debugging. - Base64 inside parameters. A long run of letters and digits ending in
%3Dis Base64 whose padding was percent-encoded. Decode the URL, then send that value to the Base64 decoder. - Mojibake. If accented characters decode to pairs like
éinstead ofé, the value was encoded as UTF-8 and then interpreted as Latin-1 somewhere upstream. The URL decoder is behaving correctly; the producer was not.
Decoding happens entirely in your browser, which matters here more than for most tools — URLs routinely carry session tokens, signed parameters and personal data in their query strings. Nothing you paste is transmitted.
URL Decoder FAQ
Why were my plus signs turned into spaces?
Because the input looked form-encoded — it contained a ?key= or &key= pattern, or had no slash at all. In that context + means a space, which is how HTML forms submit them. A path-shaped input keeps its plus signs literal, and a note tells you which interpretation was used.
The output still has %20 and %3D in it. Why?
The value was encoded twice, so one pass only removed the outer layer. Paste the output back in and decode again. The warning note appears whenever percent sequences survive a decode, because that almost always indicates a pipeline encoding something that was already encoded.
I get a malformed percent-encoding error.
A % must be followed by two hex digits. The error gives the position of the bad one. Usually it is a literal percent sign that should have been written %25, or an escape truncated at the end of the string by a log or a database column.
Why do accented characters look wrong after decoding?
If é comes out as é, the bytes were UTF-8 but something upstream interpreted them as Latin-1 before you got the string. Decoding is doing the right thing with the bytes it was given; the problem is on the producing side.
Can I decode a whole URL including the domain?
Yes. Paste the entire URL and every percent sequence in it is decoded, including those in the path, query and fragment. Only the characters that were actually encoded change; the rest of the URL is untouched.
