Free · Validate & tree-view · Nothing uploaded

JSON formatter & validator

Beautify, validate and explore JSON with a collapsible tree view. Get the exact error line for broken JSON, then copy or download. Everything runs in your browser.


              
            

🔒 Your JSON is formatted and validated entirely on your device — never uploaded.

How to format and validate JSON

Beautify messy JSON, catch errors with the exact line, and explore it as a collapsible tree — all locally.

📥

1. Paste JSON

Drop in raw or minified JSON from an API, config or log.

2. Format or validate

Beautify with clean indentation, or get a precise error location if it's invalid.

🌳

3. Explore & copy

Browse the collapsible tree, then copy formatted or minified output.

Developers use a JSON formatter to debug API responses, clean up config files, and make minified data readable. This tool validates against the JSON spec and points to the exact line and column of any syntax error, so you fix problems fast. It runs entirely in your browser, so payloads with tokens or customer data never get uploaded. Convert tabular data with JSON ↔ CSV or format queries with the SQL Formatter.

What validates your JSON

Parsing is done by the browser's own JSON.parse, so "valid" here means valid to the same implementation that will consume the data in any JavaScript runtime — not to a hand-written parser that might be more forgiving. Formatting is JSON.stringify with your chosen indent. Everything re-runs about a fifth of a second after you stop typing.

Two things are then checked that the parser alone will not tell you. The first is the node count, which walks the parsed structure using an explicit stack rather than recursion — a deliberate choice, because a recursive walk exhausts the JavaScript call stack somewhere around ten to fifteen thousand levels of nesting, while JSON.parse itself comfortably handles far deeper documents. Using a loop means the counter never fails on input the parser accepted.

The second is duplicate keys, and it is the feature most formatters lack. {"id": 1, "id": 2} is valid JSON, and the parser silently keeps only the last occurrence — the first value vanishes with no error anywhere. To surface that, the tool re-walks your raw text with a small scanner looking only at object keys, and warns you which names repeat and that the last one wins. If you have ever debugged a config where a setting was mysteriously ignored, this is often why.

The JSONPath subset in the query box

The query field implements a practical subset of JSONPath, evaluated against the parsed document. When a path is active, both the code and tree panes show the extracted result rather than the whole document, and the hint beside the box reports how many nodes matched.

SyntaxMeaningExample
$The root document$
.nameChild by key$.user.email
['name']Child by key, for names with dots or spaces$['content-type']
[n]Array element by index; negative counts from the end$.items[0], $.items[-1]
[*] or .*Every element or every value at this level$.users[*].name
..Recursive descent — search at any depth below here$..id

What is not supported: filter expressions such as [?(@.price<10)], array slices such as [1:3], and unions such as [0,2]. A path using those reports a parse error rather than silently returning the wrong nodes. For anything more elaborate, extract the subtree you need here and process it in code.

Where a round-trip changes your data

Large integers lose precision, silently. JSON numbers have no size limit, but JavaScript parses every one into a 64-bit float, which represents integers exactly only up to 9,007,199,254,740,991. Paste 9007199254740993, press Format, and you get 9007199254740992 back — no warning, because as far as the language is concerned nothing went wrong. Since 64-bit database IDs, Twitter-style snowflake IDs and some financial values live above that line, treat this tool as read-only for such documents, or have your API emit those fields as strings.

Numeric-looking keys get reordered. Formatting rebuilds the object, and JavaScript specifies that integer-like keys are enumerated first, in ascending numeric order, before any other keys in insertion order. So {"2":"a","1":"b","x":1} reformats to {"1":"b","2":"a","x":1}. The data is equivalent under the JSON spec, which defines objects as unordered, but if something downstream depends on key order, this is a change you did not ask for.

Strict JSON only. Comments, trailing commas, single-quoted strings, unquoted keys and NaN or Infinity are all rejected — correctly, since none is JSON. If you are editing a .jsonc or JSON5 config, strip the comments before pasting. There is also no schema validation here: the tool tells you the syntax is well-formed, not that the document matches what your API expects.

Your input is saved locally. So you do not lose work on an accidental reload, the contents of the input box are written to this browser's local storage, capped at 200,000 characters. Nothing leaves the device, but it does persist on it — so on a shared or public machine, clear the box when you are done, and be aware that anything past that cap is restored truncated and will no longer parse.

Everything happens on the main thread. Parsing, highlighting and tree building are synchronous, so a very large payload — tens of megabytes — will make the tab unresponsive while it works. Tree view is the heaviest part, since it creates a DOM element for every value. On a big document, use the query box to narrow to a subtree first.

Working faster with it

Use the two views for different jobs. Tree view is for orientation on an unfamiliar payload — every node shows its key or item count, so you can see the shape of an API response without scrolling through it. Code view is for reading and copying actual values. The Format and Minify buttons rewrite the input box itself, so you can paste minified data, expand it, edit it, and minify it again before sending it on.

Sort keys is the underrated option. Two API responses that differ only in key order are impossible to diff usefully; sorting both first makes a comparison meaningful. Feed the results to JSON diff to see exactly what changed between two payloads.

On error messages: the line and column are derived from the browser's own parser error, so the exact wording varies between Chrome and Firefox even though the location does not. When a message points at a spot that looks fine, the real problem is almost always slightly earlier — an unclosed bracket or a missing comma on a previous line, which the parser only notices when it reaches something unexpected.

For turning JSON into other shapes, JSON ↔ CSV handles flat tabular data and JSON to TypeScript generates interfaces from a sample payload — useful for pinning down a response you have just explored here. More are grouped on the developer tools page.

JSON formatter FAQ

Is my JSON uploaded?

No — formatting and validation run entirely in your browser. One thing to know: the input box is auto-saved to this browser's local storage so a reload does not lose your work. That never leaves the device, but it does persist on it, so clear the box after pasting anything sensitive on a shared machine.

Does it show the error location?

Yes — invalid JSON shows the exact line and a clear message. The wording comes from your browser's own parser, so it differs slightly between Chrome and Firefox. If the reported spot looks correct, check the lines above it: a missing comma or an unclosed bracket is only detected when the parser reaches the next unexpected character.

What can it do?

Beautify, minify, validate, and view JSON as a collapsible tree, then copy or download. It also counts nodes, warns about duplicate keys, can sort keys recursively, and lets you extract a subtree with a JSONPath query.

Why did my long ID number change after formatting?

Because JavaScript parses every JSON number into a 64-bit float, which holds integers exactly only up to 9,007,199,254,740,991. Anything larger is rounded to the nearest representable value on the way in, and formatting writes that rounded value back out. Database and snowflake IDs frequently exceed the limit — the durable fix is to have the API send them as strings.

What does the duplicate key warning mean?

That the same key appears more than once inside one object. This is technically valid JSON, and the parser resolves it by keeping the last occurrence and discarding the earlier ones without complaint. Since that silently drops data, the tool scans your raw text separately and names the repeated keys so you can decide which value you actually meant.

Does the query box support full JSONPath?

A practical subset: root, child access by dot or bracket, array indexes including negative ones, wildcards, and recursive descent with two dots. Filter expressions, slices and unions are not implemented and will report a parse error rather than quietly returning the wrong nodes.