Fix SyntaxError Unexpected token < — Handle Non-JSON API Responses





Fix SyntaxError Unexpected token < — Handle Non-JSON API Responses



Fix SyntaxError Unexpected token < — Handle Non-JSON API Responses

Quick answer: "SyntaxError: Unexpected token <" usually means your code tried to parse JSON but the API returned HTML (often an error/HTML error page). Stop parsing immediately, inspect the raw response and Content-Type, and add defensive parsing logic in your fetch/HTTP client so HTML or plain text won't break the parser.

Why you see 'SyntaxError: Unexpected token <'

The parser error occurs when JSON.parse (or response.json() in fetch) receives text that starts with '<' — the typical beginning of an HTML document. This often happens when the backend returns an HTML error page (500, 502, 503), an authentication redirect (login HTML), or a maintenance page instead of application/json.

Another common cause is a Content-Type header mismatch. The server may send JSON payload but omit or mislabel the "Content-Type: application/json" header, or vice versa: the server responds with HTML but declares application/json. Client libraries often try to parse based on expected content rather than actual payload, causing the exception.

Network middlemen (proxies, CDN, load balancers) and offline backend processes can also inject HTML. For example, an API gateway might return a captive-page or CDN error HTML when the origin is down. So the root cause can be backend, network, or even client assumptions about the response.

Step-by-step triage checklist (quick, practical)

Start by capturing the raw HTTP response. Use your browser devtools, curl -i, or a proxy (like Charles or Fiddler) to see status, headers, and response body in plain text. Don't rely on response.json() yet — it will throw and hide the real payload.

Next, inspect the Content-Type and HTTP status code. A correct JSON API should respond with status 200/2xx and "Content-Type: application/json; charset=utf-8". If you see text/html or an error code (4xx, 5xx), treat it as non-JSON and handle accordingly.

Then, reproduce the request from a terminal: curl -i "https://api.example.com/endpoint". Look for redirects, HTML bodies, or gateway pages. If you find HTML error pages, trace them back to the server logs or the upstream gateway that generated them.

  • Capture raw response (browser devtools / curl).
  • Check status code and Content-Type header.
  • Log response body before parsing; handle non-JSON gracefully.

Defensive parsing patterns for JavaScript (fetch) and examples

Never call response.json() blindly. Instead, inspect the response headers and optionally read as text first so you can decide how to parse. Below is a robust fetch pattern that safely handles non-JSON responses, HTML error pages, and empty bodies.

// Safe fetch + JSON parsing with fallback
async function safeFetchJson(url, options = {}) {
  const res = await fetch(url, options);
  const contentType = res.headers.get('content-type') || '';

  // Prefer text so we can inspect raw payload on errors
  const raw = await res.text();

  // Quick guard: empty body
  if (!raw) {
    throw new Error(`Empty response (status ${res.status})`);
  }

  // If server claims JSON, attempt parse; otherwise detect HTML
  if (contentType.includes('application/json') || raw.trim().startsWith('{') || raw.trim().startsWith('[')) {
    try {
      return JSON.parse(raw);
    } catch (err) {
      throw new Error(`JSON parse error: ${err.message}; raw: ${raw.slice(0,200)}`);
    }
  }

  // Detect HTML (common cause of Unexpected token <)
  if (raw.trim().startsWith('<')) {
    // Attach useful debugging details
    const snippet = raw.slice(0,120);
    throw new Error(`API returns HTML error page (status ${res.status}). Response starts with '<'. Snippet: ${snippet}`);
  }

  // Fallback: try parsing anyway, or return text
  try {
    return JSON.parse(raw);
  } catch {
    // If you want plain text instead of throwing
    return { text: raw, status: res.status, contentType };
  }
}

The code above ensures you get the raw response, protects against the SyntaxError Unexpected token <, and surfaces helpful debugging snippets. It also allows you to handle 204 No Content and other non-JSON endpoints gracefully.

For axios users, responseType and validateStatus can be used similarly. Set responseType: 'text' to inspect raw data, check headers via response.headers['content-type'], and only then JSON.parse(response.data) with try/catch.

Backend fixes and Content-Type discipline

The long-term fix is consistent API behavior: return JSON for API endpoints, set Content-Type to application/json, and use correct HTTP status codes for errors. Ensure error handlers emit JSON payloads (e.g., {"error":"service unavailable","code":503}) instead of HTML templates.

When your backend becomes unavailable, configure your gateway or CDN to pass through the origin's JSON error or to return JSON itself. Avoid default HTML error pages from layers above your app because they break clients that expect JSON.

Also add health-check endpoints and monitoring so you can detect when a service returns HTML or mislabels content. Automated alerts that flag "content-type not application/json" are helpful in catching regressions early.

Common edge cases and troubleshooting tips

Redirects for authentication can return HTML login pages. If your API call is redirected to an OAuth/login page (status 302 -> HTML), you will see Unexpected token <. Inspect network traces to see if you're being redirected by a proxy or auth server and handle auth flows properly.

Proxies, CDNs, or WAFs can inject HTML. If an upstream component injects a "service unavailable" HTML page, the client will choke. Test with curl directly to the origin or bypass the CDN to narrow down where the HTML is injected.

If your API returned an HTML error page, capture that page and link it to backend logs. For example, a hosted HTML error page might live at the exact URL returned by the service — you can examine it to see whether the error came from your application or an intermediate layer. (If you need to inspect a concrete example, check this HTML error page: API returns HTML error page.)

Semantic core (keyword clusters)

Primary queries:

  • SyntaxError Unexpected token <
  • handling non-JSON responses
  • JSON parsing error
  • API returns HTML error page
  • error handling in JavaScript fetch

Secondary & clarifying queries (LSI, synonyms, related formulations):

  • check Content-Type header
  • backend API offline error
  • API response error troubleshooting
  • response.json() throws
  • detect HTML instead of JSON
  • axios parse html error
  • how to handle non-json responses in fetch
  • prevent SyntaxError Unexpected token

FAQ

1. How do I fix "SyntaxError: Unexpected token <"?

Check the raw HTTP response and headers (via browser devtools or curl -i). If the body starts with '<', the server returned HTML. Look at the status code and Content-Type header. Fix on client side by reading as text first and only parsing JSON after verifying content-type or that the body starts with '{' or '['; fix on server side by returning application/json for API endpoints and JSON-formatted errors.

2. How can I handle non-JSON responses when using fetch?

Use response.text() to get raw body, inspect content-type (res.headers.get('content-type')) and the first characters. Attempt JSON.parse() inside try/catch only when content-type indicates JSON or raw begins with '{' or '['. Fallback to returning text or creating a structured error containing the snippet for debugging.

3. What should I check if an API returns an HTML error page?

Verify the origin server, gateway, and CDN. Confirm whether a proxy or authentication redirect injected the HTML. Reproduce the request with curl -i to see exact headers and body. Then fix the backend to emit JSON or configure the intermediary to pass through JSON error responses.

Useful references and backlinks

- MDN fetch documentation: Fetch API guide (useful for headers and response handling).

- Content-Type details and best practices: Content-Type header docs.

- Example HTML error page (inspect to reproduce the "Unexpected token <" case): API returns HTML error page.