-1

Note: the api Key is fake for privacy.

const url = 'http://newsapi.org/v2/everything?' +
          'q=platformer&' +
          'apiKey=3ce15c4d1fd3485cbcf17879bab498db';

async function getNews() {
    const response = await fetch(url);
    const data = await response.json();
    console.log(data);
}

getNews()

The problem is that when I run this javascript code I get this error:

Access to fetch at 'http://newsapi.org/v2/everything?q=platformer&apiKey=3ce15c4d1fd3485cbcf17879bab498db' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Basically I want to pull news from this newsapi.org and and see the data in the console.

Gjison Giocf
  • 145
  • 1
  • 11
  • 2
    Because of the website's CORS policy, you cannot fetch data from a different domain. A solution would be to use axios in Node.js – Bren Jul 08 '20 at 22:53
  • 2
    Making the requests on the server-side would be better, indeed. Because your API key is private. It should not be shared with anyone, so not embedded in your front-end code. That's the reason why the API did not enable CORS. [Docs](https://newsapi.org/docs/authentication) _"You can attach your API key to a request in one of three ways: - apiKey querystring parameter. - X-Api-Key HTTP header. - Authorization HTTP header. **We strongly recommend either of the latter 2 so that your API key isn't visible to others** in logs or request sniffing."_ – blex Jul 08 '20 at 23:01

2 Answers2

1

In short, you can utilize a CORS Proxy.

Your question has already been answered here, which provides a larger CORS Proxy explanation and walkthrough.


There's also an accepted answer for NewsApi.org specifically that's a bit more brief here.

Excerpt:

You need a CORS proxy

const proxyUrl = "https://cors-anywhere.herokuapp.com/"
const qInTitle = "";
const from = "";
const apiKey = "";
const url = `${proxyUrl}https://newsapi.org/v2/everything?qInTitle=${qInTitle}&from=${from}language=en&apiKey=${apiKey}`;
const request = new Request(url);

fetch(request)
  .then(response => response.json())
  .then((news) => {
    console.log(news);
  })
  .catch(error => {
    console.log(error);
  });

Also, here's a pretty thorough article if you need to know more about CORS in general:

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Tcraw
  • 274
  • 1
  • 11
  • As a comment above suggests, it would be bad practice to expose their API key to a service which should be kept private. – Bren Jul 08 '20 at 23:03
  • @Bren That may be true (and I definitely agree with @blex!), but if the OP is not asking for best practice, providing answers on utilizing a CORS proxy or other viable workarounds may still prove to be helpful for whatever the OP's objective is. – Tcraw Jul 08 '20 at 23:12
  • 1
    Im getting a 426 upgrade error: newsapi.js:20 GET https://cors-anywhere.herokuapp.com/https://newsapi.org/v2/everything?qInTitle=platformer&from=uslanguage=en&apiKey=3ce15c4d1fd3485cbcf17879bab498db 426 (Upgrade Required) – Gjison Giocf Jul 09 '20 at 13:29
1

The error message of News API provides a hint:

Requests from the browser are not allowed on the Developer plan, except from localhost

Assuming that you are indeed running the app using a local development server (like this one), pointing your browser to http://localhost:8080/ instead of http://127.0.0.1:8080/ does the trick:

Successful News Api fetch from localhost

Code sample below (run locally with a webserver):

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <h1>News</h1>

  <button id="btn-get">Get News</button>
  <div id="news-container"></div>
  <script>
    const url = `https://newsapi.org/v2/everything?q=bitcoin&apiKey=API_KEY`

    const newsContainer = document.getElementById('news-container')

    function fetchNews(url) {
      return fetch(url)
        .then(res => res.json())
    }

    document.getElementById('btn-get').addEventListener('click', () => {
      fetchNews(url)
        .then(articles => newsContainer.textContent = JSON.stringify(articles))
    })

  </script>

</body>

</html>
Juan Marco
  • 3,081
  • 2
  • 28
  • 32