How to format JSON without uploading it anywhere
You have a minified API response that you need to read. You paste it into the first online JSON formatter you find, click format, and get clean indented output. Convenient. The problem is that many of those formatters send what you pasted to a server before handing the result back. The thing you pasted often contains an access token, a session cookie, an API key in a header, a customer email, or an internal hostname. You just shipped all of that to a third party you know nothing about.
This post covers how to format and validate JSON without uploading it, how a local formatter actually works, and how to confirm with your own eyes that nothing leaves your browser.
Why pasting JSON into a random site is a real risk
JSON is the format of API traffic and config files, which means it is also the format your secrets travel in. A typical payload you might want to pretty print could look like this:
{"user":{"id":4012,"email":"ops@yourcompany.com"},"auth":{"token":"eyJhbGci..."},"db":{"host":"prod-internal.db.local"}}
If the formatter POSTs that string to its backend, the operator now has a working token, an internal hostname, and a real email address. Even if the site is honest, the data still hit a log file, a proxy, or an error tracker somewhere along the way. For anything from a production system, that is a leak. Treat every minified blob as if it contains a credential, because eventually one will.
How a client side formatter works
Formatting JSON does not require a server at all. The browser already ships a complete JSON engine. The entire operation is two function calls:
const parsed = JSON.parse(input); // string to object, throws on invalid input
const pretty = JSON.stringify(parsed, null, 2); // object back to a string, indented 2 spaces
JSON.parse reads your text and builds an in memory object, throwing a precise error if the syntax is wrong. JSON.stringify walks that object and writes it back out. The third argument controls indentation: a number for that many spaces, or "\t" for tabs. Minifying is the same call with no indent argument, which strips every space and newline.
All of this runs in the JavaScript engine on your machine. There is no reason for the text to touch a network connection. A formatter built correctly loads its code once, then does every parse and stringify locally, even with your network unplugged. That is exactly how the toolhq JSON Formatter works: the page loads, and from then on your input stays in the tab.
How to verify nothing leaves your browser
Do not take any tool's word for it, including ours. Check it yourself in about thirty seconds.
- Open the formatter page.
- Open developer tools and go to the Network tab.
- Clear the request list so you start clean.
- Paste a junk payload like
{"test":123}and trigger the format action. - Watch the request list. A local tool produces zero new requests. A tool that uploads your input produces a POST or fetch with your text in the request body.
If you see a request fire the moment you format, expand it and look at the payload. Your JSON sitting in that body is the proof it was uploaded. For an even harder guarantee, switch the Network tab to offline or disconnect from wifi entirely. A genuine client side tool keeps working with no connection. Anything that calls home will fail.
Formatting versus validating
These two operations are related but not the same, and the difference matters when you are debugging.
Formatting changes only whitespace. It takes valid JSON and re indents it for readability, or strips the indentation to minify. It does not change a single value or key. Formatting assumes the input is already valid.
Validating answers a different question: is this even legal JSON, and if not, where does it break. A good validator parses the input and, on failure, reports the position of the error so you can jump to the exact character. You validate to find the broken comma. You format to make the valid result readable. A decent tool does both in one pass, since JSON.parse already validates as a side effect of parsing.
Common causes of invalid JSON
When a parse fails, it is almost always one of these:
- Trailing commas.
{"a": 1,}is valid in JavaScript object literals but illegal in JSON. Remove the comma after the last item. - Single quotes. JSON requires double quotes on both keys and string values.
{'a': 1}fails. - Unquoted keys.
{a: 1}is a JavaScript object, not JSON. Keys must be strings in double quotes. - Comments.
//and/* */are not part of JSON. Strip them, or use JSON5 or YAML if you need comments. - Wrapped or doubly encoded strings. A value like
"{\"a\":1}"is a string that contains JSON, not parsed JSON. You need to parse it twice or unescape it first. - Trailing junk. A stray character or a second object after the first, with nothing joining them, breaks the parse at that offset.
When the error message points at a line and column, go to that spot and look one character before it. The real mistake is usually just upstream of where the parser gave up.
Keep the rest of your debugging local too
The same privacy logic applies to the neighbors of JSON in your workflow. If you are inspecting an Authorization: Bearer header, decode it with a local JWT Decoder rather than a site that logs tokens. If you need to pull one field out of a noisy log line, a regex tester that runs in the browser keeps the log on your machine. And if you are reshaping data between formats, a local JSON to CSV converter does the transform without uploading the rows.
The rule is simple. If a tool can do its job with your network turned off, it should. Anything that needs a server to format text is asking for trust it does not need.
Open the JSON Formatter and run the offline test for yourself.