A formatter that answers Unexpected token H in JSON at position 0 is telling you something real. The H is the HTTP/1.1 200 OK line you copied along with the body. Almost every failed paste has a cause of that kind, and the fix is peeling one layer off the front rather than blaming the API.
What actually lands on your clipboard
Response bodies pick up passengers on the way to your editor. Terminal output includes the status line, security middleware writes a guard prefix, and message queues hand you one document per line. The Clean the paste toggle removes the following before parsing, and the status bar names whatever it stripped.
| What you pasted | Where it came from | Handling |
|---|---|---|
HTTP/1.1 200 OK plus header lines | curl -i, curl -v, or Copy as response in a browser network tab | Status line and every header up to the blank line are dropped |
)]}', on line one | XSSI protection used by Google APIs and several Java frameworks | The guard is removed, along with the while(1); and for(;;); variants |
callback({...}); | A JSONP endpoint reached through a script tag | The wrapper is unwrapped when the inside parses as JSON |
An invisible character before { | UTF-8 byte order mark written by .NET or a PHP file with whitespace before the opening tag | The mark is stripped, so the parse reaches the real first byte |
"{\"order_id\":\"A-2291\"}" | A field holding a JSON document that was serialised twice | One layer of string encoding is unwrapped and the result parsed again |
| Several objects, one per line | Log streams, bulk exports, and the Elasticsearch and OpenAI streaming formats | Detected as JSON Lines, with each record parsed and numbered separately |
A trailing comma or a // note | A fixture edited by hand, or a config file saved as JSON with comments | Removed as a fallback after the strict parse fails, and reported when applied |
Turn the toggle off when you want the strict result. Debugging a client library that rejects a body is exactly the case for it, since the point is to see the same failure the library sees.
Turning a parse error into a location
Browser JSON errors report a character offset, not a line. The panel below the editors converts the offset to a line and column, prints the three lines around it with a caret under the byte, and the Go to the bad character button moves the cursor there. Three messages cover most of what you will hit:
- A tag where a brace belongs. The response was an HTML error page. A reverse proxy timeout, a login redirect, or a WAF block page reached you instead of the API. Read the first line of the output and you usually find the real status.
- Input that stops early. The body was cut off. Connection limits, a client reading a fixed number of bytes, and truncated gzip all end this way. The last line in the trace shows how far the document got.
- Content after the closing brace. Two documents are stuck together. That is a stream, so switch the format control to JSON Lines and each record gets parsed on its own.
- Paste the body untouched, including anything above it.
- Read the badge in the toolbar to see which format was detected. A response you expect to be JSON showing up as Plain text means the front of the document is wrong.
- Press Validate for a yes or no answer with no reformatting.
- If the parse fails, follow the caret to the byte and look at the character before it, which is where the real mistake usually sits.
The shape panel
Under the panes sit four numbers taken from the parsed document rather than the text: nesting depth, total node count, total key count, and the length of the longest array. Top level keys appear beside them.
Depth is the number worth watching. A payload nested eight levels deep forces every consumer to write defensive accessor code, and mobile clients pay for it in parsing time on older devices. Widest list tells you whether an endpoint returns everything at once, which is the difference between a page of results and an accidental full table scan. Compare the same endpoint before and after a schema change and the four numbers show what moved.
Sort keys reorders every object alphabetically at all levels. Two responses from different environments become diffable that way, because key order stops being noise. Use it before pasting both into a diff tool, and leave it off when key order is part of what you are inspecting.
XML responses carry more than tags
SOAP envelopes and legacy REST services arrive as one long line. Formatting indents by nesting level, keeps namespace prefixes exactly as written, and leaves CDATA blocks untouched, since the whitespace inside them is content rather than layout.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>Invoice not found</faultstring></soap:Fault></soap:Body></soap:Envelope>A SOAP fault returns HTTP 200 in most implementations, so an HTTP status check alone will not catch it. Format the body and look for a Fault element inside Body. That is the failure signal in this protocol, and the Top level list makes it visible without reading the whole document.
Attributes against child elements
The key count for XML counts attributes, not elements, so a document that models data as attributes reports differently from one using child elements for the same fields. Both are valid. Knowing which one an endpoint uses matters when you map the response onto a JSON model, because attributes usually end up prefixed and children do not.
YAML is stricter than it looks
Config APIs and Kubernetes-style endpoints return YAML, and the parse follows the YAML 1.1 rules the popular libraries use. Two habits cause most surprises:
- Bare words become booleans.
country: noparses asfalse, andyes,on, andoffbehave the same way. Country codes, answer fields, and anything holdingNOneed quotes. The YAML sample above includes this line so you see the parsed value. - Version numbers lose a decimal.
version: 2.4is a float and re-emits as2.4, whileversion: 2.4.0stays a string. A key like"200"under responses has to stay quoted or it turns into an integer and stops matching the status code.
Tabs are illegal for indentation anywhere in a YAML document, and a duplicate key at the same level is an error in strict parsers while others silently keep the last value. The error line reported here points at the mapping where the parser gave up, which is normally one line past the real problem.
Where this formatter stops
Everything runs in your browser. No request leaves the page, which rules out several things you might want:
- No requests are sent. There is no URL field and no proxy. Fetch the response with your own client and paste the body. Sending a production response through a third party server is not something this page asks you to do.
- No schema validation. Well formed is checked, valid against a contract is not. JSON Schema, OpenAPI, and XSD checks need a validator that reads your schema file.
- Comments and anchors do not survive YAML round trips. The document is parsed to a value and re-emitted, so comments disappear and anchors expand into repeated content. Format YAML here to read it, not to hand the output back into version control.
- XML output collapses mixed content. Whitespace between tags is treated as layout, which is right for data documents and wrong for markup where spacing between inline elements is meaningful.
- Large bodies feel it. Beyond a few megabytes the editor and the parse both slow down, and browsers hold the whole string in memory. Multi-megabyte exports belong in a streaming command line parser.
- Binary and compressed bodies are out of scope. Protocol buffers, MessagePack, and a gzip body copied before decoding all read as noise here.
The trailing comma repair is the one place where the output differs from strict input, and the status line always names it when it happens. Everything else preserves your values exactly, including number precision beyond what JSON parsers round to.
Working with one format only? The JSON Fixer repairs broken payloads more aggressively, and the XML Pretty Print page handles documents that are not API responses at all.
