SyntaxError: Unexpected token < in JSON at position 0
JSON.parse() / response.json() received something that isn’t JSON — very often an HTML error page.
Meaning
The < at position 0 is the start of <!DOCTYPE html> or <html>: the server returned an HTML page (404, 500, login redirect, SPA fallback) where your code expected JSON. Newer browsers say “Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON”.
Common causes
- Wrong API URL — the request hits the frontend’s index.html fallback
- Server error returned an HTML error page (500, 502, 404)
- Authentication redirect to a login page
- Dev server not proxying
/apito the backend - PHP warnings/notices printed before the JSON output
- Empty response body (“Unexpected end of JSON input”)
⚡ Quick fix
- Log
await res.text()instead ofres.json()to see what actually came back - Check
res.okandContent-Typebefore parsing - Verify the full request URL in the Network tab
- Turn off
display_errorsin production PHP so warnings don’t corrupt JSON
Detailed fix by platform
JavaScript
- Parse defensively:javascript
const res = await fetch('/api/items'); const type = res.headers.get('content-type') || ''; if (!res.ok || !type.includes('application/json')) { throw new Error(`Expected JSON, got ${res.status} ${type}: ${(await res.text()).slice(0, 200)}`); } const data = await res.json();
PHP
- Send
header('Content-Type: application/json'), echo onlyjson_encode(...), and make sure no whitespace/BOM or warnings are printed before it.
React
- Vite: add
server: { proxy: { '/api': 'http://localhost:8000' } }so API calls don’t hit index.html.
How to diagnose
- Raw body — What does res.text() contain?
- Status — Is it a 4xx/5xx/3xx?
- URL — Is the path/host correct?
- Server output — Any warnings printed before JSON?
🧠 Still stuck? Analyze your error
Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.
Was this page helpful?
Report a correction or suggest an improvement
Last updated 2 Oct 2026