What the error position actually means
When JSON.parse fails it reports a character offset, which this page converts to a line and column and prints with the surrounding lines. That position is where the parser could no longer continue, which is often one token past the real mistake. A trailing comma after the last element of an array does not fail on the comma, it fails on the closing bracket that follows it. An unterminated string does not fail at the opening quote, it fails at the end of the file. Read the marked line and the one above it together.
Different browsers word the message differently. Chrome and Node say Unexpected token } in JSON at position 84, Firefox says expected double-quoted property name, Safari says something else again. The offset is the part worth trusting.
JSON is narrower than a JavaScript object literal
Most invalid JSON is valid JavaScript that someone pasted out of source code or a config file. The differences that catch people:
| Written | Valid JSON? | Why |
|---|---|---|
{name: "x"} | No | Keys must be double-quoted strings |
{'name': 'x'} | No | Single quotes are not string delimiters in JSON |
[1, 2, 3,] | No | No trailing commas anywhere |
// comment | No | JSON has no comment syntax |
{"a": undefined} | No | Only null, true, false, numbers, strings, arrays, objects |
{"a": NaN} | No | NaN and Infinity are not JSON numbers |
{"a": 0x1F} | No | Decimal only, no hex or octal literals |
If the file you are debugging is tsconfig.json or VS Code's settings.json, it is JSONC, not JSON: comments and trailing commas are allowed there and this parser will reject them. Same story for JSON5, which additionally allows unquoted keys and single quotes. Strip the comments before pasting, or use a parser that speaks the dialect you actually have.
Sorting keys, and what minifying does not do
Object key order carries no meaning in JSON, so sorting keys produces an equivalent document. That is useful right before a text diff of two files: with both sides sorted, a line-based diff stops reporting reordered keys and shows only the values that moved. Arrays are left in place, because array order does mean something.
Minifying removes whitespace between tokens. It does not shorten keys, obfuscate anything, or change values, and it is not compression. Over the wire, gzip or brotli will save you far more than minifying will, and they compose: minified plus gzipped is smaller than either alone, but the gzip step is doing most of the work.
Numbers do not always survive a round trip
JSON has one numeric type and JavaScript parses it into a double. Anything above 253 loses its low digits: a Twitter-style 19-digit ID like 9007199254740993 comes back as 9007199254740992, silently. Formatting the document re-serialises the parsed value, so the damaged number is what appears in the output. The same erasure happens to trailing zeros, 1.0 becomes 1, and to 1e3, which becomes 1000.
None of that is fixable at this layer. If an API hands you IDs bigger than nine quadrillion, they need to be strings on the wire, and the fix belongs on the server. When you only need to look at the document rather than transform it, a viewer that keeps the raw text will show you the original digits.
Nothing leaves the page
The input is parsed by the browser's own JSON.parse and re-serialised by JSON.stringify in the tab you have open. There is no upload, no request, no logging, and closing the tab is the end of it. That matters here more than on most pages, because the thing people most often need to reformat is an API response with a bearer token or a customer record in it. The only remaining exposure is your own screen, so be careful what is visible if you are sharing it.
Questions people ask
Why did my long ID number change?
JavaScript stores every JSON number as a 64-bit float, which represents integers exactly only up to 9,007,199,254,740,991. Beyond that, the parse rounds to the nearest representable value and the original digits are gone before any formatting happens. It is not a bug in the formatter, it is what any JavaScript parser does, and it bites hardest on database IDs and Snowflake-style identifiers. The only real fix is for the producer to send those values as JSON strings.
My config file has comments and it will not parse.
Standard JSON has no comment syntax, so a file with // or /* */ in it is JSONC or JSON5 rather than JSON, even when the extension says .json. tsconfig.json, VS Code settings and several linter configs are all JSONC. This page uses a strict parser deliberately, because the point is to tell you whether something is valid JSON. Remove the comments and trailing commas to check the rest.
Is there a size limit?
No hard limit, but the practical ceiling is a few megabytes. Everything is held in memory, the whole document is re-serialised, and the browser has to paint the result into a textarea. Past roughly five megabytes you will notice the tab hesitate. For files that size, jq from a terminal is a better tool and it streams.
Does anything I paste get uploaded?
No. The parse and the re-serialise both happen in your browser with no network request involved. There is no account, no storage, and nothing is written anywhere. You can confirm it by opening the network tab before you press Format, or by disconnecting entirely once the page has loaded.