How Axios Handles Unexpected HTML Error Pages
When consuming REST APIs, clients typically expect JSON responses. However, web servers, reverse proxies, and firewalls often return HTML error pages (such as 404, 502, or 504 status pages) during outages, route misconfigurations, or authentication redirects. This article explains how the Axios HTTP client processes unexpected HTML responses when expecting JSON, what happens behind the scenes, and how to handle these scenarios reliably in your application.
Default Axios Response Parsing
By default, Axios sets the responseType configuration to
'json'. Under the hood, Axios uses a default response
transformer that attempts to parse incoming response data using
JSON.parse().
If the server responds with an HTML payload, the behavior depends on the HTTP status code:
- Error Status Codes (4xx / 5xx): By default, Axios
rejects promises for any status code outside the 2xx range. The
resulting error object contains an
error.responseproperty. Because the payload is HTML, the default transformer fails to parse it as JSON and falls back to returning the raw HTML string insideerror.response.data. - Success Status Codes (200 OK): Some servers,
proxies, or captive portals return an HTML page with a
200 OKstatus (such as a login redirect or single-page app fallback). In this scenario, Axios resolves the promise successfully. However, becauseJSON.parse()fails silently inside Axios's default transformer,response.datais returned as a plain HTML string rather than a JavaScript object.
Common Causes of HTML Responses
- Reverse Proxy Errors: Cloudflare, Nginx, or AWS ALBs returning standard 502 Bad Gateway or 504 Gateway Timeout HTML pages before the request reaches the application server.
- Single Page Application (SPA) Fallbacks: A server
routing non-existent API paths to
index.htmlwith a 200 status code. - Authentication Gateways: Corporate firewalls or captive Wi-Fi portals intercepting API requests and serving HTML login forms.
Detecting and Handling HTML Responses
To prevent application crashes when expecting structured JSON data, implement safeguards using response headers or global interceptors.
1. Checking the Content-Type Header
Verify that the content-type header matches
application/json before processing data:
axios.get('/api/data')
.then(response => {
const contentType = response.headers['content-type'];
if (!contentType || !contentType.includes('application/json')) {
throw new Error('Received non-JSON response from server.');
}
// Safe to use response.data as JSON
})
.catch(error => {
if (error.response) {
console.error(`Status: ${error.response.status}`);
console.error('Payload:', error.response.data);
}
});2. Global Handling via Axios Interceptors
You can implement an Axios response interceptor to validate content types across all requests globally and normalize error reporting:
axios.interceptors.response.use(
(response) => {
const contentType = response.headers['content-type'] || '';
if (typeof response.data === 'string' && contentType.includes('text/html')) {
return Promise.reject(new Error('Unexpected HTML response received.'));
}
return response;
},
(error) => {
if (error.response && typeof error.response.data === 'string') {
if (error.response.data.trim().startsWith('<!DOCTYPE html>') || error.response.data.includes('<html')) {
error.message = `Server returned an HTML error page with status ${error.response.status}`;
}
}
return Promise.reject(error);
}
);By inspecting the response content type and payload structure, you can gracefully handle HTML responses and avoid runtime errors caused by unexpected data types.