Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
Axios

5 Ways to Make an HTTP Request in JavaScript

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For most ordinary browser requests, use the built-in fetch() API. Check response.ok yourself: Fetch resolves its promise when it receives an HTTP response, including responses such as 404 or 500. Use XMLHttpRequest when you need its event-based progress controls or must support an existing XHR codebase; Axios when you want a shared library abstraction; Node.js http/https for low-level stream control; and EventSource for one-way server-to-browser updates.

Choose the request method that fits your JavaScript environment

These five approaches are not interchangeable. Fetch, XMLHttpRequest (XHR), and Axios make ordinary requests and receive responses. Node.js http/https gives server-side code lower-level access to streams and connection details. EventSource keeps an HTTP connection open for server-sent events (SSE), but it is a one-way channel.

Approach Where it fits Best use Main trade-off
Fetch Modern browsers, workers, and current Node.js releases New request code using the built-in Promise API Check HTTP status explicitly; browser cross-origin requests remain subject to CORS.
XMLHttpRequest Browsers Existing XHR code, or event-based upload/download progress and response types More event plumbing; synchronous use on the main thread blocks the interface.
Axios Browsers and Node.js A project that wants a library-based client abstraction Adds a dependency; adapter details can vary by release.
Node.js http/https Node.js Detailed control over headers, sockets, and response streams More callback and event handling than a high-level client.
EventSource Browser clients talking to an SSE endpoint Receiving a continuing stream of server updates Server to client only; it is not a general request API.

The Fetch API is the practical default for most new browser code. MDN describes it as a flexible replacement for XHR; XHR remains useful when its specific event and response controls suit the task. On the server, choose between Fetch, a library such as Axios, and Node’s lower-level APIs based on the control your application needs.

1. Fetch: the default for ordinary requests

fetch() returns a Promise that resolves to a Response after response headers arrive. A network failure can reject the Promise, but an HTTP error status does not automatically do so. Test response.ok (true for successful 2xx responses) or inspect response.status before parsing the body.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

GET JSON and handle HTTP errors

async function getProducts() {
  const response = await fetch("https://example.org/products.json");
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  return response.json();
}

getProducts()
  .then(products => console.log(products))
  .catch(error => console.error("Request failed:", error));

This example distinguishes an HTTP error response from a rejected request. The catch handler also catches errors thrown by the status check and errors while parsing JSON. In real applications, decide how each case should reach the user or be logged instead of silently swallowing it.

POST JSON

async function createUser() {
  const response = await fetch("https://example.org/users", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ username: "ada" })
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  return response.json();
}

Set the method, indicate the JSON content type, and serialize the object for a JSON request body. The server still determines whether that method and payload are accepted.

Use Fetch in a browser versus Node.js

Fetch is global in browser window and worker contexts, and it is available in current Node.js releases. Browser requests to another origin are subject to CORS rules. A Node.js request is server-side and is not governed by the browser’s CORS enforcement, though the destination server can still require authentication, reject the request, or impose other access rules.

Fetch is the right starting point when a Promise-based request/response flow is enough. If you need upload progress events or more direct event control, consider XHR; if you want a library abstraction, consider Axios.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. XMLHttpRequest: event-driven browser requests

XHR follows a sequence: construct the object, call open(), attach event listeners, and then call send(). It can provide progress events and selectable response types, so it remains relevant to progress-sensitive tasks and existing applications.

Read JSON and handle request failures

const xhr = new XMLHttpRequest();
xhr.open("GET", "/data.json");
xhr.responseType = "json";

xhr.addEventListener("load", () => {
  if (xhr.status < 200 || xhr.status >= 300) {
    console.error(`HTTP ${xhr.status}`);
    return;
  }
  console.log(xhr.response);
});

xhr.addEventListener("error", () => {
  console.error("Network error");
});
xhr.send();

The load event indicates that the request completed; it does not by itself mean the HTTP status was successful. Check xhr.status. The error handler covers a network-level failure. For uploads or downloads where progress matters, XHR’s progress events can report transfer progress; add the relevant progress listener and present that information accurately rather than treating it as a guarantee that the server has finished processing.

Keep XHR asynchronous

Asynchronous requests are the normal choice. Synchronous XHR outside a Web Worker blocks the main thread, freezing interaction while the request waits. Avoid it for interactive pages.

3. Axios: a library abstraction for browser and Node.js

Axios is a Promise-based HTTP client for browsers and Node.js. It gives a project a client library abstraction instead of using Fetch or a lower-level Node API directly. The cost is an additional dependency, and exact adapter behavior is release-sensitive, so consult documentation for the version your project installs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install and make a request

Install Axios using the package manager and version policy already used by your project. Then, in a JavaScript module:

import axios from "axios";

async function loadProducts() {
  try {
    const { data } = await axios.get("https://example.org/products.json");
    return data;
  } catch (error) {
    console.error("Request failed:", error);
    throw error;
  }
}

async function createUser() {
  try {
    const { data } = await axios.post("https://example.org/users", {
      username: "ada"
    });
    return data;
  } catch (error) {
    console.error("Request failed:", error);
    throw error;
  }
}

Axios’s examples return the response body as data. Keep error handling around the call: requests can fail, and the application still needs a defined response to that failure. Choose Axios when its abstraction benefits the project, not on the assumption that it removes browser security rules or all request configuration work.

