Quick answer
The server sent back HTML (usually starting with <!DOCTYPE html> or <html>) and your code tried to parse it as JSON. The parser fails on the very first character, which is why the position is 0. The JSON is not broken. The response is not JSON at all, so look at what the server actually returned.
The same error in different browsers
- Older Chrome and Node.js:
Unexpected token < in JSON at position 0 - Newer Chrome and Node.js:
Unexpected token '<', "<!DOCTYPE "... is not valid JSON - Firefox:
JSON.parse: unexpected character at line 1 column 1 of the JSON data
Most common reasons
- Wrong URL. The endpoint does not exist and the server returned a 404 HTML page.
- Server error. The API crashed and returned an HTML error page (500, 502, 503).
- Login redirect. The request was redirected to a login page.
- Single-page app fallback. The host returns
index.htmlfor unknown paths, including your API path. - Missing proxy or wrong port. In local development the request goes to the frontend dev server instead of the API.
How to find the real problem
Check the status code and content type, and print the start of the response before parsing:
const res = await fetch("/api/users");
const type = res.headers.get("content-type") || "";
if (!res.ok || !type.includes("application/json")) {
const text = await res.text();
console.log(res.status, type);
console.log(text.slice(0, 200)); // you will see the HTML here
throw new Error("Expected JSON but got " + type);
}
const data = await res.json();
You can also open the request in the browser Network tab and look at the Response tab. If it shows a web page, the problem is on the server or in the URL, not in your parsing code.
The same problem in Python
import requests
r = requests.get(url)
print(r.status_code, r.headers.get("content-type"))
print(r.text[:200])
data = r.json() # fails if the body is HTML
The Python message is usually Expecting value: line 1 column 1 (char 0).
If the response really is JSON
Sometimes the text starts with a hidden character or extra text before the JSON. Paste it into the JSON Formatter to see where it breaks, or use the JSON Repair tool.
Have broken JSON right now?
Paste it into the free JSON Repair tool. It runs in your browser, so nothing is uploaded.
Open JSON Repair toolFAQ
Why does the error point to position 0?
HTML starts with a less-than sign, and that is not a valid first character for JSON, so the parser fails immediately.
Why does it work locally but not in production?
Often the API base URL or proxy settings differ, so in production the request reaches a different server that returns an HTML page.
Is this a bug in JSON.parse?
No. JSON.parse is doing its job. The input is not JSON.