Lupe Camacho

Wikipedia Viewer: Wikipedia API & Cross-Origin Requests (SOLVED)

A lot of people working on the freeCodeCamp Wikipedia Viewer run into problems making requests to the Wikipedia API. They plug the request URL into the search browser and it pulls up the data just fine.

But as soon as they start making the request inside their JavaScript, all sorts of error messages start popping up in the console and no data seems to be getting through.

According to the cross-site request portion of the API documentation, there are two ways to make a cross-site request to a MediaWiki site: JSONP and CORS.

You can bypass these issues by using JSONP instead, but in this article I’m going to be focusing on making the request work using the CORS method.

Wikipedia API Search Example

We’ll start by trying to reverse-engineer the example that freeCodeCamp gives us: a search for the term butterfly that yields a long list of pages containing the word butterfly.

Screenshot of the example freeCodeCamp Wikipedia Viewer with a list of results for the search term ‘butterfly’

I’m going to use this request URL to get the same sort of results:

https://en.wikipedia.org/w/api.php?action=opensearch&search=butterfly&format=json

You’ll note that I’m using the opensearch action, so let’s look at the OpenSearch action in more detail. The API documentation for OpenSearch gives us this handy blurb about what it does:

Get pages whose name matches a given string. When limit is reached, results are ordered by number of incoming links.

The page gives us more parameters to use to configure our request URL, but we’ll just stick to the basics right now.

You should get something like this if you visit the above link.

Screenshot of JSON response when visiting the endpoint above. Several arrays are returned: one that consists of a list of article titles, one consisting of article descriptions, and another of links.

Now for the code:

$.ajax(wikiLink, {
  dataType: "json",
  type: "GET",
  success: function(data) {
  console.log(data);
}

I have the wikiLink variable set to the request URL shown above, and we’re specifying that we want to GET JSON data back from the API. If the request is successful, the data will be logged to the console for us to look at.

But, this is where we run into a problem…

Wikipedia CORS

If we submit the request as-is in our development environment, we get this message from the console:

XMLHttpRequest cannot load https://en.wikipedia.org/w/api.php?action=opensearch&search=butterfly&format=json. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost’ is therefore not allowed access.

I’m developing on a local server, so your origin may be different. But what the heck does that mean?

If you go to the API sandbox, you’ll see this blurb under the origin parameter:

When accessing the API using a cross-domain AJAX request (CORS), set this to the originating domain. This must be included in any pre-flight request, and therefore must be part of the request URI (not the POST body)...

For non-authenticated requests, specify the value *. This will cause the Access-Control-Allow-Origin header to be set, but Access-Control-Allow-Credentials will be false and all user-specific data will be restricted.

This is discussed in more detail in the CORS section of the documentation.

Upon reading this part of the documentation, we see that request URL must contain the origin parameter. Since we have a non-authenticated request (i.e. not from one of the allowed domains) we have to specify the origin with an asterisk.

But first let’s take a look at what this is saying in the context of the Chrome Developers console. When you open the Network tab and enter the XHR tab, you’ll see that the request was actually sent a 200 status back.

Screenshot of Network tab under Chrome DevTools, which shows a 200 status response from the Wikipedia endpoint.

Despite being denied access, you can see that the resource was actually transmitted. If you click on the request name, you’ll be able to actually see the requested data under the Response tab. Now let’s look at the Headers tab:

The Response Headers tab of the Wikipedia XHR resource, which lacks the headers we're looking for.

You can see that the Response Headers section is devoid of the Access-Control-Allow-Origin and Access-Control-Allow-Credentials that we keep reading about.

Those CORS headers are what Wikipedia needs to be sending us in order for our JavaScript to be allowed access to the data.

In that case, we can get the API to send us those headers by specifying our origin using the asterisk just as the API documentation noted.

The Origin Solution

Let’s tag &origin=* onto the end of our original request URL, giving us a request URL of:

https://en.wikipedia.org/w/api.php?action=opensearch&search=butterfly&format=json&origin=*

So what happens when we send a request to the API using that URL instead?

The same tab as above, but access-control headers have magically appeared in the Response Headers section.

Now, we still have the same OK status code but the Access-Control-Allow-Origin and Access-Control-Allow-Credentials have been added to the header.

You can also do this by leaving &origin=* off the URL, and simply adding this origin parameter into the ajax request instead:

$.ajax(wikiLink, {
  dataType: "json",
  data: {
    origin: "*"
  },
  type: "GET",
  success: function(data) {
  console.log(data);
}

Going back to the console tab of our Developer Tools, we can finally see the data!

The browser console now shows the same array that we saw when visiting the endpoint directly.

For more information about the Wikipedia API and this CORS solution in particular, check out this helpful answer on StackExchange.

Update: BONUS

This post has gotten more traffic than any of my other web dev posts, and I totally understand why. FreeCodeCamp just throws you into the section on APIs without any prep and holy ****, APIs are ridiculously hard to comprehend when you’re first introduced to them.

Even when I’d completed a couple of the API projects,  I still didn’t really understand what the heck I was doing.

¯\_(ツ)_/¯

One of the main resources that was a lifesaver early in the game when I was about ready to give up was Treehouse’s AJAX Basics class. (FYI I’m a total Treehouse fangirl because they are one of the only e-learning providers that actually speak to me at my level, minus the needless jargon.)

If you’re interested in checking it out, go to the class page and check out the material that’s covered; it includes AJAX concepts, retrieving and working with JSON, and much more. You have the option to try a 7-day free trial, so there’s nothing to lose!