XMLHttpRequest (XHR) is a JavaScript object used to exchange data between a web browser and a server. It allows a web page to update content dynamically without requiring a full page refresh. This technology enables faster, more interactive user experiences by letting scripts perform background data tasks while the user remains on the page.
What is XMLHttpRequest?
XMLHttpRequest is the core API behind AJAX (Asynchronous JavaScript and XML) programming. Despite its name, it can transfer any type of data, including JSON, HTML, and plain text, not just XML.
The standard is [well established and available across browsers since July 2015] (MDN). Historically, [Internet Explorer 5 implemented the concept in 1999] (Wikipedia) using ActiveX. Other browsers followed with native support: [Gecko engine provided support in 2002] (Wikipedia), [Safari 1.2 featured support in 2004] (Wikipedia), and [Opera 8.0 support arrived in 2005] (Wikipedia).
Development of the specification has moved across several bodies. The W3C [original Working Draft published on April 5, 2006] (Wikipedia), followed by a [Level 2 Working Draft released on February 25, 2008] (Wikipedia). These were [merged as a single entity from a standards perspective at the end of 2011] (XMLHttpRequest Standard).
Why XMLHttpRequest matters
XHR makes modern web applications possible by handling data silently in the background.
- Improved User Experience: Users can interact with a page while it loads new data, preventing the "flicker" of full page reloads.
- Reduced Bandwidth: Since the browser only requests the specific data it needs, it avoids re-downloading the entire page layout and assets.
- Real-time Updates: Sites can display new notifications, search suggestions, or live data feeds without user intervention.
- Background Actions: You can log user behavior or send analytics data to a server without interrupting the current session.
How XMLHttpRequest works
Using XHR involves a specific sequence of steps to establish a connection and handle the data returned by the server.
- Initialize: Create the object using the
new XMLHttpRequest()constructor. - Open: Use the
open()method to set the HTTP method (like GET or POST) and the target URL. - Set Listeners: Define a function to handle the response. You can listen for the
onreadystatechangeevent or specific progress events likeonload. - Send: Call the
send()method. For asynchronous requests (the default), the script continues running while the request processes. - Process Response: The server returns data in properties like
responseTextorresponseXML. You check thestatusandreadyStateto ensure the request finished successfully before using the data.
Types of requests
Requests are defined by how they interact with the browser's main window.
| Type | Key Characteristics | When to Use |
|---|---|---|
| Asynchronous | Does not block the browser; user can continue clicking and scrolling. | Default choice for almost all scenarios. |
| Synchronous | Freezes the browser interface until the response arrives. | Avoid this; it is being removed from the platform due to poor UX. |
Best practices
- Always use asynchronous requests: Synchronous requests outside of web workers freeze the main interface and frustrate users.
- Listen to events before opening: Add your event listeners for
progress,load, orerrorbefore calling the.open()method to ensure no events are missed. - Handle errors gracefully: Use the
onerrorevent to provide feedback to the user if the network fails or the server is down. - Bypass the cache when needed: If you need the most recent data, append a unique timestamp to your URL (e.g.,
url?t=123456) to force a fresh request. - Use the correct responseType: Tell the browser if you expect a "blob", "json", or "document" to avoid manual parsing later.
Common mistakes
- Mistake: Forgetting that
readyStatechanges multiple times.
Fix: Always verifyreadyState == 4(Done) andstatus == 200(OK) before processing data. - Mistake: Using XHR for full-duplex messaging.
Fix: Use WebSockets if you need constant two-way communication. - Mistake: Violating the Same Origin Policy.
Fix: Ensure the server is configured with CORS (Cross-Origin Resource Sharing) headers to allow requests from different domains. - Mistake: Initializing headers at the wrong time.
Fix: You must callsetRequestHeader()afteropen()but beforesend().
Examples
Example scenario: Providing search suggestions When a user types into an input field, the browser sends an XHR to a search API. The server returns a list of names, which the script then displays in a dropdown without reloading the page.
Example scenario: Logging errors
A script can use XHR to send a POST request with error details to /log every time a JavaScript error occurs on the client side.
XMLHttpRequest vs Fetch
| Goal | XMLHttpRequest | Fetch API |
|---|---|---|
| Syntax | Callback-based (older) | Promise-based (modern) |
| Progress monitoring | Built-in via the upload and progress events |
Not natively simple for request bodies |
| Complexity | Requires more lines of code and state checking | Cleaner, more readable code |
| Timing out | Has a built-in timeout property |
Requires an AbortController |
Rule of Thumb: Use fetch() for most modern projects, but keep XHR for legacy browser support or when you need detailed upload progress monitoring.
FAQ
What does the name XMLHttpRequest stand for? The name is historical. While it was originally designed for XML data transfer, it now handles many formats. The identifier was [standardized in IE7 in 2006] (Wikipedia), replacing earlier ActiveX versions.
Can I request data from a different domain? Yes, but only if the server allows it via Cross-Origin Resource Sharing (CORS). Without CORS, the browser's Same Origin Policy will stop the request from completing.
Does XHR work with files?
Yes, XHR can send and receive binary data using Blob or ArrayBuffer objects. However, progress events are not available when using the file: protocol.
What is the difference between responseText and responseXML?
responseText returns the data as a raw string. responseXML attempts to parse the data into a DOM object you can navigate like an HTML document.
Why did my request return status 0? A status of 0 usually means the request was "UNSENT" or blocked. Common causes include changing the page origin before the request finishes or a network error.