What the error means
The text you tried to parse starts with the character <, which is the start of an HTML tag. JSON can never begin with <, so the parser stops at position 0. The server almost always sent an HTML page, for example an error page or a login page, where your code expected JSON.
The message looks like this in Chrome, Edge and Node.js (Firefox and Safari use different wording for the same problems):
Unexpected token '<', "<!DOCTYPE "... is not valid JSON
Unexpected token < in JSON at position 0 (older Chrome and Node.js)Common causes
The URL is wrong and the server returned a 404 page
A typo in the path, a missing API prefix or the wrong base URL makes the server answer with its HTML "Not Found" page. Open the URL in a browser tab and check what it returns.
The server crashed and returned an HTML error page
A 500 error from a framework, a reverse proxy or a hosting platform is usually an HTML page. Check the HTTP status code, not just the body.
Broken: <!DOCTYPE html><html><body>Internal Server Error</body></html>You were redirected to a login page
When a session expires, many sites answer API calls with the HTML login page. The status may even be 200 after following the redirect.
A development server or proxy returned index.html
Single-page-app dev servers return index.html for every unknown route. If your API proxy is not configured, a request to /api/users comes back as the app's HTML shell.
You are reading a file or a script instead of an API
Requesting data.json from a path that does not exist, or loading a page that wraps the JSON in HTML, produces the same error.
How to find the problem
- Paste the text that you passed to JSON.parse into the editor above. The status bar shows the line and column of the first problem, and Go to error jumps there.
- Remember that the position in the message is where the parser gave up, which is often one token after the real mistake. Look at the character before it as well.
- If the text came from a request, log the raw response text before parsing it. In the browser, open the Network tab, select the request and read the Response tab.
Check the response before parsing it
const res = await fetch(url);
if (!res.ok) throw new Error("HTTP " + res.status);
const type = res.headers.get("content-type") ?? "";
if (!type.includes("application/json")) {
console.error("Not JSON:", (await res.text()).slice(0, 200));
throw new Error("Expected JSON but got " + type);
}
const data = await res.json();Frequently asked questions
Can Fix JSON repair this?
No. The text is not damaged JSON, it is a different format. Fix the request so that the server returns JSON.
Why does it say position 0?
Because the very first character is already invalid. The parser reads from the start and fails on the first character.