4. Node.js http and https: low-level control

Node.js’s built-in HTTP API is intentionally low-level. Its request and response streams and events, including data and end, are useful when you need control over headers, sockets, or streaming. The trade-off is manual response handling, including collecting and parsing the body.

GET and parse a JSON response

import https from "node:https";

https.get("https://example.org/data.json", (res) => {
  let body = "";
  res.setEncoding("utf8");

  res.on("data", chunk => {
    body += chunk;
  });

  res.on("end", () => {
    if (res.statusCode < 200 || res.statusCode >= 300) {
      console.error(`HTTP ${res.statusCode}`);
      return;
    }

    try {
      console.log(JSON.parse(body));
    } catch (error) {
      console.error("Response was not valid JSON:", error);
    }
  });
}).on("error", error => {
  console.error("Request failed:", error);
});

Use https for an HTTPS URL and http for HTTP. The response status is separate from the request’s error event, so check it before treating the body as a successful result. This API is worthwhile when stream and connection-level control matter; for routine requests, a higher-level API usually needs less plumbing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. EventSource: receive one-way live updates

EventSource is for Server-Sent Events, where a browser connects to an HTTP endpoint and receives a stream of server updates. It is not a replacement for ordinary GET or POST requests. The connection is one-way: the browser receives events, but cannot send events back to the server through that same channel.

Listen for updates

const events = new EventSource("/events");

events.onmessage = (event) => {
  try {
    const update = JSON.parse(event.data);
    render(update);
  } catch (error) {
    console.error("Invalid event data:", error);
  }
};

events.onerror = () => {
  console.error("Event stream encountered an error");
  events.close();
};

The browser’s onmessage handler receives event data as text, so parse it only if the server sends JSON. Closing the EventSource on error, as above, stops the client from continuing to listen. Use Fetch, XHR, or Axios for ordinary client requests and uploads; use WebSockets when the application needs a long-lived bidirectional channel.

Cross-origin requests: CORS is not bypassed by choosing another API

In browsers, cross-origin behavior is governed by Cross-Origin Resource Sharing (CORS). The server must permit the requesting origin for browser JavaScript to read a cross-origin response. Depending on the method and headers, the browser may first send a preflight request to ask whether the actual request is allowed.

Setting Fetch’s mode to "no-cors" is not a workaround for an API that does not allow your origin. It restricts which methods and headers the request can use, and the response is opaque: JavaScript cannot inspect its status or body. If a browser request is blocked, configure the destination server’s CORS policy where you control it, or make the request through a server you control when appropriate. Switching from Fetch to XHR or browser-based Axios does not remove the browser’s cross-origin restrictions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common problems and how to fix them

  • Fetch does not enter catch for a 404 or 500: Fetch resolves for HTTP error responses. Check response.ok or response.status before parsing.
  • JSON parsing fails: The response may not contain valid JSON, may be empty, or may be an error page. Check the status and the endpoint’s response format before calling response.json() or JSON.parse().
  • The browser reports a CORS error: The server has not permitted the browser origin or the preflight. Configure CORS on the server you control; no-cors makes the response unreadable rather than fixing the permission.
  • XHR fires load but the operation failed: load means the exchange completed, not that the status is 2xx. Inspect xhr.status.
  • The page appears frozen while a request runs: Check for synchronous XHR on the main thread and replace it with asynchronous handling.
  • Node.js receives an error status but no request error: Inspect res.statusCode; HTTP errors are responses, not necessarily transport failures. Handle request errors separately.
  • EventSource does not send client data: That is the protocol’s one-way design. Use a separate request for client-to-server actions or WebSockets for bidirectional communication.

Performance, reliability, and cost considerations

The choice between these APIs is primarily about environment and control, not a documented speed ranking. The cited authoritative documentation provides no directly relevant comparative benchmark, so there is no basis here for claiming one method is faster. Fetch is built into modern browsers and current Node.js releases; Axios adds a dependency; XHR and Node’s low-level APIs may fit particular progress or streaming requirements. Evaluate performance in the context of the actual endpoint, payload, network, and application.

For reliability, handle both transport-level failures and unsuccessful HTTP statuses, and parse the body according to the response format. Consider timeouts, cancellation, retries, and authentication according to the service and application requirements; these are operational policies rather than reasons to assume an API automatically makes a request reliable. Browser requests also remain subject to CORS regardless of whether the code uses Fetch, XHR, or Axios.

Or skip the browser setup

If your goal is to capture a webpage rather than build and operate your own browser-based screenshot flow, ScreenshotNeo provides a screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers indicate the page verdict and whether the request was billed. AI agents can use its MCP server tools, including take_screenshot, get_page_info, and capture_pdf.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request details. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up free for ScreenshotNeo and try it with 1,000 screenshots a month and no card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Further reading

Frequently Asked Questions

Can I use Fetch in Node.js as well as in a browser?

Yes. Fetch is available in current Node.js releases as well as browser window and worker contexts.

Is EventSource a replacement for WebSockets?

No. EventSource delivers server-to-browser updates over a one-way connection. Use WebSockets when both sides need a bidirectional, long-lived channel.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.