Stop Unexpected Token Errors Disrupting JSON API Responses

A deploy goes out on a Friday, the orders table renders empty, and the console shows one line: SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON. The team starts bisecting the frontend, the state management, the fetch wrapper. Two hours later somebody opens the Network tab and finds a 502 HTML page from the load balancer sitting where the JSON should be.

The parser was never broken. The error message was correct, complete, and telling you the answer in the first character.

The '<' Is the Most Honest Error Message in Web Development

When a JSON parser reports an unexpected <, it is not confused. It is reporting that the first character it could not consume is an angle bracket, which cannot legally open any JSON value. That is only possible if the body it received is markup.

Expected somewhere: {, [, ", a number, true, false, null
Actually received:   <!DOCTYPE html>

In practice this means one of a short list of things happened on the way to the client: the endpoint returned a 404 page, an unhandled server exception produced a stack-trace HTML page, an authentication redirect sent a login form, or an edge proxy returned its own 502 or 503 document. All four produce the same error string. The difference between them lives in the HTTP status code and the response headers, not in the body the parser complained about.

Read the Excerpt, Not Just the Token

Node and Chrome phrase this error by quoting the first few characters of the offending input:

Unexpected token '<', "<!DOCTYPE "... is not valid JSON

That quoted fragment is an excerpt of the beginning of the body. It is not a position. Firefox, by contrast, reports the location instead of the content:

JSON.parse: unexpected character at line 1 column 1 of the JSON data

Same defect, two different reports, and the correct fix depends on knowing which one you are holding. A runtime that hands you the excerpt is telling you what the response is. A runtime that hands you a line and column is telling you where it broke. The excerpt is far more useful for the HTML case, because it hands you the identity of the unexpected document rather than a coordinate.

The Six Payload Defects, Ranked by How Often They Bite

Unescaped characters in a hand-built response are the classic cause, but the API-specific failures tend to follow a fixed ranking.

  1. An HTML error page in place of JSON. The < case. Anything that intercepts the request before your handler runs can answer with markup.
  2. A trailing comma. Legal in JavaScript object literals, illegal in JSON. Config endpoints built from a template are the usual source.
  3. Single-quoted strings. JSON requires double quotes around keys and values. A value written by hand or copied from Python often arrives with apostrophes.
  4. Unquoted property names. {name: "x"} parses in JavaScript and fails in JSON. Generators that emit language literals instead of serializing produce this.
  5. A byte-order mark at position zero. This is the one that deserves its own section, because it is invisible.
  6. Truncation. The message changes to Unexpected end of JSON input, and the cause is a response cut short by a timeout, a buffer limit, or a proxy.

The BOM: One Invisible Character at Position Zero

A UTF-8 file or a stream can begin with the byte sequence EF BB BF, which decodes to the single character U+FEFF. You cannot see it in a text editor. It shifts every subsequent character by one and makes the first token of otherwise perfect JSON unreadable.

// This throws, and the token looks like a space
JSON.parse('\uFEFF{"ok":true}');

// The BOM is part of JavaScript's whitespace set, so trimming removes it
JSON.parse('\uFEFF{"ok":true}'.trim());   // {"ok": true}

The fix is a one-line trim on the raw text before parsing, and it belongs on the client side as a defensive measure regardless of what the server promises. It also explains a category of bug that is maddening to reproduce: a payload that validates perfectly when pasted into a form and fails when fetched, because the paste never carried the BOM.

Why "Line 1, Column 4821" Points at Nothing Useful

Most production APIs are minified, which means the entire response is one line. A column number in the thousands is technically accurate and practically worthless — it tells you the offset but not the structure around it.

Two things make that coordinate useful again. First, converting the offset to a line and column lets you locate the token in a pretty-printed copy of the same payload, where the surrounding context is legible. Second, when the runtime gives you no position at all and only an excerpt, you can search the raw input for the excerpt, offset by the length of the failing token, and recover the position yourself. That reconstruction is worth having in your own tooling, because it is the difference between "somewhere in this 400 KB body" and a cursor.

Formatting the payload first is what turns a coordinate into an insight, which is the entire reason a validator with a working indent control beats a bare parse call — the same argument that applies to formatting deeply nested payloads before you try to read them.

A Triage Workflow That Finds the Cause in Four Steps

  1. Look at the raw body, not the parsed object. In the browser, that is the Network tab with the Response sub-tab selected, never Preview. From a terminal, curl -i so you also get the status line and headers.
  2. Read the Content-Type header. If it says application/json while the body starts with <!DOCTYPE, the bug is on the server, and you now know it is a mislabelled error response rather than a serialization problem.
  3. Paste the whole raw body into a validator. The token and its position tell you whether you are looking at a syntax defect or an entirely different document.
  4. Reproduce with the same input locally. Feed the captured body to JSON.parse in isolation. If it fails there, the payload is the problem. If it succeeds, your client is corrupting it — usually by calling a text helper on the response before parsing.

The Header Lies More Often Than the Body

The single most common misdiagnosis in this class of bug is trusting Content-Type. A framework's error handler frequently returns an HTML error page to a route that normally serves JSON, and the client's res.json() call then fails with an unexpected token error that points at the symptom rather than the cause.

Three specific patterns are worth checking by name: a global exception handler that renders a template for every route; an authentication middleware that redirects unauthenticated API calls to a login page; and an edge proxy or CDN that answers with its own branded error document when the origin is unreachable. In each case the status code is your fastest signal. A JSON parse error on a 200 usually means a real serialization defect. The same error on a 404, 500, or 502 almost always means the response is not the document you think it is.

Fixing It at the Source, Not in the Client

Two changes upstream eliminate most of this category permanently.

Server side, set the content type explicitly on every JSON response rather than relying on a framework default, and make the catch-all error handler emit {"error": "..."} with the correct header for every route under your API prefix. A client should never have to guess whether a 500 is HTML or JSON.

Client side, check res.ok before touching the body, and only call the JSON parser once the status confirms a success. If you want the raw text for a diagnostic, capture it with res.text() first and parse it yourself, so the failure surfaces with the actual body attached instead of a generic parser exception. That single ordering change turns a two-hour hunt into a one-line console message.

Anything that does reach the parser can be pasted into a client-side validator that never uploads the payload, which matters when the offending body contains credentials or customer data you cannot send to a third party to debug.

Checking a Whole Batch of Endpoints

Once the immediate bug is fixed, the same tooling is useful for prevention. Keep a folder of captured response bodies — one file per endpoint, taken from staging — and run each through a validator on a schedule. A trailing comma introduced by a template change or a BOM introduced by an editor switch will show up as a failing file rather than as a production incident.

Sequential validation with a per-file pass or fail result is enough. The value is not in the volume; it is in having a known-good corpus so that a regression has somewhere to land.

What a Formatter Will and Will Not Do for You

It is worth being precise about the division of labour, because the two halves of a JSON tool do different jobs.

A formatter restructures valid JSON into indentation that a human can scan. It cannot repair broken syntax, because there is no way to know whether a missing brace was meant to close an object or an array. A validator, by contrast, tells you precisely where the text stopped being JSON and what it found instead. Run the validator first, fix the reported token, and only then use the formatter to read the result.

That ordering explains why an indent control is a diagnostic setting and not a cosmetic one. Choosing between two and four spaces has no effect on validity, but it does change how quickly you can find the line the error position is pointing at, and it is the reason what a beautifier does to your data types is worth understanding before you trust the output.

The Rule to Remember

An unexpected token error is a statement about the text, not about your code. The token itself is the evidence: a < means you received a document, a comma at the end of a block means syntax, and a token at position zero that looks like nothing at all usually means a BOM.

Read the token first, check the status code second, and only then go looking at your own parsing logic. In the order of things that actually break JSON APIs, the client is the suspect far less often than the response is — and the error message has been telling you which one it is since the first character.

Frequently Asked Questions

What is an "unexpected token" error in a JSON API response?

An "unexpected token" error occurs when the JSON parser encounters a character or syntax element that doesn't conform to standard JSON formatting rules. This usually happens when the API response contains HTML, XML, or malformed JSON instead of the expected valid data. Using an online JSON error checker can instantly pinpoint the exact location of this invalid character.

How do I fix an unexpected token error in JSON?

To fix this error, you need to identify and remove the invalid syntax causing the parsing failure, such as trailing commas, unquoted strings, or missing brackets. An online JSON validator highlights these exact syntax issues so you can correct them quickly. Once the formatting issues are resolved, your API response will parse successfully.

Why does my API return an unexpected token '<' in JSON?

This specific error almost always means your API endpoint is returning an HTML error page (like a 404 or 500 error) instead of the expected JSON data. The parser fails because the '<' character from the HTML tags is not valid in JSON. You can paste your API response into an online JSON checker to verify if you are receiving HTML instead of JSON.

How can an online JSON error checker help debug API responses?

An online JSON error checker automatically validates your API response and highlights the exact line and column where the syntax error occurs. This eliminates the need to manually search through large blocks of data to find a missing comma or misplaced quote. It provides a fast, reliable way to ensure your API outputs strictly valid JSON.

What are the most common causes of JSON parsing errors?

The most common causes include unquoted property names, trailing commas at the end of arrays or objects, and the use of single quotes instead of double quotes. Additionally, non-escaped control characters or returning non-JSON data like HTML will trigger parsing errors. Running the payload through an online JSON validator quickly exposes these standard formatting mistakes.

How do I validate a JSON API response online?

Simply copy the raw API response body and paste it into the text area of a reliable online JSON validator or error checker. The tool will immediately parse the data and display either a success message or a detailed error log. This allows you to test and format API responses without writing any custom validation scripts.

Can an online JSON formatter fix unexpected token errors automatically?

While an online formatter can restructure and beautify valid JSON, it cannot automatically guess the correct fix for broken syntax like missing quotes or invalid characters. However, a good error checker will highlight the exact location of the unexpected token so you can manually correct it. Once fixed, the tool can then format the clean JSON for easier readability.

What does "unexpected end of JSON input" mean?

This error indicates that the JSON string ended abruptly before the parser could finish reading the data, usually due to missing closing brackets or braces. It often happens when an API response is cut off during transmission or truncated. An online JSON checker will identify the unclosed structures so you can complete the payload properly.

Is there a way to check JSON syntax errors in bulk?

Many advanced online JSON error checkers allow you to upload files or validate multiple JSON objects sequentially. This is highly useful for developers testing multiple API endpoints or large datasets at once. The tool will generate a report detailing any unexpected tokens found across all the provided inputs.

Why is my JSON invalid after fetching from a REST API?

A REST API might return invalid JSON if there is a server-side error, an unhandled exception, or if the content-type header is incorrectly set to JSON while serving plain text. Using an online JSON validator helps you see exactly what raw data the server is actually sending back. Once you identify the malformed output, you can adjust your server-side code to return proper JSON.