jsonerrorsdebuggingfetchapi

Unexpected Token < in JSON at Position 0 — Fixed

·6 min read

What Does "Unexpected token < in JSON at position 0" Mean?

This error means JSON.parse() tried to parse a string that starts with `<` — which is an HTML tag, not JSON. Your code expected a JSON response but received an HTML page instead.

SyntaxError: Unexpected token < in JSON at position 0

The `<` at position 0 is almost always the `<` from an HTML `<!DOCTYPE html>` declaration or an `<html>` tag.

Why Does This Happen?

Cause 1: The server returned an error page

Your API returned a 404 Not Found, 500 Internal Server Error, or 401 Unauthorized HTML error page instead of JSON. Many web servers and frameworks serve HTML error pages by default even when the client expects JSON.

Cause 2: Wrong API URL

The endpoint URL is wrong. You hit a web page instead of the API route. The server returns the webpage HTML, and your code tries to parse it as JSON.

Cause 3: Redirect to login page

You made an authenticated API request but your session expired. The server redirects to a login page (HTML), and your fetch follows the redirect and gets HTML back.

Cause 4: Proxy or CDN returning its own error page

A Cloudflare, Nginx, or load balancer error page is returned instead of your API response.

Cause 5: Development server misconfiguration

In local development, the API proxy is misconfigured. Requests that should go to your backend hit the frontend server instead, which returns the HTML index page.

How to Diagnose

Open the browser Network tab (F12 > Network). Find the failing request. Click it and check:

  • Status code — is it 404, 500, 302, or 200?
  • Response tab — do you see HTML? Copy it and paste it into your browser to see what page it is.
  • URL — is the request going to the right endpoint?

Fix 1: Check response.ok Before Parsing

Always check the HTTP status before calling .json():

javascript
const response = await fetch('/api/users');

if (!response.ok) {
  const text = await response.text(); // read as text, not JSON
  console.error('Server returned:', response.status, text);
  throw new Error(`HTTP error ${response.status}`);
}

const data = await response.json();

This gives you the actual HTML error page in the console so you know exactly what went wrong.

Fix 2: Always Set the Accept Header

Tell the server you expect JSON, not HTML:

javascript
const response = await fetch('/api/users', {
  headers: {
    'Accept': 'application/json',
  },
});

Many Express and Django apps will return a JSON error response (instead of HTML) when the request has `Accept: application/json`.

Fix 3: Correct the API URL

Double-check the URL. Common mistakes:

  • Missing the `/api` prefix — `/users` instead of `/api/users`
  • Wrong port — `http://localhost:3000` instead of `http://localhost:8000`
  • Extra slash or typo in the path

Fix 4: Handle Authentication Redirects

If the error only happens after login expires, catch 401 and redirect to login:

javascript
const response = await fetch('/api/data', {
  credentials: 'include', // send cookies
});

if (response.status === 401) {
  window.location.href = '/login';
  return;
}

const data = await response.json();

Fix 5: Use a Safe JSON Parse Wrapper

Wrap JSON parsing to catch and log the raw text when it fails:

javascript
async function fetchJSON(url, options) {
  const response = await fetch(url, options);
  const text = await response.text();
  try {
    return JSON.parse(text);
  } catch {
    console.error('JSON parse failed. Raw response:', text.slice(0, 500));
    throw new Error(`Server returned non-JSON response (status ${response.status})`);
  }
}

Quick Checklist

  • Open Network tab, check the response body — is it HTML?
  • Check the status code — 404, 500, or 302 all indicate a problem before parsing
  • Verify the URL is exactly correct
  • Add `Accept: application/json` to your request headers
  • Always check `response.ok` before calling `.json()`

Use JSONKit's JSON Validator at /json-validator to confirm your JSON is valid before sending it, and to inspect any JSON response you receive.

Try JSON Validator

Paste your JSON to pinpoint the unexpected token and fix it instantly.