Unexpected token <, <!DOCTYPE is not valid JSON: the server returned HTML
The error means one thing: the first character of the response was <, so the server sent HTML. What is left is to find out which page and why.
Five common causes
A wrong URL: a typo or an extra or missing /api, and the server returned a 404 page. The session expired and the request was redirected to a login page. A proxy or load balancer answered with its own 502 or 504 error page. The frontend server returns index.html for any unknown path, and the API request reached it instead of the backend. The application itself crashed and sent an HTML error page instead of JSON.
How to see what actually arrived
Run the request with -i: curl shows the status code and headers, including Content-Type. If it says text/html, look at the status. 404 means a wrong URL, 401 or a redirect to a login page points to authorization, and 502 or 504 point to a proxy or a crashed service.
curl -i https://api.example.com/api/orders/42How to protect code and tests
Check the status code and Content-Type before parsing JSON. In an automated test, make them separate assertions: then the report says a 404 text/html arrived rather than that the JSON is invalid. In Checkcraft these are rules on the status code and header, next to the field checks.
const response = await fetch('/api/orders/42');
const type = response.headers.get('content-type') || '';
if (!response.ok || !type.includes('application/json')) {
const text = await response.text();
throw new Error(`HTTP ${response.status}, ${type}: ${text.slice(0, 200)}`);
}
const order = await response.json();Repeat this on your own API
Checkcraft is a desktop app that saves API response checks without code and shows what did not match. Start with a sample, then use your own sanitized data. Free runs on Windows and Linux with no time limit.
Download FreeDownload and first runNo sign-up or email needed, the archive is ready in a couple of minutes. See the edition limits.
References
Start with the linked example and compare its result with your own test requirement.