You call an API, the request looks fine, and then your code crashes. The console shows a red error that says something like SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON or Unexpected token 'o', "not json" is not valid JSON. It feels random, but it is not. This error has a very clear meaning once you know where to look.
This guide shows what the error means and how to fix it step by step.
Quick Answer
An “Unexpected token” JSON parse error means your code tried to parse text as JSON, but the text was not valid JSON. The most common cause is that the API returned HTML, plain text, or an error page instead of JSON, or the response was empty. Fix it by logging the raw response text first, checking the HTTP status and content type, and only calling JSON.parse() or response.json() after you confirm the response really contains JSON.
What Does “Unexpected Token” Actually Mean?
JSON is a strict format. Keys and strings must use double quotes, with no trailing commas and no comments. A parser reads it character by character and expects certain tokens in certain places.
An “unexpected token” is the parser telling you: “I found a character here that should not exist in valid JSON.” The token named in the error is your best clue. If the token is <, the text almost certainly starts with HTML, because HTML tags start with that character. If the token is a letter like o in the word “not”, the text is probably a plain English error message.
The official behavior of the parser is described in the MDN Web Docs guide to JSON.parse and its SyntaxError handling, which explains that any input that does not follow the JSON grammar throws a SyntaxError.
Common Versions of This Error
You may see slightly different wording depending on your browser or runtime:
Unexpected token '<', "<!DOCTYPE "... is not valid JSON— the server sent an HTML page.Unexpected token 'o', "not found" is not valid JSON— the server sent plain text.Unexpected token 'u', "undefined" is not valid JSON— you tried to parse the valueundefined.Unexpected end of JSON input— the response body was empty.Unexpected token } in JSON at position 42— the JSON itself is malformed, often a trailing comma or missing quote.
Step 1: Log the Raw Response Before Parsing
Never debug this error blind. Look at the exact text your code received. Do not guess. Print the raw text.
If you use the Fetch API, read the response as text first:
- Replace
response.json()withresponse.text()temporarily. - Log the result with
console.log(). - Open your browser console or terminal and read the first 200 characters carefully.
- Check whether the text starts with
{or[, which is how real JSON starts.
Here is a safe pattern you can keep in production code:
const text = await response.text();
console.log(text.slice(0, 200));
const data = JSON.parse(text);
If the logged text is an HTML page like “404 Not Found”, your problem is the request itself, not JSON. The URL may be wrong or the server may have returned its default error page.
Plain text like “Not Found” means the API sent a text error. An empty string means no body was returned, common with 204 No Content. JSON that looks almost right usually has single quotes or a trailing comma.
Step 2: Check the HTTP Status Code
Fetch does not reject its promise for HTTP errors like 404 or 500, only for network failures. So your code can try to parse an error page as if it were data.
Always check response.ok and response.status before parsing:
- Log
response.statusright after the request finishes. - If the status is not in the 200 range, stop and handle the error.
- Read the body as text so you can see the server’s error message.
- Only parse JSON when the status tells you the request worked.
Status codes guide your fix. A 401 or 403 means a missing API key or token. A 404 means the path is wrong. A 500 means the server failed.
Step 3: Check the Content-Type Header
Servers declare what they are sending with the Content-Type header. For JSON, it should be application/json. If it says text/html, the server is sending a web page, no matter what you asked for.
You can check this in two places:
- In code, read
response.headers.get('content-type')and log it. - In the browser, open the Network tab in DevTools, click your request, and read the response headers.
A mismatch often reveals a setup issue. Many single page apps return index.html for every unknown route, so a typo in your API URL returns HTML instead of JSON.
Step 4: Check the Request Itself
If the raw response is an error page, work backwards to the request. Small request mistakes produce this error every day.
Wrong URL or Missing Path
Compare your request URL with the API documentation. A missing /api prefix or a wrong domain can route you to an HTML page instead of the API.
Wrong Method or Missing Headers
Some endpoints only accept POST. Others require an authorization header. Without the token, the server may redirect you to an HTML login page, a classic cause of the < token error.
CORS and Redirects
For example, our related guide on why fetch requests return undefined in JavaScript and how to await them correctly covers a related response-handling mistake.
Step 5: Validate the JSON Itself
Sometimes the server sends broken JSON, often from hand-written mock data. Paste the raw text into a JSON validator and look for these faults:
- Single quotes around keys or values instead of double quotes.
- Unquoted keys, like
{ name: "Ali" }instead of{ "name": "Ali" }. - A trailing comma after the last item in an object or array.
- Unescaped quotes or line breaks inside a string value.
- The value
undefined,NaN, orInfinity, which are JavaScript values but not valid JSON. - Comments inside the data, which JSON does not allow.
If the bad JSON is from your own mock file, fix the file. If it comes from a third-party API, report it and protect your code with try...catch.
Double-Encoded and Already-Parsed Data
Two special cases confuse beginners. Double encoding means the server sends a JSON string containing JSON, spotted when the raw text starts with a quote. Already-parsed data means a library parsed it for you, so an extra JSON.parse() fails with [object Object]. Remove the extra parse and use the object directly.
Step 6: Parse Safely With try…catch
Wrap the parse in a try...catch block. In the catch block, log the raw text and show a friendly message like “We could not load this data.” In Node.js, the same approach works for config files with typos: log the file path and first characters to spot the fault.
Common Mistakes and Useful Tips
- Parsing before checking the status: the number one cause. Always check
response.okfirst. - Guessing instead of logging: two minutes of logging beats an hour of guessing. Print the raw text every time.
- Parsing an empty body: endpoints that delete data or return
204have no JSON. Check the text length before parsing. - Calling
JSON.parseon an object: if the value is already an object, parsing it turns it into the text[object Object]and fails. - Ignoring redirects: an expired session can redirect API calls to an HTML login page. Check the final URL and status in the Network tab.
- Trusting the endpoint name: a URL ending in
.jsonproves nothing. Trust the status and the content type, not the name.
Tip: use one helper function for all API calls that checks status and parses safely. This prevents most of these bugs.
Conclusion
The “Unexpected token” JSON parse error is not really a JSON mystery. It is a sign that non-JSON text reached your parser. Log the raw response, check the status code, check the content type, and fix the request or the data at the source. Add safe parsing with try...catch so one bad response never crashes your app again. Follow these steps in order and you will solve this error in minutes instead of hours.
Frequently Asked Questions
What does Unexpected token ‘<‘ mean in JSON?
It means the text you tried to parse starts with the < character, which almost always comes from HTML such as <!DOCTYPE html>. Your code expected JSON but received a web page, usually because of a wrong URL, a redirect to a login page, or a server error page.
Why does response.json() fail even though the API works in Postman?
Your app may call a different URL, miss an authorization header, or hit a different environment than Postman. Compare the exact URL, method, and headers, and check the status and raw text in your app.
How do I fix “Unexpected end of JSON input”?
This error means the response body was empty. Check the status code first. If the endpoint returns 204 No Content or an empty 200 response, do not parse the body. Read the text first and only parse when the text is not empty.
Can a trailing comma cause an Unexpected token error?
Yes. JSON does not allow a comma after the last item in an object or array. Browsers will report the closing bracket or brace as the unexpected token. Remove the extra comma and validate the full payload with a JSON validator to catch similar faults.
Should I use response.json() or JSON.parse() with fetch?
Both parse JSON, but response.json() hides the raw text, which makes debugging harder. When you face parse errors, use response.text() plus JSON.parse() so you can log what the server sent.


Leave a Reply