How to Read a Minified JSON API Response (and Find the Error Inside It)
Disclaimer: This article is general technical guidance, not support for any specific API. Never paste production credentials or customer data into a tool you have not verified runs locally.
You open the Network tab, click the request that is returning the wrong number, switch to the Response view, and get a wall of text. Sixty kilobytes, one line, no indentation, and somewhere inside it the field you actually came for. The browser offers no help beyond a horizontal scrollbar.
This is the normal state of API responses. What is less obvious is that half the work of debugging one is not reading it at all — it is getting the payload into a shape where the parser's own error message becomes useful. That is what this guide covers.
The short version: open the response in the Network tab and click the {} pretty-print button. If you are working outside the browser, wrap the raw text in JSON.parse() and re-serialise it with JSON.stringify(value, null, 2). If the payload will not parse at all, use a formatter that reports the error position, because the position is the only clue that tells you where to look.
Why APIs Send JSON on a Single Line
Minified JSON is one long line because whitespace between tokens carries no meaning. Indentation and newlines exist purely for human eyes; the parser does not need them, so serialisers leave them out.
The usual justification is payload size, and it is a weaker argument than it sounds. Almost every API response is compressed on the wire with gzip or Brotli, and both are very good at collapsing repeated spaces. The bytes you save by minifying are largely the bytes compression was already going to remove. In practice, minification persists mostly out of convention: JSON.stringify(value) and json.dumps(value) both produce compact output by default, and adding indentation is an extra step a server author has to think about.
There is one real benefit beyond size. A compact payload has no layout of its own, so every client can render it however it likes — two spaces, four spaces, a collapsible tree. If the server sent indentation, clients would either discard it or impose it on people who wanted something else.
Three Ways to Make It Readable
1. The browser's built-in pretty-print
In Chrome, Edge and Firefox, open DevTools, go to Network, click the request, and choose the Response or Preview tab. Near the top of the panel there is a small {} button — the tooltip reads "Pretty-print" or "Format". Clicking it re-indents the payload in place, with collapsible nodes.
This is the fastest option and usually enough. Two caveats: it only appears when the response is served with a JSON content type, and it works on the current response only. If you reload, you are back to one line.
2. Reprocess it in the console
When you need the data rather than a look at it, do this in the DevTools console once you already have the response:
JSON.stringify(JSON.parse(rawText), null, 2)
Read it from the outside in. JSON.parse(rawText) turns the text into a real JavaScript value, and JSON.stringify(value, null, 2) turns that value back into text with two-space indentation. Any number of spaces works, or you can pass "\t" for tabs. The reason this round trip is the right move is that it separates the two questions that a broken payload confuses: is this valid JSON? and what is in it? If the first call throws, you know the answer to the first question is no, and everything after it is irrelevant.
A useful variation when you only care about one branch of a large object is to stringify just that branch:
console.log(JSON.stringify(data.items[0], null, 2))
3. An offline formatter
When the payload is not something you can reach from the console — a saved .json file, a log line, a response pasted from a colleague — paste it into a JSON formatter. The advantage over the two options above is that a good formatter does not just indent: it also refuses to guess. It parses strictly, and when parsing fails it reports the exact position, which is the part that actually saves time.
One thing to check before you paste: confirm the tool processes the text in your browser. A formatter that posts your payload to a server has just sent that payload to a third party — which, for an API response, may include bearer tokens, internal hostnames or customer records. With a client-side tool you can verify nothing is uploaded by opening the Network tab and watching that no request fires while you paste.
Orienting Yourself in a Large Payload
Once the JSON is indented, the next problem is scale: a nicely formatted 4,000-line document is still 4,000 lines. Three habits make it navigable.
- Find the repeating unit. Almost every API response is a wrapper around a collection. Look for the array — the first
[at a shallow depth — and read one element of it closely. The shape of that one record tells you the shape of the other 499. - Read the shallow keys first. Top-level keys are usually metadata (pagination, status, timestamps) and the payload hangs off one or two of them. Collapse everything you are not looking at.
- Check the types, not just the values. A number rendered as
"12"with quotes is a string, and sorting or comparing it as a number will behave unexpectedly. This is a common source of bugs that look like logic errors but are type errors.
The Six Failure Modes That Break the Parse
When someone says "the API is broken", the payload usually contains perfectly fine-looking data. These are the failure modes worth checking in order, because the first two account for most of them.
| What you see | What is actually wrong | How to confirm it |
|---|---|---|
Unexpected token < |
An HTML error page was returned with a JSON content type — typically a proxy, load balancer or maintenance page answering before your app did. | Look at the first character of the response body. If it is <, you are reading HTML. |
Unexpected end of JSON input |
The response was truncated. The document starts correctly and simply stops — a dropped connection, a timeout, or a server that crashed mid-write. | Compare the byte length in the Network tab against a known-good response. |
Unexpected token \uFEFF |
A byte-order mark was prepended to the body. JSON does not permit one, even though many editors write it silently. | Check the first three bytes of the file are not EF BB BF. |
Error points at an unexpected } or ] |
A trailing comma before the closing bracket. Valid in JavaScript and in JSON5, rejected by strict JSON. | Read the position as "the parser gave up here" and look one character back. |
| Parsing fails on a value you never wrote | NaN, Infinity or -Infinity. Python's json.dumps emits all three by default and none are valid JSON. |
Search the payload for those bare words. Fix it server-side with allow_nan=False. |
| Parsing succeeds but the fields are strings | The response was double-encoded: a JSON document whose value is another JSON document, so you get one string instead of an object. | If a field starts "{\", parse that field a second time. |
Note what these have in common: not one of them is a data problem. Every single one is a syntax problem, which is why the position in the error message is the most valuable thing you get. A validator that only says "invalid" leaves you scrolling; a validator that says line 3, column 5 puts you one screen away from the answer.
Turning a Character Offset Into a Line and Column
Different engines report errors differently, and knowing which you are looking at saves a wasted search.
- V8 (Chrome, Edge, Node) reports a character offset:
... in JSON at position 412. Recent versions append the line and column as well. - SpiderMonkey (Firefox) reports the line and column directly:
JSON.parse: unexpected character at line 3 column 5 of the JSON data. - JavaScriptCore (Safari) uses a different phrasing again, and is the least consistent across versions.
When all you get is an offset, converting it is mechanical. The offset counts every character in the document, newlines included, starting from zero. Count the newline characters before it to get the line number, then count the characters since the last newline to get the column. For a large payload, doing that by hand is exactly the kind of task that should not be done by hand — a formatter computes it from the same offset in one pass.
Read the position as "the parser gave up here", not "the error is here". JSON is parsed left to right, so a missing comma is only detected when the parser reaches the next token. The reported character is usually the innocent one after the mistake. Look at what comes immediately before it.
A Worked Example
Here is a payload that fails, pasted exactly as an API returned it:
{"order":1041,"items":[{"sku":"A-19","qty":2,},{"sku":"B-04","qty":1}],"total":47.5}
The parser stops at the } that closes the first item and reports something along the lines of Expected double-quoted property name in JSON at position 45. Position 45 is that brace. The actual mistake is the comma immediately before it — a trailing comma after "qty":2.
Remove it and the document is valid. Format the result and the structure becomes obvious at a glance:
{
"order": 1041,
"items": [
{
"sku": "A-19",
"qty": 2
},
{
"sku": "B-04",
"qty": 1
}
],
"total": 47.5
}
Nothing about the data changed. Formatting and minifying only move whitespace around; key order, values and number precision are untouched. That is worth stating plainly, because a fair number of people avoid formatting for fear it will "change something". It cannot: the tool parses the text and re-serialises the parsed value, and if the text will not parse, there is no value to re-serialise.
A Short Checklist for the Next Time It Happens
- Look at the first character of the body. If it is
<, you received HTML, not JSON. - Check the response is complete — a truncation looks identical to a syntax error until you compare byte lengths.
- Paste it into a formatter and read the position, then look at the character before it.
- If it parses but the shape is not what you expected, check for double encoding and for numbers delivered as strings.
- Once it is readable, find the array and study one element rather than the whole document.
Frequently Asked Questions
Why is JSON from an API minified?
Minifying removes whitespace, so the payload is marginally smaller on the wire. The saving is small once the response is gzipped, which already collapses runs of spaces, so today it is mostly convention: most frameworks serialise without indentation by default and clients are expected to format the data if a human needs to read it.
What does "Unexpected token" in a JSON error mean?
It means the parser met a character it did not expect at the position given. The character itself is usually correct and the real mistake is just before it, so always read the reported position as "the parser gave up here", then look at what precedes it. A missing comma, a stray trailing comma or an unquoted key are the usual causes.
How do I convert a JSON error position into a line and column?
The position is a zero-based character offset counting every character including newlines. Count newline characters before that offset to get the line, and the number of characters since the last newline to get the column. A formatter does this for you, which is why it is worth pasting the payload into one rather than counting by hand.
Why does my API return NaN or Infinity in JSON?
Because the serialiser was lenient. Python's json.dumps emits NaN, Infinity and -Infinity by default, and none of them are valid JSON, so a strict parser on the receiving end rejects the whole document. If you control the server, pass allow_nan=False so the problem surfaces immediately instead of corrupting the response.
Is it safe to paste an API response into an online JSON formatter?
Only if the tool runs entirely in your browser. A formatter that uploads your payload sends whatever is in it, including tokens, internal hostnames and personal data, to a third party. Our JSON formatter parses and re-serialises locally, so nothing leaves the page — you can verify that by watching the Network tab while you paste.
Methodological note: This article was written and fact-checked by the Fengvi Editorial Team following a documented editorial methodology. All cited data comes from public sources.