top of page

How to make HTTP Request in JavaScript in 5 different ways

Updated: Jun 2, 2023

In JavaScript, there are several ways to make HTTP requests to remote servers. These options range from native solutions like the XMLHttpRequest object to third-party libraries such as Axios. Having a diverse set of choices has made requesting and dynamically loading content in web applications easier than ever before.


In this article, we will guide you on how to make HTTP request in JavaScript in 5 different ways.

how to make HTTP request in JavaScript in 5 different ways


What is an HTTP request in JavaScript?

An HTTP request is a mechanism used to communicate with a remote server and retrieve data or perform actions. It allows JavaScript code running in a web browser or a server-side environment like Node.js to interact with web servers and exchange information.


An HTTP request typically consists of two parts: the request method and the request URL. The request method defines the action to be performed on the server, such as retrieving data (GET), submitting data (POST), updating data (PUT/PATCH), or deleting data (DELETE). The requested URL specifies the location of the server and the specific resource or endpoint to interact with.


When sending an HTTP request in JavaScript, you typically use one of the available APIs or libraries that provide convenient methods for creating and sending requests. These APIs include the native XMLHttpRequest object, the newer Fetch API, or third-party libraries like Axios, SuperAgent, or Ky.


Once the request is sent to the server, it processes the request and generates an appropriate response. The response typically includes a status code indicating the outcome of the request (e.g., 200 for success, 404 for not found), along with the requested data or any error messages.


How to make HTTP Request in JavaScript?

Below we have different methods to make HTTP requests in JavaScript. We will start with the native options provided by the language and then delve into the following five modules, each offering its own approach for sending HTTP requests:

  1. XMLHttpRequest: This is a built-in browser object that allows you to send HTTP requests and handle responses asynchronously. It has been the traditional method for making AJAX requests in JavaScript.

  2. Fetch: Fetch is a newer and more modern API for making HTTP requests. It provides a simpler and more powerful interface compared to XMLHttpRequest, making it widely adopted in modern web development.

  3. Axios: Axios is a popular third-party library that provides a simple and elegant API for making HTTP requests from both browsers and Node.js. It supports features like request and response interception, automatic JSON parsing, and more.

  4. SuperAgent: SuperAgent is another widely used third-party library that offers a high-level API for making HTTP requests. It provides features like request and response serialization, automatic retries, and a fluent interface for building complex requests.

  5. Ky: Ky is a lightweight and modern HTTP client library that focuses on simplicity and ease of use. It offers a concise API and supports features like JSON parsing, request cancellation, and timeout handling.


1. XMLHttpRequest

XMLHttpRequest is a native JavaScript API that allows you to send HTTP requests asynchronously without having to refresh the entire web page. It has been the foundation for many popular HTTP request modules and is still useful for handling unique use cases.


Here's an example of how to send a GET request and retrieve data asynchronously from a remote API using the XMLHttpRequest API:

//create XMLHttpRequest object 
const xhr = new XMLHttpRequest();
 
//open a get request with the remote server URL 
xhr.open("GET", "https://world.openfoodfacts.org/category/pastas/1.json"); 

//send the Http request 
xhr.send();  

//EVENT HANDLERS 

//triggered when the response is completed 
xhr.onload = function() {   
    if (xhr.status === 200) {     
        //parse JSON datax`x     
        data = JSON.parse(xhr.responseText);     
        console.log(data.count);     
        console.log(data.products);   
    } else if (xhr.status === 404) {     
        console.log("No records found");   
    } 
};  

//triggered when a network-level error occurs with the request 
xhr.onerror = function() {   
    console.log("Network error occurred"); 
}  

//triggered periodically as the client receives data 
//used to monitor the progress of the request 
xhr.onprogress = function(e) {   
    if (e.lengthComputable) {     
        console.log(`${e.loaded} B of ${e.total} B loaded!`);   
    } else {     
        console.log(`${e.loaded} B loaded!`);   
    } 
}; 

In this example, we create an XMLHttpRequest object, open a GET request to the desired URL, and send the request. We use event handlers like onload, onerror, and onprogress to handle the response and track the progress of the request.


To send a POST request, we follow a similar pattern:

// create XMLHttpRequest object 
const xhr = new XMLHttpRequest();
 
// open a POST request 
xhr.open("POST", "/food"); 

// set content-type header to JSON 
xhr.setRequestHeader("Content-Type", "application/json"); 

// send JSON data to the remote server 
xhr.send(JSON.stringify(food));  

// Event Handlers 

// track data upload progress 
xhr.upload.onprogress = function(e) {   
    console.log(`${e.loaded}B of ${e.total}B uploaded!`); 
};  

// triggered when data upload is finished 
xhr.upload.onload = function(e) {   
    console.log("Upload completed"); 
};  

