TypeError: Failed to fetch and CORS in JavaScript

avatar

Borislav Hadzhiev

Last updated: Jul 25, 2022

banner

Photo from Unsplash

TypeError: Failed to fetch and CORS in JavaScript #

The "TypeError: Failed to fetch" occurs for multiple reasons:

  1. An incorrect or incomplete URL has been passed to the fetch() method.
  2. The server you are making a request to does not send back the correct CORS headers.
  3. A wrong protocol is specified in the url.
  4. A wrong method or headers have been passed to the fetch() method.

typeerror failed to fetch

Here's an example of how the error occurs.

index.js
async function getUser() { try { // ⛔️ TypeError: Failed to fetch // 👇️ incorrect or incomplete URL const response = await fetch('https://example.com/does-not-exist'); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } const result = await response.json(); return result; } catch (err) { console.log(err); } } getUser();

The url we passed to the fetch() method is incorrect, so we got back two errors:

  • CORS - "No 'Access-Control-Allow-Origin' header is present on the requested resource."
  • "TypeError: Failed to fetch"

Make sure that the URL you're passing to the fetch method is correct and complete. You have to:

  • include the protocol, e.g. https:// or http:// if you're testing on localhost without an SSL certificate
  • the path has to be correct e.g. /articles
  • the HTTP method (e.g. GET or POST) has to be correct for the specific path (e.g. /articles)
  • if you misspell any of the configurations, e.g. a property in the headers object or the HTTP method, you would get the error back.

To solve the "TypeError: Failed to fetch", make sure to pass the correct configuration to the fetch method, including the URL, HTTP method and headers, and verify that the server you're making a request to is setting the correct CORS headers with the response.

index.js
// ✅ Works async function getUser() { try { const response = await fetch('https://randomuser.me/api/', { method: 'GET', headers: { accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } const result = await response.json(); return result; } catch (err) { console.log(err); } } getUser();
If you're making a POST, PUT or PATCH request, make sure the body is passed to the JSON.stringify() method in the call to fetch.

If the configuration you pass to the fetch method is correct, check if your server is sending the correct CORS headers in the response.

The server should be setting the following CORS headers along with the response:

cors
# 👇️ your domain below, e.g. http://localhost:3000 Access-Control-Allow-Origin: http://example.com Access-Control-Allow-Methods: POST, PUT, PATCH, GET, DELETE, OPTIONS Access-Control-Allow-Headers: Origin, X-Api-Key, X-Requested-With, Content-Type, Accept, Authorization

You might have to tweak the values depending on your use case, but open the Network tab in your browser, click on the request and check if your server is setting these CORS-related headers.

The headers are:

  • Access-Control-Allow-Origin - which origins are allowed to make requests to the server.
  • Access-Control-Allow-Methods - which HTTP methods the origins are allowed to use when making requests to the server
  • Access-Control-Allow-Headers - which HTTP headers the origins are allowed to use when making requests to the server
If you can't get the CORS options working, try using the * (asterisk) symbol as the origin and see if that works.

When an asterisk * is set for the Access-Control-Allow-Origin header, any origin on the internet can access the server.

cors
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, PUT, PATCH, GET, DELETE, OPTIONS Access-Control-Allow-Headers: *

You would want to narrow this down in production, but it's a useful tool when debugging.

When the Access-Control-Allow-Headers is set to an asterisk, all headers are allowed in a preflight request.

CORS is a mechanism that allows a server to use a combination of HTTP headers to indicate from which domains, other than its own, it receives requests.

By default, servers only take requests made from applications hosted on the same domain.

If your server is hosted on http://example.com, for you to be able to make an HTTP request from http://localhost.com, your server has to send the necessary CORS headers in its responses.

To allow other origins to make requests to your server, you have to set the Access-Control-* headers in your server's responses.

If you don't have access to the server, use a proxy #

A proxy is a server that sits between the client (browser) and the server you need to make an HTTP request to.

If you aren't able to set the Access-Control-Allow-* response headers on the server, you can make an HTTP request to a proxy, which makes an HTTP request to the other server.

This is possible because the same origin policy isn't enforced when making requests from one server to another.

If your proxy server sends the correct Access-Control-Allow-* headers to your client (browser), then it can just fetch the information from the other server and respond with it.

Here is an example of a simple proxy using Express.js.

In order to use it, you first have to install the dependencies.

shell
npm install express

The proxy consists of the following code stored in an index.js file.

index.js
const express = require('express'); const app = express(); app.use((_req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', '*'); next(); }); app.get('/users', async (_req, res) => { const url = 'https://randomuser.me/api/'; try { const response = await fetch(url); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } const result = await response.json(); return res.json(result); } catch (error) { console.log(error); return res.status(500).json({error: 'An error occurred'}); } }); const port = 3456; app.listen(port, () => console.log(`Server running on http://localhost:${port}`), );

You can start the proxy server with the node index.js command.

shell
node index.js

You can make an HTTP request to http://localhost:3456/users to get a response with the data.

make http request to proxy

We set the Access-Control-Allow-Origin and Access-Control-Allow-Headers headers to an asterisk to allow all origins to make requests to the proxy server.

The next step is to make an HTTP request to the other server and send the response to the client.

The proxy server simply sits between the browser and the other server and takes advantage of the fact that one server can make an HTTP request to another without having to pass CORS checks.

Alternatively, you can use a proxy server that makes a request to the specified URL and responds with the result.

The cors-anywhere package is a NodeJS proxy which adds CORS headers to the proxied request.

Using the cors-anywhere package as a proxy #

You can use the following command to install the cors-anywhere package.

shell
npm install cors-anywhere

Here are the contents of a simple implementation of the proxy server stored in an index.js file.

index.js
const cors_proxy = require('cors-anywhere'); const host = process.env.HOST || '0.0.0.0'; // Listen on a specific port via the PORT environment variable const port = process.env.PORT || 8080; cors_proxy .createServer({ originWhitelist: [], // Allow all origins }) .listen(port, host, function () { console.log('Running CORS Anywhere on ' + host + ':' + port); });

You can start the proxy server with the node index.js command.

shell
node index.js

The server is available at http://localhost:8080.

As shown in the docs, the URL to proxy is taken from the path.

Here are some examples.

shell
# 👇️ makes a request to randomuser.me/api http://localhost:8080/randomuser.me/api # 👇️ makes a request to google.com http://localhost:8080/google.com

make http request using proxy server

The concept is the same - the proxy server makes an HTTP request to the specified URL and sends the response data back to the client.

Conclusion #

To solve the "TypeError: Failed to fetch and CORS" error, make sure:

  1. You haven't specified an incorrect or incomplete URL when making the request.
  2. Your server sends back all the necessary CORS headers to enable requests from a different origin.
  3. You haven't specified the wrong protocol in the URL.
  4. You haven't specified a wrong HTTP method or headers when making the request.
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.