Skip to main content
QUIETLYTIC
Encoding & Data

URL Decoder

Decode percent-encoded text, including repeatedly-encoded strings.

Local · nothing leaves this browser Waiting for input
Esc Clear
Decoded — not fetched

Paste encoded text on the left.

How it works

Reading a percent-encoded string by eye is a reliable way to miss what it says. Decoding it here costs nothing — nothing is fetched, nothing is requested, and no reputation service is told what you are looking at — so a hostile URL can be read safely before any decision is made about it.

Repeated decoding is a choice, not a default

A redirector often hides its real destination behind two or three layers of encoding, and decoding once leaves you looking at %2F%2Fevil.test wondering whether that is the answer. But repeated decoding also changes meaning: a legitimate value containing a literal %2520 is a string that merely looks encoded, and decoding it twice silently alters the data.

So it is a checkbox. When on, decoding repeats until the string stops changing, capped at eight passes so a crafted input cannot loop, and the status strip reports how many passes ran.

A plus sign is only sometimes a space

In form data (application/x-www-form-urlencoded, what an HTML form submits) + means a space. Everywhere else — a path, a fragment, most APIs — it is a literal plus. So that is a checkbox too, and it applies to the first pass only: a + that came out of decoding %2B was escaped on purpose.

Malformed input

A % not followed by two hex digits is not valid percent-encoding, and escapes that spell bytes which are not valid UTF-8 (%E9 on its own, the Latin-1 é) cannot be decoded to text either. Each is reported by name rather than guessed at, because guessing invents content.

Repeated decoding is different. If a later pass hits one of those, the % came out of an escape the sender wrote on purpose — 100%25%20off is 100% off, not an error — so decoding stops at the last pass that worked and the status strip says it stopped at a literal %.

Example

a%2526b decodes once to a%26b and twice to a&b. If the decoded result is a live URL, run it through the IOC Defanger before it goes into a ticket or a chat window, or take it apart with the URL Parser.

Frequently asked questions

Why is repeated decoding optional rather than automatic?

Because it changes meaning. A legitimate value containing a literal %2520 is a string that happens to look encoded, and decoding it twice silently alters the data. Redirector chains often do hide their destination behind double encoding, so the option is there — as a decision you make, capped at eight passes so a crafted input cannot loop.

What does it do with a malformed escape?

Reports it. (With repeated decoding on, a later pass that hits one keeps the last good result instead: that % came out of an escape, so it is a literal.) A % not followed by two hex digits is not valid percent-encoding, and escapes that spell bytes which are not valid UTF-8 — %E9, a Latin-1 é, on its own — are reported as that. Guessing at what was meant would invent content.

Does + become a space?

Only if you tick the form-data option. In a form submission + means a space; in a path or most other places it is a literal plus, and turning it into a space would change the value.

Should I decode a suspicious URL here before opening it?

Decode it here, yes — nothing is fetched and nothing is requested, so reading a hostile URL costs nothing. Opening it is a separate decision. Run the result through the IOC Defanger before pasting it into a ticket or a chat window.

Related tools

From the intelligence desk