Skip to content
FormatKit

Free online URL decoder

URL decode, one parameter at a time

Paste a link and the readable version appears at once — free, with no account, and with no limit on how many you run. Every %XX escape becomes the character it stands for, a plus is read as a space where that is what it means, and a value that was encoded twice is unwrapped round by round instead of coming back half-decoded. Below the output, any query string is broken into a table: one row per parameter, the value as it was sent beside the value decoded, so you can see which one is malformed rather than squinting at a 300 character link.

  • 100% free
  • No signup
  • Up to 1 MB
  • Per-parameter table
  • Double encoding unwrapped
Right for a query string and a form body; wrong for a path segment.
Decoded

The plain text appears here as you paste.

Nothing to decode yet. Paste a link, or press Ctrl+V anywhere on this page.

How to decode a URL

Paste it, tell the page what a plus means, read the table.

  1. Paste the link or the value

    Drop a whole URL, a bare query string, or a single escaped value into the left box — a keyboard paste lands here from wherever the cursor sits: ⌘V, or Ctrl+V on Windows and Linux. Nothing needs trimming first: a link copied out of a log line, an email tracking redirect or a browser address bar all go in as they are.

  2. Decide what a + means here

    The toggle above the box is on, which reads every + as a space. That is correct for a query string and for a form body, and wrong for a path segment or a Base64 payload, where a plus is a plus. Flip it off and the output updates without re-pasting anything.

  3. Read the value, or read the table

    The right pane holds the decoded text and the Copy button takes it. Underneath, if the input had a query, every parameter appears on its own row with the value as it was sent beside the value decoded, plus a note for the ones that need one — a repeated name, PHP bracket notation, a value that is still encoded after the first pass.

Technical specifications

Accepted inputA full URL, a bare query string, a fragment or a single escaped value; up to 1,048,576 characters, decoded in about 20 ms
Escapes%XX in either case (%C3%A9 and %c3%a9 are the same); a % that is not followed by two hex digits stops the decode and is reported with its 1-based position
Plus signSwitchable. On by default, matching application/x-www-form-urlencoded; off leaves + as a literal plus for path segments and Base64
Double encodingUp to 6 rounds, continuing while the result still holds a %XX escape, with every round listed and its escape count shown
Character setBytes are read as UTF-8, so %F0%9F%93%9A is one book emoji; a byte run that is not valid UTF-8 falls back to Windows-1252 and says so instead of printing replacement characters
Query breakdownSplit on & and on the first = of each pair before any decoding, with repeated names, PHP [] notation, empty values and still-encoded values flagged per row
Not attemptedSplitting the URL into scheme, host and path, and rewriting punycode hostnames — a decoder that guesses at structure gets it wrong on relative URLs
Price and processingFree, unlimited, no account; every decode runs in this tab, so the link you paste is never sent anywhere

Frequently asked questions

Why is the space in my URL a + and not %20?

Because whatever produced it used form encoding, where a space is written as a plus sign. That convention comes from HTML 2.0 form submission in 1995 and survives today as application/x-www-form-urlencoded, the media type a browser posts a plain <form> with and the format URLSearchParams writes. It applies to the query string and to a form body — nowhere else. A plus inside a path segment is a literal plus, which is why this page makes the behaviour a switch instead of a rule: decoding /files/c++/readme with the switch on gives you /files/c /readme and a puzzle.

What does %2520 mean, and why does one decode leave a %20 behind?

It is a space that was encoded twice: the space became %20, then the % of that escape became %25, giving %2520. One round of decoding can only undo one round of encoding, so it hands back %20 and stops — correctly, because a decoder cannot know whether that %20 is data or another layer. This page decodes again while the result still contains an escape, up to six rounds, and lists each round so you can see how many encoders the value passed through. Two rounds almost always means a URL was put inside a redirect parameter of another URL by code that called the encoder without checking whether one had already run.

The decoder stopped at a position and named a character. What broke?

