JSON Formatter_

Paste JSON and read it: formatted with your indent choice, syntax-highlighted, and explorable as a collapsible tree with key and item counts. Invalid JSON gets a real diagnosis — line, column, a caret under the exact character, and a plain-language hint for the usual suspects — not "unexpected token".

Everything runs in this tab. API responses full of tokens and customer data never leave your browser, and there is no Save Online button to change that — a claim worth checking on any tool you paste production data into.

toolkit.codes/json-formatter
Paste JSON to format it
UTF-8
Ready
100% LOCAL
Input
Pasted or uploaded JSON text — valid or not, one line or several megabytes.
Output
Indented JSON at 2 spaces, 4 spaces or a tab, optionally with keys sorted; a single-line minified form; or a collapsible tree with key and item counts.
Processing
Parsed and re-serialized in this tab by your browser. There is deliberately no load-from-URL button, because fetching a URL on your behalf is the one feature that would put your payload on the wire.
Limits
No size cap on parsing. Past 300,000 output characters the on-screen display truncates and highlighting turns off, while Copy and Download keep the whole document.
Grammar
RFC 8259 strictly — no comments, no trailing commas, no unquoted keys. JSONC and JSON5 are different formats, and input written in them is reported as an error rather than quietly accepted.

A JSON formatter & validator that explains itself

Formatter, beautifier, prettifier — one job, three words

Nothing separates them. Beautify, prettify, pretty-print, indent, format: all five name the same operation — re-serializing the same data with newlines and indentation so a human can read it — and tools pick a word for marketing reasons, not technical ones. Minifying is the same operation with the whitespace set to nothing. None of the three changes your data; what comes out parses to exactly what went in, which is why switching between them costs nothing.

What the JSON validator checks, and where it points you

Validation means one thing: does this text obey the JSON grammar in RFC 8259. It runs here on every keystroke, and when the answer is no, the answer alone is useless — a 2,000-line config with one trailing comma fails with "unexpected token" in most places you would paste it. So a second, iterative parser runs purely to locate the failure: it reports the line and column, prints that line with a caret sitting beneath the bad byte, and names the cause when it is one of the six classics — a comment, a trailing comma, single quotes, an unquoted key, NaN, or a leading zero. Paste {"port": 8080,} and you get line 1, column 15, the caret sitting under the closing brace, and the words "trailing comma".

What it warns about that validators skip

Perfectly valid JSON can still betray you, so a second pass scans for it. A 64-bit ID like 9007199254740993 is legal JSON, but JavaScript parses it to 9007199254740992 — silent precision loss that has corrupted real databases; the scanner flags every affected number with both values. Duplicate keys are legal-ish too, and JSON.parse silently keeps the last one — flagged with the line. A __proto__ key parses safely but pollutes prototypes the moment the object is merged in JavaScript — flagged. A leading byte-order mark is stripped for parsing and reported, because the spec forbids it on the wire.

Why in-browser matters more here than anywhere

Consider what people paste into a formatter: production API responses. Those payloads carry bearer tokens, session identifiers, email addresses, customer records. Some of the most-used formatter sites process input server-side — your paste literally travels to their machines — and the ones that advertise browser-side validation still offer "load external data" and "save online" buttons beside it, which do exactly what they say. Nothing here is posted anywhere: the parse, the re-indent and the scan all happen in this tab, and there is deliberately no load-from-URL button, because the ability to fetch a URL on your behalf is exactly the ability to send your payload somewhere. That inability is the feature.

Chrome extensions, editor plugins, and where conversions live

A JSON formatter Chrome extension does one thing this page cannot: it formats a response in place when you open an API URL in the browser, with no copy-paste step, and it shows the same collapsible tree you get here. Install any well-reviewed one and it takes over raw JSON responses automatically — worth having alongside this page rather than instead of it, since an extension cannot help with JSON that arrived by email or lives in a config file. In Sublime Text the equivalent is Package Control plus the "Pretty JSON" package, formatting with Ctrl+Alt+J (Cmd+Ctrl+J on macOS).

Converting is not formatting, and each direction has a page of its own: JSON to CSV for flattening an array of objects into spreadsheet rows, CSV to JSON for the trip back, and JSON to YAML for configuration files. Format here first if the payload is one long line — deciding how nested data should flatten is much easier once you can see the nesting.

