URL decode

Paste a percent-encoded string and read it back. Most of the time what arrives here is a URL out of a log file or an analytics export, where the part you actually want is somewhere under a run of `%3A%2F%2F`. Multi-byte characters are reassembled properly, so accents and emoji come back as themselves rather than as a row of question marks.

Query strings from HTML forms write spaces as +. In a path, a plus is a plus.

Result

The answer appears here as you type.

  • Where it runs

    Nothing is uploaded, because there is no file — it is worked out in this page.

  • No queue, no account

    It answers as fast as your machine can, and it never asks who you are.

  • As often as you like

    Nothing is counted and nothing is capped — answering again costs us nothing.

How it works

  1. Paste the encoded text into the box.
  2. Decide what a plus sign means. In a query string from a form it is a space; in a path it is a plus.
  3. Read the result. Nothing was uploaded to produce it.

A percent sequence is a byte, not a letter

Decoding is not a lookup table from `%41` to `A`. Each sequence names one byte, and the bytes together form UTF-8 characters — so `%C3%BC` is a single `ü` built from two sequences, and an emoji is built from four. A decoder that translates sequence by sequence produces two mojibake characters where one should be.

This is also why an incomplete sequence cannot simply be skipped. `%E0%A4` is the first two bytes of a three-byte character; there is no correct output, only a guess. This page reports it as malformed rather than guessing, which is the difference between knowing your input was truncated and quietly believing a wrong answer.

The plus sign is a genuine ambiguity

There is no rule that resolves it from the string alone. `application/x-www-form-urlencoded` — what an HTML form posts, and what most query strings are in practice — writes a space as `+`. Percent-encoding itself has no such rule, so in a path `+` is simply a plus character.

So the same eight characters decode two ways depending on where they came from, and only you know which. The setting is offered rather than assumed for that reason. If you are decoding a query string, spaces is nearly always right; if you are decoding a path or a value that might legitimately contain a plus — a phone number, a search for `C++` — it is not.

Spotting a string that was encoded twice

If the result still has percent sequences in it, it was encoded twice and you have peeled off one layer. The signature is `%2520`: that is `%20` whose `%` was itself encoded as `%25`. Decoding once gives you `%20`, decoding again gives you the space.

It is worth noticing rather than just decoding twice, because double encoding is a bug somewhere upstream — usually a framework that encodes a value and a template that encodes it again. The user-visible symptom is a `Hello%20world` in a page title, and by then it is several systems away from where it started.

Reading a URL out of a log file

This is the most common reason to be here. An access log or an analytics export stores the full request line, and any URL that was itself a parameter — a redirect target, a callback, a referrer — arrives encoded once for its own sake and again for the one it is inside.

Decode the outer layer and the inner URL becomes readable; decode it once more and its own parameters do. Do not decode a third time out of habit: at that point you are decoding sequences that were literal text in the original, and you will turn a `%` that belonged to somebody's search term into something else.

Why this one is also worth doing locally

URLs from a log carry session identifiers, tokens in query parameters where they should not be, search terms and, often enough, an email address. That is the same category of thing as the tokens on the Base64 page and it deserves the same treatment.

Nothing here is uploaded. The decoding is a few lines of arithmetic in the page you are reading, and the network panel is the way to confirm it rather than a sentence on a marketing page.

URL decode: common questions

Why does my result still contain percent signs?

Because the string was encoded twice. Look for %25, which is an encoded percent sign — decode once more and you will get the real text. It is worth tracing where the second encoding came from, because it is usually a framework and a template both escaping the same value.

Should + become a space?

In a query string, almost always yes — that is what HTML form encoding specifies and what most query strings are. In a path, or in a value that could genuinely contain a plus such as a phone number or a search for C++, no. Nothing in the string itself tells you which, so it is a setting rather than a guess.

It says the sequence is malformed. What does that mean?

That the bytes those percent sequences spell do not form valid UTF-8 characters — usually because the string was truncated part-way through a multi-byte character, or because it was encoded as Latin-1 by something old. There is no correct output in that case, so it reports the problem rather than inventing one.

Does it handle non-Latin text?

Yes. Sequences are reassembled into UTF-8 before being turned into characters, so Cyrillic, Devanagari, CJK and emoji all come back intact. A decoder that works one sequence at a time produces mojibake for all of them, which is the most common way this goes wrong.

Is what I paste kept or logged?

Neither. It never leaves your browser, so there is nothing here to keep. That is worth having for this tool in particular: URLs pulled out of logs routinely carry session identifiers, tokens and search terms that were never meant to be handed to a third party.

Other tools