A % that is not followed by two hexadecimal digits, which makes the escape meaningless. The usual cause is a literal percent sign that was never encoded — “50% off” written straight into a query value produces %20 out of “% o”, or fails outright — and the fix is to write it as %25 at the source. A truncated string does it too, when the copy stopped between the % and its digits. Position numbers here count characters from the start of what you pasted, so you can find the spot without counting by hand.

Why did %E9 come back with a Windows-1252 note instead of é?

Because a single byte E9 is é in Latin-1 but is not valid UTF-8 at all — in UTF-8 that letter is two bytes, %C3%A9. Something upstream encoded the text in a legacy character set: an old .NET handler, a form whose page declared iso-8859-1, or a desktop application that never left the 1990s. The bytes are shown through Windows-1252 rather than as replacement characters, so the text stays readable, but the fix belongs at the encoder: serve the page as UTF-8 and the same letter arrives as %C3%A9.

Does this decode a whole URL, or only one parameter?

Both, and it does them at the same time. The right pane decodes everything you pasted as one string, which is what you want for a value; the table below splits the query first and decodes each parameter separately, which is what you want for a link. Splitting a URL into scheme, host, port, path and fragment is a different operation and lives on the URL parser page.

Is it safe to decode a query string before splitting it on &?

No, and it is the most common way to corrupt a URL. A value may legitimately contain %26, an ampersand that is data rather than a separator; decode first and that value splits into two parameters, quietly. The same applies to %3D, an equals sign inside a value. Every parser worth using splits on the raw & and =, then decodes each half, and that is the order this page follows — which is why the table shows the raw value beside the decoded one.

My string has plus signs and is not a URL. Will decoding damage it?

It will, if the plus toggle is on and the string is Base64. Base64 uses + as one of its 64 data characters, so turning it into a space destroys the payload — the page notices a Base64-shaped input and says so rather than letting you find out later. A signature, a hash in a header and an encrypted token have the same problem. Switch the toggle off for anything that is not a query string.

About percent-decoding

A URL is allowed a small alphabet and no more. RFC 3986 divides the printable ASCII characters into three groups: unreserved ones that always mean themselves — the letters, the digits, and - . _ ~ — reserved ones that carry structure, such as the slash between path segments and the ampersand between query pairs, and everything else, which has no place in a URL at all. Anything from the last two groups that is data rather than syntax has to be written as a percent sign followed by two hex digits standing for one byte. Decoding is the reverse of that substitution and nothing more: it recovers bytes, and those bytes are read as UTF-8 because RFC 3986 §2.5 says new URI schemes should use it and every browser now does.

The plus sign is the exception that catches everyone, and it is a historical accident rather than a rule. Percent-encoding never had an opinion about spaces; form submission did. HTML 2.0 defined how a browser packs form fields into a request, chose + for the space because it is shorter than %20, and that format — application/x-www-form-urlencoded — is still what a plain form posts and what URLSearchParams serialises to. So a plus means a space inside a query string and inside a form body, and means a plus everywhere else. A decoder that applies the rule everywhere corrupts path segments and Base64; one that applies it nowhere leaves you reading hello+world. It has to be a choice, and the encoder on the other side makes the same one explicitly.

Order matters more than most tools admit. A query string has to be cut into pairs on the raw ampersands, and each pair cut at its first equals sign, before anything is decoded — otherwise a value containing %26 turns into two parameters and a value containing %3D loses half of itself, silently, with no error to notice. That is the whole reason this page shows a table instead of a single decoded blob: the blob is what you read, the table is what the server will actually see. When the question is where the host ends and the path begins rather than what a value says, the URL parser takes the same link apart structurally.

Where the link you paste goes

Nowhere. The decoding is a loop over the characters of your string, running in this tab on your own machine, and the page makes no request while it works — which matters here because the things people decode are session tokens, password-reset links and signed callback URLs. No history of what you pasted is kept, and reloading the page clears it.