// triggered when the response is fully received 
xhr.onload = function() {   
    console.log(xhr.status); 
};  

// triggered due to a network-level error 
xhr.onerror = function() {   
    console.log("Network error occurred"); 
}; 

For a POST request, we set the appropriate headers, such as the content-type header, and send JSON data using JSON.stringify(). We can also utilize the upload events available through the xhr.upload field to track data upload progress.


Pros of XMLHttpRequest

  • Native support in all modern browser versions.

  • No external dependencies required.

  • Allows low-level access and manipulation of asynchronous HTTP requests.


Cons of XMLHttpRequest

  • Verbose and lengthy code.

  • Lacks support for modern syntax like async/await or promises.

  • Many newer HTTP request packages provide simpler abstractions over the complex XMLHttpRequest API.


2. Fetch

Fetch is a modern native JavaScript API that simplifies making HTTP requests. It provides built-in support for promises and offers a more concise syntax compared to XMLHttpRequest. Fetch has gained popularity as one of the preferred methods for sending HTTP requests in JavaScript.


Using a promise-based syntax, we can utilize Fetch to send HTTP requests from the client-side, as demonstrated in the example below:

fetch("https://world.openfoodfacts.org/category/pastas/1.json")   
    .then(response => {     
        // indicates whether the response is successful (status code 
        200-299) or not     
        if (!response.ok) {       
            throw new Error(`Request failed with status');
        }
        return reponse.json();
    })                                                     
    .then(data => {     
        console.log(data.count);     
        console.log(data.products);  
    })   
    .catch(error => console.log(error)); 

Fetch simplifies the code by leveraging promises and providing a cleaner syntax. In this example, we use the response.ok field to check if the response contains an HTTP error. Errors caught in the catch block typically relate to network-level errors rather than application-level errors.


The fetch function accepts a configuration object as the second parameter, allowing easy manipulation of HTTP fields like headers, request method, content types, etc. For a complete list of configuration options supported by Fetch, refer to the official documentation.


Making POST requests with Fetch follows a similar pattern. We utilize the configuration object to specify the request method and include the data to be posted.


Here's an example using async/await:

async function postData () {   
    const food = {     
        name: "Bread",     
        weight: 450,     
        quantity: 3   
    };    
    
    const response = await fetch("/food", {     
        method: "POST",     
        body: JSON.stringify(food),     
        headers: {       
            "Content-Type": "application/json"    
        }   
    });    
    
    if (!response.ok) {     
      throw new Error(`Request failed with status ${reponse.status}`)       
    }  
    console.log("Request successful!"); 
} 


Pros of Fetch

  • Provides a simplified and native way to make HTTP requests in JavaScript.

  • Easy to learn and use for developers of any level.

  • Supports promise-based implementation, resulting in cleaner and more concise code.

  • Offers additional features compared to XMLHttpRequest, such as integration with the native Cache API and the ability to send no-cors requests.


Cons of Fetch

  • Lacks certain features supported by XMLHttpRequest, such as request aborting and progress monitoring. (However, Fetch allows the use of a separate AbortController object for controlling request aborts and timeouts.)

  • Considers a response as valid even when an HTTP error occurs. We need to manually check for HTTP errors and handle them.

  • Not compatible with Internet Explorer, although this is generally not a significant concern anymore.


3. Axios

Axios is a widely used third-party package for making HTTP requests in JavaScript. It utilizes the native XMLHttpRequest API in the background and offers a convenient and versatile set of features. Axios is known for its ability to intercept HTTP requests, handle simultaneous requests, and provide a straightforward syntax. Similar to Fetch, it supports promises for handling asynchronous requests.


When making GET requests with Axios, we can use the dedicated axios.get() method. Here's an example:

axios.get("https://world.openfoodfacts.org/category/pastas/1.json")   
    .then(response => {     
        // access parsed JSON response data using response.
        data field     
        data = response.data;
        console.log(data.count);     
        console.log(data.products);   
    })   
    .catch(error => {     
        if (error.response) {       
            //get HTTP error code       
            console.log(error.reponse.status);     
        } else {       
            console.log(error.message);     
        }   
    }); 

As shown in this example, Axios simplifies the process of making HTTP requests compared to Fetch. It automatically parses the received JSON data, which we can access through the response.data field. Axios also handles HTTP errors in its catch method, eliminating the need to explicitly check the status code before processing the response. Inside the catch method, we can differentiate HTTP errors using an error.response check, which provides the HTTP error code.


For sending POST requests with Axios, we use the dedicated axios.post() method. Here's an example using async/await:

async function postData () {   
    const food = {     
        name: "Bread",     
        weight: 450,    
         quantity: 3   
    };    
    
    try {     
        const response = await axios.post("/food", food);     
        console.log("Request successful!");   
    
    } catch (error) {     
        if (error.response) {       
            console.log(error.reponse.status);     
        } else {       
            console.log(error.message);     
        }   
   } 
} 

Again, Axios simplifies this implementation by automatically converting JavaScript objects to JSON without additional intervention. These Axios methods also accept a final parameter for specifying HTTP configurations.


Aside from these basic features, Axios provides solutions for many unique use cases, such as intercepting requests, sending simultaneous requests, aborting requests, automatic JSON data transformation, and monitoring request progress. However, these advanced features are beyond the scope of this explanation.


Pros of Axios

  • Provides a simple, concise, and easy-to-learn syntax.

  • Supports a versatile set of features not found in many other HTTP request packages, including intercepting requests, sending simultaneous requests, aborting requests, automatic JSON data transformation, and request progress monitoring.

  • Compatible with all major browser versions, including Internet Explorer.

  • Provides client-side support for XSRF protection.


Cons of Axios

  • Introduces an external dependency on the application since it is not a native module.


4. SuperAgent

SuperAgent is an early third-party package used for making HTTP requests in JavaScript. Similar to Axios, it utilizes the XMLHttpRequest API and offers a comprehensive set of features for request handling. It supports both promise-based and callback-based implementations.


To send HTTP requests with SuperAgent, we can use its dedicated methods for different request types. For example, the superagent.get() method is used to send GET requests. Here's an example:

superagent   
    .get("https://world.openfoodfacts.org/category/pastas/1.json")   
    .then(response => {     
        // get parsed JSON response data    
         data = response.body;
         console.log(data.count);     
         console.log(data.products);   
     })   
    .catch(error => {     
        if (error.response) {       
            console.log(error.status);     
        } else {       
            console.log(error.message);     
        }   
      }); 

SuperAgent follows a similar pattern to Axios with promise-based syntax for sending GET requests. It automatically parses the response body into a JavaScript object without manual intervention. HTTP errors are caught inside the catch method, and we can identify them using the error.response field. If the request fails due to a network-related error, these fields will remain undefined.


We can send POST requests with SuperAgent in a similar manner:

superagent   
    .post("/food")   
    .send(food)   
    .then(response => console.log("Request successful!"))   
    .catch(error => {     
        if (error.response) {       
            console.log(error.status);     
        } else {       
            console.log(error.message);     
        }   
    }); 

SuperAgent assumes the passed data is in JSON format by default and handles data transformation and content-type headers automatically. The send() method is used to send the data with the POST request.


Pros of SuperAgent

  • Provides an easy-to-use, promise-based solution for sending HTTP requests.

  • A mature and well-supported module in JavaScript.

  • Supports retrying requests if a network-related or other transient error occurs.

  • Offers an evolving set of plugins to extend the package's functionality, including features like mocking HTTP calls, caching request and response data, and request queueing and throttling.

  • Compatible with all major browser versions.


Cons of SuperAgent

  • Adds an external dependency as it is not a native module.

  • Does not support monitoring request progress.


5. Ky

Ky is a relatively new JavaScript package for making asynchronous HTTP requests from the front end of a web application. It is built on top of the native Fetch API, offering a simpler syntax and additional functionality.


Ky provides a simple syntax for making requests using its dedicated HTTP methods. Here's an example of sending a GET request with Ky using async/await:

async function getData () {   
    try {     
        const data = await ky.get("https://world.openfoodfacts.org/category/pastas/1.json") .json();     
        console.log(data.count);     
        console.log(data.products);   
    } catch (error) {     
        if (error.response) {           
            console.log(error.response.status);     
        } else {       
            console.log(error.message);     
        }   
    } 
} 

Similarly, POST requests can be sent following a similar pattern:

async function postData () {   
    try {     
        const response = await ky.post("/food", { json: food });     
        console.log("Request successful!");   
    } catch (error) {     
        if (error.response) {       
            console.log(error.reponse.status);     
        } else {       
            console.log(error.message);     
        }  
    } 

} 

Pros of Ky

  • Provides a simple, lightweight, promise-based API for making HTTP requests.

  • Addresses limitations in the native Fetch API by supporting features like request timeout, retry, and request progress monitoring.

  • Offers hooks for modifying requests during their lifecycle, such as beforeRequest, afterResponse, and beforeRetry.

  • Supports all modern browsers like Chrome, Firefox, and Safari.


Cons of Ky

  • Relatively new compared to other mature options mentioned.

  • Adds an external dependency for usage.


Conclusion

While these methods have their own strengths and weaknesses, you can pick the best fit to use in your web applications after carefully considering your requirements. We hope this post will help you conduct that analysis and identify the right method for sending HTTP requests in your future projects.

bottom of page