Format it, sort it, or flatten it to one line

  1. 01Paste JSON (or Upload a local file — it is read in-browser, not sent anywhere). It runs live: valid input formats immediately, invalid input shows line, column, caret, and hint.
  2. 02Pick your indent — 2 spaces, 4 spaces, or tabs — and toggle Sort keys for a stable, diff-friendly ordering. Arrays keep their order; only object keys sort.
  3. 03Switch to the Tree view to explore structure: every object and array shows its key/item count, expands on click, and paginates instead of freezing on huge arrays.
  4. 04Copy the output, or Download a .json file. Minify produces the single-line form for payloads; the warnings panel below the status line lists anything valid-but-dangerous it found.

Four payloads people actually paste

Unreadable API response

One minified line from curl becomes navigable structure. The tree view answers “what fields does this actually have?” faster than scrolling.

Input
{"data":{"users":[{"id":1,"name":"Ada"}],"total":1},"ok":true}
Output
{
  "data": {
    "users": [
      {
        "id": 1,
        "name": "Ada"
      }
    ],
    "total": 1
  },
  "ok": true
}

Config file that won't load

The app says “invalid JSON” and nothing else. Paste it here and get the line, the caret, and the actual reason.

Input
{
  "port": 8080,
  "debug": true,
}
Diagnosis
✗ Expected a double-quoted property name at line 4, column 1.
}
^
Trailing comma before the closing bracket — JSON forbids trailing commas.

The 64-bit ID that changed

Two systems disagree about an ID and nobody knows why. The warning scanner shows the exact number JavaScript silently rounded.

Input
{"order_id": 9007199254740993}
Warning
line 1: 9007199254740993 exceeds 2^53−1 and parses as 9007199254740992 — precision is silently lost.

Diff-ready normalization

Sort keys + 2-space indent turns two exports into comparable text — stable ordering leaves only the edit you care about in a diff.

Input
{"z":1,"a":{"c":2,"b":3}}
Output (sorted)
{
  "a": {
    "b": 3,
    "c": 2
  },
  "z": 1
}

The whole JSON grammar in one table

TypeSyntaxNotes
String"text"Double quotes only; escapes: \" \\ \/ \b \f \n \r \t \uXXXX
Number-12.5e3No leading zeros, no leading +, no .5 or 5. shorthand
Booleantrue · falseLowercase only
NullnullThe only “empty” value — undefined does not exist in JSON
Object{"key": value}Keys are double-quoted strings; pairs comma-separated
Array[value, value]Ordered; mixed types allowed

A document is exactly one top-level value of any of these types. Whitespace between tokens is free.

Looks fine, is NOT valid JSON

You wroteWhy it failsThe fix
// comment or /* */JSON has no comments — that is JSONC/JSON5Delete them, or keep the file as JSONC and don't call it JSON
[1, 2, 3,]Trailing commas are forbiddenRemove the comma before ] or }
{'key': 'value'}Single quotes are not string delimitersUse double quotes
{key: 1}Unquoted keys are JavaScript, not JSON{"key": 1}
NaN, InfinityNot representable in JSONUse null or encode as a string
01, +5, .5Number grammar is strict1, 5, 0.5
undefinedNot a JSON valuenull, or omit the key

Every row here is something JavaScript itself accepts — which is exactly why payloads that “work in JS” fail JSON validation.

Habits that keep JSON readable and diffable

  • Formatting is for reading; minified is for shipping. The whitespace is pure transport weight — the byte counts in the status line show exactly what it costs.
  • Sort keys before committing JSON fixtures — stable ordering means your diffs show real changes, not reordering noise.
  • Big integer IDs (snowflake IDs, database bigints) belong in strings. If the warning panel flags one, the fix is on the producer side: quote it.
  • Tabs vs spaces is a team convention, not a correctness question — the indent select covers both.
  • Use Upload for multi-megabyte files instead of pasting — the file is read locally and skips the clipboard round-trip.
  • The tree view is the fastest answer to “is this field an array or an object?” — counts show before you expand.

Valid JSON that still breaks something

Numbers past 2^53 lose precision silently

JSON allows arbitrary integers; JavaScript stores them as doubles. 9007199254740993 parses to …992 with no error, anywhere JS touches the payload. This page warns with both values; the durable fix is transmitting big IDs as strings (or parsing with a BigInt-aware parser).

