URL Decoder – Decode Percent-Encoded URLs & Query Strings
Paste any percent-encoded string and get the original text back instantly. Handles %-escapes, the +-as-space convention from HTML forms, and full UTF-8 including emojis and non-Latin scripts. Free, private, and runs entirely in your browser.
Input
Percent-encoded → TextResult
Waiting for inputWhat is URL decoding?
URL decoding is the reverse of URL encoding. It takes a percent-encoded string — where unsafe characters have been replaced with a % sign followed by two hex digits — and turns it back into the original plain text. For example, hello%20world decodes to hello world, a%26b%3Dc decodes to a&b=c, and the four-byte UTF-8 sequence %F0%9F%8C%8D decodes to the emoji 🌍.
You run into percent-encoded strings constantly: query parameters in a URL bar, values in an HTTP Location header, fragments passed between single-page app routes, cookies, tracking links, and the payload of an OAuth callback. Whenever you need to see what a URL or query string actually contains, decoding is the first step.
Everything runs locally in your browser. The strings you paste never leave your device, there's no signup, and there are no usage limits.
Component vs Full URL decoding
The two decoding modes mirror the two encoding modes defined by the WHATWG URL standard and the ECMAScript specification. The same percent-encoded string can decode differently depending on which mode you use, because the two functions treat reserved characters differently.
| Mode | Equivalent to | Decodes | Use for |
|---|---|---|---|
| Component | decodeURIComponent() | Every %XX escape, including reserved characters like / ? & = | A single value — a query parameter, a form field, a route fragment. |
| Full URL | decodeURI() | Only escapes that represent unreserved characters | A complete URL that was encoded with encodeURI(). |
In practice, Component mode is what you want almost all the time. It fully reverses encodeURIComponent(), which is how query values and form fields are encoded. Full URL mode is useful when the string is a complete URL that was encoded with encodeURI() — the reserved characters : / ? # [ ] @ ! $ & ' ( ) * + , ; = were left unencoded, so leaving them alone during decoding preserves the URL structure.
The classic example: an encoded value of a%2Fb decodes to a/b in Component mode, but stays as a%2Fb in Full URL mode because / is a reserved character that gives a URL its structure.
The + character and form data
In the query string portion of a URL, the + character is conventionally treated as a space. This comes from the HTML form encoding rules defined in application/x-www-form-urlencoded: a form submission replaces spaces with + before sending them. Servers that parse query strings this way expect the same on the way in.
This decoder has a toggle to treat + as a space. Enable it when you know the input came from a form. Leave it off when the input is a strict RFC 3986 URL where + is a literal character — for example, a Base64 value that uses the standard alphabet, which includes +.
| Input | + as space OFF | + as space ON |
|---|---|---|
hello+world | hello+world | hello world |
a+b%20c | a+b c | a b c |
a%2Bb | a+b | a+b |
Note that an explicit %2B always decodes to a literal +, regardless of the toggle — that's the correct behaviour because it was an unambiguous escape to begin with.
Common decoding errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
| Invalid percent-escape | A % not followed by two hex digits, like %2 or %ZZ | Find the position the tool reports and complete the escape, or remove it if it isn't part of the data. |
| Invalid UTF-8 sequence | The escaped bytes form an incomplete multi-byte character — for example, a truncated emoji or a partial CJK character. | Re-copy the string from the source. Bytes were probably lost in transit or when pasting. |
| Decoded string still has %XX | Doubly-encoded input, or the string uses + where you expected %20. | Decode again, or enable the +-as-space toggle. |