URL decode percent-encoded text
Percent-encoded URLs are hard to read: %2F is a slash, %3D an equals sign and %C3%A9 an “é”. The URL decode tool reverses the encoding so you can read redirect links, tracking parameters, OAuth callbacks, log lines and API requests the way they were meant to be read.
How decoding works
- Every
%XXsequence is turned back into the byte with that hex value. - Consecutive bytes are read as UTF-8, so multi-byte sequences like %E2%82%AC become a single character (€).
- If Decode + as space is on, each
+becomes a space first — the convention used by HTML forms and most query strings.
Example
Encoded input:
https%3A%2F%2Fshop.example%2Fsearch%3Fq%3Dcaf%C3%A9+%26+cr%C3%A8me%26page%3D2Decoded output:
https://shop.example/search?q=café & crème&page=2The decoded output is a complete URL again, including its query string. Paste it into the URL Parser to see each parameter on its own line.
Robust handling of broken input
JavaScript’s decodeURIComponent() throws a “URI malformed” error on the first invalid sequence — a lone % in “100%”, or a UTF-8 sequence cut in half. This tool decodes everything it can and leaves invalid sequences as they were, so you still get readable output and can see exactly where the problem is.
Input:
Save 100% on caf%C3%A9 %E0%A4Output:
Save 100% on café %E0%A4
The plus sign question
Whether + means a space depends on where the text came from:
- Query strings and form bodies (
application/x-www-form-urlencoded):+is a space. Leave the option on. - Paths, fragments, Base64 values and data encoded with
encodeURIComponent:+is a literal plus sign, because spaces were written as%20. Turn the option off, or a Base64 token likeab+c/d==will be corrupted.
Decoding multiple layers
Redirect chains often encode a URL inside another URL’s parameter, sometimes several times. If the output still contains %3A or %2F, paste the decoded text into the URL encoded box again. Text containing %25 is a sure sign of double encoding: %2520 decodes to %20, which decodes to a space.
Security tips
- Decode links from unexpected emails or messages before clicking them to see where they really lead; phishing links often hide the destination inside an encoded parameter.
- On the server, decode input exactly once. Decoding twice can let encoded characters such as %252e%252e%252f (../) slip past validation — a classic path traversal trick.
URL decoding in code
Different libraries disagree about the plus sign, which explains many decoding bugs. JavaScript’s decodeURIComponent leaves + alone, while URLSearchParams turns it into a space. Python offers urllib.parse.unquote (keeps +) and unquote_plus (converts it); PHP has rawurldecode and urldecode with the same split. Java’s URLDecoder.decode always performs form decoding, so a literal plus in a path must be sent as %2B. Most web frameworks decode query parameters for you — decoding them a second time in your own code is a frequent source of corrupted values.
To encode text again, use the URL Encoder. If the value inside the URL is JSON, JSON URL Decode decodes and pretty-prints it in one step. Everything runs in your browser; the URLs you paste are not sent anywhere.
URL decode in Python
Use urllib.parse.unquote() for percent-encoded text and unquote_plus() when + should become a space, as in form data and most query strings. Picking the wrong one is the usual bug: unquote() leaves every + in place. For a complete URL, do not decode it and then split it, because a decoded & inside a value looks like a separator. Parse the query with parse_qs() instead; it splits first and returns decoded values.
from urllib.parse import unquote, unquote_plus, urlsplit, parse_qs
encoded = "https%3A%2F%2Fshop.example%2Fsearch%3Fq%3Dcaf%C3%A9+%26+cr%C3%A8me%26page%3D2"
print(unquote(encoded)) # + stays a plus sign
print(unquote_plus(encoded)) # + becomes a space
# a query string: parse first, the values come back decoded
url = "https://shop.example/search?q=caf%C3%A9+%26+cr%C3%A8me&page=2"
print(parse_qs(urlsplit(url).query))
The first two lines match the decoder above with Decode + as space off and on. One difference: Python replaces a broken sequence such as %E0%A4 with �, where this page leaves it as written.