Duplicate keys: last one wins, nobody tells you

The spec leaves duplicate keys undefined; every JavaScript runtime keeps the last occurrence and drops the rest silently. A payload can carry two "amount" fields and parse without complaint. The warning scanner reports which key repeated, and where.

JSON ≠ JSON5 ≠ JSONC

VS Code settings accept comments (JSONC); some configs use JSON5 (comments, trailing commas, unquoted keys). Both fail strict JSON validation — by design. This tool tells you which convenience broke the parse instead of silently accepting it and letting your API reject it later.

“But it works in JavaScript!”

Object literals in JS accept unquoted keys, single quotes, trailing commas, NaN. JSON borrows the look but keeps a stricter grammar. Anything pasted from JS source will likely need quote and comma cleanup — the not-valid-JSON table above is the checklist.

A "load from URL" button is a privacy answer

A pasted API response routinely contains authorization tokens and customer data, so the question is where that paste ends up. Load-external-data and save-online features are the tell: both require a server, whatever the page says about validating in your browser. Prefer tools whose privacy is verifiable rather than promised. Here the payload never leaves: formatting, minifying, the tree, sorting, upload, copy and download all complete without a single request. The content policy blocks cross-origin connections outright. What it does permit is this site’s own analytics beacon, which reports that a page was viewed and never what you typed into it — so the claim worth making is that no tool code makes a request, not that the page is incapable of one.

Parser, scanner, and the limits that matter

Validation
Native JSON.parse (RFC 8259); on failure an iterative locator parser pins line/column and states what was expected — deep nesting cannot overflow it
Error hints
Targeted detection for comments, trailing commas, single quotes, unquoted keys, NaN/Infinity/undefined, leading zeros
Warnings
Single-pass scanner, capped at 100: integers past ±(2^53−1) with the parsed value shown, duplicate keys (escape-aware, per object), __proto__ keys. A leading BOM is reported separately by the parser, which strips it before parsing
Formatting
2 / 4 / tab indent; recursive key sort (arrays untouched); minify
Views
Syntax-highlighted code · lazy collapsible tree with key/item counts, 500 children per page. Past 300k output chars the display truncates and highlighting turns off — Copy/Download keep the full document
Large inputs
Warning scan yields to the event loop; highlighting renders in chunks; tree builds on expand — multi-MB payloads stay responsive
File handling
Uploads are read inside the page with the browser File API and are never transmitted; Download writes out what is already in the tab. There is deliberately no load-from-URL: fetching a URL on your behalf is the one feature that would put your payload on the wire.
Network
None from tool code. A test sweep calls every function this page uses with fetch and XMLHttpRequest replaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.

Questions about formatting and validating JSON

Is it safe to paste API responses with tokens in them?

Here, yes — which is worth checking elsewhere, because a formatter offering to load data from a URL or save your document online is a formatter your bearer token travels to. The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.

Why does it say my JSON is invalid when JavaScript accepts it?

JavaScript object literals allow unquoted keys, single quotes, trailing commas, and NaN; JSON does not. The error hint names which of those bit you, and the "not valid JSON" table lists the full set with fixes.

What does the big-number warning mean?

JSON can express integers of any size, but JavaScript numbers lose exactness past 9,007,199,254,740,991 (2^53−1). Your 64-bit ID gets silently rounded — the warning shows the value in the text and the value JS actually produces. Ship large IDs as strings.

Does the formatter change my data?

Formatting re-serializes what JSON.parse produced: whitespace changes, key order is preserved (unless you enable Sort keys), and everything JSON.parse silently normalizes — duplicate keys, big-number rounding — is exactly what the warnings panel reports. The tool never "fixes" invalid syntax for you.

How big a file can it handle?

Multi-megabyte payloads format fine: parsing is native, the warning scan yields to keep the tab responsive, past 300k characters the on-screen output truncates (Copy and Download keep everything) because DOM layout, not parsing, is what freezes tabs, and the tree renders children lazily. For hundred-MB dumps, use a streaming CLI tool like jq instead of any browser tab.

Can it convert JSON to CSV or query it with JSONPath?

Not on this page — half-built converters make bad neighbours, so each conversion gets its own tool. JSON to CSV, JSON to YAML and CSV to JSON and the JSONPath tester all have their own pages.