Comparing working with JSON using the XHR and the Fetch API


Nowadays, JavaScript is often used to make Ajax requests. There are a lot of libraries that can do that for us, for example, axios or jQuery. Both of them use XMLHttpRequest (XHR). It differs from the relatively new Fetch API that was introduced a few years ago. This article explains both of them and points out their differences.


Even though people used some tricks to create sites that fetch additional data before XMLHttpRequest, the introduction of XHR was quite a milestone in the history of web development. Despite its name, XHR can be used to fetch data in a form other than XML: JSON, HTML or plain text. Let’s make a request like that to better understand what is happening inside of libraries that we use.

Using XMLHttpRequest

The first thing to do is to create an instance of an XMLHttpRequest object.

Once you have it, you can initialize a request. To do this. you use the open function. Its essential arguments are the HTTP request method and the URL.

If you wish to append some headers to your request, call the setRequestHeader after executing the open function. You should do that to indicate that you are actually sending JSON and not a plain text.

Once that is done, you can use the send function. If you are using, for example, the POST method and you want to send some data, you need to put it into the argument of the send function. We use it here to send stringified JSON, but it accepts quite a few types of data. For more information check the MDN documentation.

After executing this lines of code, you can observe a new request being sent out.

The XMLHttpRequest.prototype inherits from the EventTarget.prototype. Thanks to that, you can use the addEventListener function and listen for the load event that fires when the transfer is complete.

If you want to know more about prototypes, check out Prototype. The big bro behind ES6 class

As you can see, such requests are asynchronous by default. You can actually change that by providing a third argument to the open function. If you set it to false, the send function does not return until the request finishes. Synchronous requests are basically a bad idea because will make your main thread busy and block your user interface.

If you want to read about threads in JavaScript, look into When async is just not enough. An introduction to multithreading in the browser

Using promises

Thanks to the load event we can provide a callback to our request. Another useful event is the error. What if we grew accustomed to promises? No worries, we can easily create a function that returns a promise when using XHR.

Looks pretty similar to the usage of libraries we deal with on a daily basis, doesn’t it?

If you wish to know more about promises, check out Explaining promises and callbacks while implementing a sorting algorithm

Fetch API

Fetch API is a new standard allowing you to make network requests in a similar manner to the XHR. The first difference that you see is that Fetch API uses promises.

That’s it! A request is made. As you can see, the JSON needs to be stringified also, and the headers should indicate the format. When the request succeeds, the promise will be resolved. There is the first gotcha, though! According to the MDN:

The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.

In other words, even if the server responds in with a non-ok status, the request is treated as completed, and therefore successful. The promise is resolved.

The callback you provide to the then function is given an instance of the Response object. It has a set of properties that you can use to further handle the response of your request. You can check the ok boolean property to make sure that the request succeeded. Another important property is the json function. It returns a promise with the response body as JSON.

With the Response object, you can handle more than just JSON. For a list of the possible functions, check out the MDN documentation.


Fetch does not use cookies by default. To do that, you need to set the credentials option. There are a few possibilities:

  • include
    causes the browser to send cookies even for a cross-origin call
  • same-origin
    cookies are sent only if the request URL is on the same origin
  • omit
    the browser does not send cookies at all

It differs from the XMLHttpRequest, where a default behavior is to send cookies if the origin matches current URL. You can send cookies with the cross-origin call using the withCredentials flag, but you can’t exclude them for all types of requests (aside from using the non-standard mozAnon flag).

If you would like to know more about cookies, you might be interested in Cookies: explaining document.cookie and the Set-Cookie header


In this article, you got to know both the XMLHttpRequest and the Fetch API. It included a quick tutorial on how to use both of them and points out their main differences. Thanks to the knowledge on how the XMLHttpRequest works, you can understand better what happens under the hood of libraries like axios. The explanation of the Fetch API included some pitfalls that you might stumble upon when using it. This will help you write less buggy and cleaner code.

Notify of
1 Comment
Newest Most Voted
Inline Feedbacks
View all comments
11 months ago

Thanks for sharing! What about JSONP? It’s way simpler and cooler.