JSON.parse() throws a SyntaxError when its input is not valid JSON. “Unexpected token <” often means the input starts with HTML instead of JSON—but that message alone does not reveal why. Check the response body, HTTP status, and Content-Type before changing your code or server.
What “Unexpected token <” means
The parser found a character that does not fit valid JSON at the reported position. A leading less-than sign is a useful clue because HTML markup commonly starts with <. For example, a client may expect an API response but receive an HTML page instead.
As an Amazon Associate I earn from qualifying purchases.
The error does not identify the cause. A wrong endpoint, an error page, a redirect, or other routing or server behavior could produce an unexpected body. Inspect what actually came back rather than treating the token as a diagnosis.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →How to find the actual problem
- Find the parsing call. Identify the code path calling
JSON.parse()orresponse.json(), and determine which string or response body it tries to parse. - Check the HTTP status. With
fetch(), inspectresponse.statusorresponse.ok. A 404 response does not, by itself, make the fetch promise reject, so code may continue and attempt to parse an error page as JSON. See MDN’s Fetch guide. - Check the response content type. Inspect the
Content-Typeheader to see whether the server says it returned JSON. A header is evidence, not proof that the body is valid JSON; compare it with the actual response. MDN’s Fetch guide shows checking response headers before reading the body. - Read the body as text when it is unexpected. For diagnosis, use
response.text()instead of immediately callingresponse.json(). Check whether the body is HTML, an error message, or something else. A response body is a stream, so read it once; if you need to inspect and then parse it, clone the response before consuming it. - Compare the result with the API contract. If the body is HTML, investigate whether the URL points to the intended API route and whether the response reflects an error, redirect, or authentication behavior. Treat these as possibilities to verify, not conclusions from the parser error.
- If JSON was intended, inspect its syntax. Use the reported position or line and column, if available, to locate the invalid text. Correct the JSON rather than trying to parse JavaScript object-literal syntax.
What other JSON.parse errors can tell you
Error wording varies among JavaScript engines. The token and position are clues to where parsing failed; inspect the complete input before inferring a cause.
#1 Best Overall
- “Unexpected token o” or another letter: The parser encountered a character that was invalid at that point. The letter alone does not establish what the input contains or why it was supplied.
- “Unexpected end of JSON input” or “unexpected end of data”: The input ended before the parser could read a complete JSON value.
- Unexpected character after JSON data: There may be non-whitespace text after an otherwise complete JSON value.
- Trailing comma or single-quoted key: These are not valid JSON forms. JSON requires double-quoted property names and does not allow trailing commas. For example,
{"name":"Lee",}and{'name':'Lee'}are invalid JSON even though similar syntax can appear in JavaScript. See MDN’s JSON.parse error reference.
Handle responses without masking the cause
Check the status and content type before treating a response as the JSON your application expects. If the response is an error or its body is not JSON, handle that case explicitly; otherwise, a parsing error can obscure the more useful HTTP status or server message.
async function getJson(url) {
const response = await fetch(url);
const contentType = response.headers.get("content-type") || "";
if (!response.ok) {
const body = await response.text();
throw new Error(`HTTP ${response.status}: ${body}`);
}
if (!contentType.toLowerCase().includes("application/json")) {
const body = await response.text();
throw new Error(`Expected JSON, received ${contentType || "no Content-Type"}: ${body}`);
}
return response.json();
}
This example assumes the endpoint returns JSON on successful responses and uses an application/json content type. Adapt the check if the API contract permits other JSON media types. Response.json() reads the response stream to completion and parses it; it is not simply a check of the header. See MDN’s Response.json() reference.
Quick Recap
Best Value
Rank #4
Rank #2
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




