What is the difference between XMLHttpRequest and fetch?

JavaScript

The short answer

Both make HTTP requests from the browser, but fetch is the modern replacement. fetch uses promises (cleaner syntax), has a simpler API, and supports streaming. XMLHttpRequest uses callbacks, is more verbose, but supports upload progress events and request cancellation (without AbortController). Use fetch for everything unless you specifically need XHR features.

fetch — the modern way

const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John' }),
});
const data = await response.json();

XMLHttpRequest — the old way

const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/users');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
const data = JSON.parse(xhr.responseText);
};
xhr.onerror = function () {
console.log('Error');
};
xhr.send(JSON.stringify({ name: 'John' }));

Key differences

FeaturefetchXMLHttpRequest
SyntaxPromise-basedCallback-based
Response handling.json(), .text(), .blob()Manual parsing
Error handling.catch() or try/catchonerror callback
StreamingYes (ReadableStream)No
Upload progressNo (need XMLHttpRequest)Yes (xhr.upload.onprogress)
CancellationAbortControllerxhr.abort()
CookiesNot sent by default (credentials)Sent by default
HTTP errorsDoes not reject on 404/500Triggers onload for all HTTP responses

When XHR is still useful

The main reason to use XMLHttpRequest today is upload progress:

const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
const percent = (event.loaded / event.total) * 100;
console.log(`${percent}% uploaded`);
});

fetch does not have a built-in way to track upload progress (though you can track download progress with ReadableStream).

The fetch gotcha

fetch does not reject on HTTP errors like 404 or 500:

// This does NOT throw for 404
const response = await fetch('/not-found');
response.ok; // false
response.status; // 404
// You need to check manually
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}

Interview Tip

Show both APIs with the same request to highlight the difference in verbosity. Mention the response.ok gotcha with fetch — this is a common interview follow-up. Knowing that XHR is still useful for upload progress shows you have real experience with file uploads.

Why interviewers ask this

This tests your knowledge of browser APIs and web development history. Interviewers want to see if you know the modern approach (fetch) and understand its limitations compared to the older API.