JSON URL Decode
Pull the JSON back out of a query string and make it readable
Encoded Input
Decoded JSON
Reading the payload out of a link
Someone sends you a URL that misbehaves, or you find one in a log, and the interesting part is a parameter holding a few hundred characters of %7B%22 and friends. You need to know what is actually in there. Paste it above and you get the JSON back, indented, with the structure visible.
Two things make this harder than it looks, and both fail quietly rather than loudly. The first is the plus sign. decodeURIComponent reads + as a literal plus, but a browser submitting a form writes a space as +. Both readings decode without error and only one is right, so the answer depends on how the URL was built — which is why there is a switch for it here and a note under the output saying which reading was applied.
The second is double encoding. When a value passes through two encoders, %20 becomes %2520, and one decode leaves you holding the literal text %20 instead of a space. That produces JSON that will not parse for reasons that look nothing like the cause. Any %25 in the input gets flagged here, because it is nearly always a bug somewhere upstream rather than something you meant.
Numbers survive the round trip. A parsed 19-digit ICCID would normally lose its last few digits to the precision limit RFC 8259 warns about, so the pretty-printer here reads the original source text rather than the parsed value, and 8901240544102066246 comes back with all nineteen digits.
How to use it
- Paste the parameter value – Just the value, not the whole URL — everything after the
=and before the next&. If you paste a whole URL you will get the query string back as text rather than JSON, which the page will tell you rather than pretend otherwise. - Read the note under the output – It says what was noticed: how a plus sign was read, whether anything was multi-byte, whether there was nothing to decode at all. Those are observations, not problems — the coloured bars are reserved for things that are genuinely wrong.
- Flip the plus-sign switch if a value looks off – If a decoded string reads
SIM+swapwhere you expectedSIM swap, the URL came from a form and wants the other reading. Nothing errors in either direction, which is exactly why you have to look. - Check for the double-encoding warning – An amber bar naming a
%25sequence means the value went through two encoders. Decode it a second time to get the real payload, then go and find the place that escaped it twice. - Take the JSON on to another tool – Once it is readable, JSON to Table is often the fastest way to see a list of records, and JSON Validator will tell you precisely where a truncated payload gave out.
If the decoded JSON stops mid-string, do not assume the encoding is broken — check the length of what you pasted. A payload cut at a suspiciously round number is a proxy or a server request-line limit truncating the URL, and no amount of decoding will bring the rest of it back. The fix is at the other end, in how much you are trying to put in the link.
The plus sign, and why nothing warns you
This is the failure worth showing because it does not look like a failure. Here is one encoded payload read both ways. Both decode cleanly, both give valid JSON, and one of them has quietly changed a phone number into something that will never match a record:
%7B%22note%22%3A%22SIM+swap%22%2C %22msisdn%22%3A%22%2B447700900112%22%7D # the space became a bare + # the real plus became %2B
# + read as a plus {"note":"SIM+swap", "msisdn":"+447700900112"} # + read as a space — correct {"note":"SIM swap", "msisdn":"+447700900112"} # both are valid JSON. neither # errors. the msisdn is safe # because it was written %2B — # that is the habit to copy.
When this comes up
Debugging a link that came in on a ticket
A support ticket carries a URL that reproduces a bug and the payload is unreadable. Getting the JSON out is usually the whole investigation — very often the filter contains something nobody expected, like an empty array where the code assumes at least one element.
Reading a callback or redirect parameter
OAuth state and redirect_uri parameters nest inside one another, so a value can arrive encoded twice through no fault of your own. The double-encoding flag here is the quickest way to tell whether you are looking at one layer or two before you start reasoning about the flow.
Turning a log line back into data
Access logs record the full request line, so a JSON filter is sitting there percent-encoded in your log aggregator. Pull it out and you can replay exactly what a user asked for, which beats trying to reconstruct it from the timestamps around it.
Checking what a client library actually sent
You expect a request to carry one shape and the server sees another. Decoding what went over the wire settles it in seconds, and it fairly often reveals an encoding style mismatch rather than a bug in the payload — a library using form encoding where the server expects the component style.
What this page does
- Decodes and pretty-prints in one step, so the payload is readable rather than merely decoded.
- Names the character position when an escape is broken, instead of the single unhelpful message the browser built-in throws for four different faults.
- Flags double encoding by pointing at the actual
%25sequence it found. - Lets you choose how a plus sign is read, and says which reading it used.
- Keeps long integers exact — a 19-digit identifier is not rounded on the way through.
- Shows the decoded byte length and the key count, which is often enough to tell whether a payload is complete.
- Runs entirely in your browser. Nothing you paste is sent anywhere.
Questions people actually ask
Why did my decoded JSON come out with +++ instead of spaces?
Because the URL was built by something that follows application/x-www-form-urlencoded, where a space is written as +, and it was decoded with the component reading, where + means a plus sign. Switch the reading at the top of the output pane. The reverse mistake is worse: reading a genuine plus as a space silently damages phone numbers and Base64 payloads.
What does the double-encoding warning mean?
It means the input contains %25 followed by two hex digits — the escape for a percent sign, immediately followed by what looks like another escape. That is the signature of a value that went through two encoders. Decode the output once more to get the real payload. This is a well-documented source of both bugs and security problems, which is why it gets a coloured bar rather than a footnote.
It says "URI malformed" in my own code but this page shows a position. Why?
decodeURIComponent throws one generic URIError for four separate faults — a truncated escape, non-hex digits, invalid UTF-8, and an encoded surrogate — and tells you nothing about where. This page decodes byte by byte and keeps track of where each byte came from, so it can point at the character. On a 3KB query string that difference is the whole job.
The decoded text is not JSON. What now?
The text is still shown, which is deliberate — seeing where it stops is usually what identifies the problem. A payload that ends mid-string means the URL was truncated. A payload full of %20 as literal text means it needs decoding again. Something that was never JSON at all means the parameter you grabbed was not the one you wanted.
Can I paste a whole URL rather than one parameter?
You can, and you will get the query string back as readable text rather than parsed JSON, because a whole URL is not a JSON document. That is a perfectly useful thing to do when you want to see the structure of a link — but to get the payload as JSON, take the one parameter value.
Does pretty-printing change anything?
It adds whitespace and nothing else. Keys keep their order, values keep their types, and numbers too long for a JavaScript double keep every digit — the printer works from the original source text rather than a parsed number. Turn it off if you want the exact bytes that were in the URL.
Related tools
References
- MDN — decodeURIComponent() – Including the single error it throws for every fault
- WHATWG URL — form-urlencoded parsing – Where the plus-sign rule is actually written down
- RFC 3986 §2.4 — When to Encode or Decode – On decoding exactly once, and why twice corrupts