ERROR - Updated 2026-06-25
Unexpected token < in JSON at position 0
Why Unexpected token < in JSON at position 0 usually means your API returned HTML, not JSON, and how to debug it.
Open JSON Formatter & Error CheckerQuick Answer
Unexpected token < in JSON at position 0 usually means the response starts with <, so the parser is seeing HTML instead of JSON. Common causes include a 404 page, a login page, a server error page, or a development proxy returning the front-end app. Debug the HTTP response before changing JSON syntax.
Why This Matters
This error is one of the most common API debugging traps. The JSON parser is not telling you that < belongs in your JSON. It is telling you that the first character of the response is not JSON at all.
Common Causes
| Response Starts With | Likely Cause | Check |
|---|---|---|
<!doctype html> | HTML page returned | Request URL |
<html> login page | Auth expired | Cookies, token, redirect |
| 404 HTML | Missing route | API path and base URL |
| 500 HTML | Server error page | Server logs |
| Front-end app HTML | Proxy fallback | Dev server or rewrite config |
Practical Workflow
- Open the failed request in the browser Network tab.
- Check status code and Request URL.
- Check the
Content-Typeheader. - Copy the response body and inspect the first 200 characters.
- Use JSON Error Doctor only after confirming the body is meant to be JSON.
API Response Checklist
| Check | Good sign | Warning sign |
|---|---|---|
| Request URL | It hits the intended API endpoint. | It returns the app shell, login page, or documentation page. |
| Status code | 2xx status with expected body shape. | 3xx redirect, 401, 403, 404, or 500 HTML response. |
| Content-Type | application/json or a documented JSON media type. | text/html, text/plain, or missing header. |
| First characters | { or [ for most API JSON bodies. | <!doctype html>, <html>, Error, or a framework page. |
| Parser call | response.json() after response checks. | Blind response.json() before checking response.ok. |
Example
const response = await fetch("/api/profile");
const text = await response.text();
console.log(response.status, response.headers.get("content-type"), text.slice(0, 200));
If text starts with HTML, fix routing, authentication, or server error handling. Do not try to "repair" the HTML as JSON.
Common Mistakes
- Calling
response.json()without checking status code. - Missing a base URL difference between local and production.
- Treating a login redirect as a successful API response.
- Assuming HTTP 200 always means JSON.
Practical FAQ
Is Unexpected token < a JSON syntax problem?
Usually no. The < character normally points to HTML, so the first task is to find why the API returned a page instead of JSON.
Why does this happen only in production?
Production may use a different base URL, rewrite rule, authentication cookie, CORS path, or proxy target. Compare the full request URL and response headers between local and production.
Should I call response.text() or response.json() while debugging?
Use response.text() temporarily when the body is suspicious. It lets you inspect the raw response before deciding whether JSON parsing is appropriate.
Can HTTP 200 still return HTML?
Yes. Some login pages, app shells, proxy fallbacks, and CDN error pages can return a 200 status with HTML. Check Content-Type and the first characters, not status alone.
What should the server return for API errors?
For JSON APIs, return a clear status code and a JSON error body. Avoid silently redirecting API clients to HTML login pages when they expect machine-readable JSON.
Related Tool
Related Article
Updated
2026-06-25
Official references
These official references were used to verify the criteria discussed in this article.
- Response: json() methodMDN Web Docs - Checked: 2026-06-25
- Response: text() methodMDN Web Docs - Checked: 2026-06-25
- SyntaxError: JSON.parse: bad parsingMDN Web Docs - Checked: 2026-06-25