9

I'm trying to access the Deezer API from localhost, but I'm keep getting the following error:

Fetch API cannot load http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost' is therefore not allowed access.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

localhost's response's headers does have Access-Control-Allow-Origin header (Access-Control-Allow-Origin:*).

I'm using fetch like: fetch('http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem').

What am I doing wrong?

Tamás
  • 950
  • 2
  • 10
  • 29
  • Check out this: https://stackoverflow.com/a/20035319/4304132 – Andreas Aug 03 '17 at 12:15
  • With http://html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html, it loads the request but with http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem, it errors the same way. – Tamás Aug 03 '17 at 12:48
  • is the **api** responding to that request with an `access-control-allow-origin: *` ? or an `access-control-allow-origin:` in this cast localhost? – Schrodinger's cat Aug 03 '17 at 13:00
  • By using no cors definitin will help for some apis that's not required by header – HipsterSantos Aug 18 '21 at 15:52

3 Answers3

15

You can make the request through a public CORS proxy; to do that try changing your code to:

fetch('https://cors-anywhere.herokuapp.com/http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem')

That sends the request through https://cors-anywhere.herokuapp.com, which forwards the request to http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem and then receives the response. The https://cors-anywhere.herokuapp.com backend adds the Access-Control-Allow-Origin header to the response and passes that back to your requesting frontend code.

The browser will then allow your frontend code to access the response, because that response with the Access-Control-Allow-Origin response header is what the browser sees.

You can also set up your own CORS proxy using https://github.com/Rob--W/cors-anywhere/

For details about what browsers do when you send cross-origin requests from frontend JS code using XHR or the Fetch API or AJAX methods from JavaScript libraries—and details about what response headers must be received in order for browsers to allow frontend code to access the responses—see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • Good to know! However, as an API author, can I still restrict my API not to respond to proxies? Or would proxies fetch anyway – Schrodinger's cat Aug 03 '17 at 14:13
  • 1
    There’s no general way to detect whether a request is coming from a proxy vs somebody’s backend server code. Regardless, it’s outside the scope of CORS config at least—since even CORS config does not restrict your server from responding to any requests but instead just affects what response headers are added (or not added) to responses. For CORS at least, it’s strictly up to browsers to enforce the cross-origin restrictions on requests made by frontend code. – sideshowbarker Aug 03 '17 at 14:17
  • cors-anywhere is not longer available : https://cors-anywhere.herokuapp.com/corsdemo – Nitneq Jun 28 '21 at 17:57
3

For now, it is impossible to make this request. You can proxy request to API from your own backend or use jsonp. Here is a library with fetch-like syntax https://github.com/camsong/fetch-jsonp. Usage example https://jsfiddle.net/4dmfo0dd/1/

fetchJsonp('https://api.deezer.com/search/track/autocomplete?limit=1&q=eminem&output=jsonp')
.then(function(response) {
    return response.json();
  })
  .then(json => console.log(json))
  .catch(function(error) { console.log(error); });
2

CORS or Cross Origin requests made to servers

http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem

in this case, have a preflight check enabled by all modern browsers.

and usually fail, if the server does not respond with Access-control headers.

In case of a fetch too, since you are basically fiddling with Javascript ,

You Need the Server to respond with Access-control-Allow-Origin Headers, which are flexible.

You Can not do Much about it Unless, the API itself becomes flexible and more open.

You however can Use fetch with mode set to no-cors

IFFF you only wish to cache the result of the request you make, to serve as a response, and not consume it yourself

Read Opaque Responses

No-CORS Definition

no-cors — Prevents the method from being anything other than HEAD, GET or POST. If any ServiceWorkers intercept these requests, they may not add or override any headers except for these. In addition, JavaScript may not access any properties of the resulting Response. This ensures that ServiceWorkers do not affect the semantics of the Web and prevents security and privacy issues arising from leaking data across domains

Community
  • 1
  • 1
Schrodinger's cat
  • 1,074
  • 10
  • 17
  • 1
    Note that as far as `mode: no-cors`, in practice you almost never want to use `mode: no-cors`. The reason is that when you set that for a request, it tells the browser to block your frontend JavaScript code from having any access to the response under any circumstances. It also tells the browser to completely block your frontend code from being able to add any custom headers to the request. I’m not sure in practice you can pass on the response from a `mode: no-cors` request in the way you say. As far as I understand at least, basically all you can do with it is cache it (with service workers). – sideshowbarker Aug 03 '17 at 14:20
  • Again! Good to know more about it! If I may ask though, Since a service worker can intercept , but not read from such a response, would the body in its entirety be forwarded If I were to call another API and pass on the opaque response? – Schrodinger's cat Aug 03 '17 at 14:25
  • 1
    As far as I understand, you can’t pass on an opaque response to any other code, period. I think all that you can do with it is have the service worker load it from its cache when handling a request for it (rather than re-fetching it). I could be wrong but I think that’s how it works – sideshowbarker Aug 03 '17 at 14:29