Guides / JSON errors
“Unexpected token '<' in JSON at position 0”
How it appears per engine
- Uncaught SyntaxError: Unexpected token < in JSON at position 0 (Chrome / Node.js)
- Unexpected token '<', "<!DOCTYPE "... is not valid JSON (newer Chrome / Node.js)
- SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data (Firefox)
What this error means
JSON can never start with a “<” character — but HTML always does. This error means your code called JSON.parse on something that is actually an HTML document, almost always an error page (404, 500, login redirect) returned where your code expected a JSON API response.
The important insight: the bug is rarely in your parsing code. It is in what the server sent back.
Common causes
1. The API returned an error page instead of data
A wrong URL, a missing route, an expired session redirecting to a login page, or a server error all return HTML. Parsing that HTML throws this error. Log the raw response before parsing to see what actually came back.
Fails
const data = await fetch('/api/users').then((r) => r.json());
// throws: Unexpected token '<' … when /api/users returns a 404 pageWorks
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`API ${res.status}: ${await res.text()}`);
const data = await res.json();2. The dev server served index.html for an unknown path
Single-page-app dev servers (Vite, CRA, Next) respond to unknown paths with your index.html. If your API proxy is misconfigured, /api/... silently returns your app shell — which starts with <!DOCTYPE html>.
3. A proxy, CDN, or captive portal intercepted the request
Corporate proxies and hotel Wi-Fi login pages replace responses with HTML. Check the Content-Type header — if it is text/html, the body was never JSON.
Works
const type = res.headers.get('content-type') ?? '';
if (!type.includes('application/json')) {
throw new Error(`Expected JSON, got ${type}`);
}How to fix it
- Open the request in the browser Network tab and look at the actual response body — it is almost certainly HTML.
- Check res.ok and res.status before calling res.json().
- Verify the URL, the HTTP method, and that auth headers or cookies are attached.
- Validate the Content-Type header is application/json before parsing.