Tania Rascia

Skip Navigation
How to Connect to an API with JavaScript

How to Connect to an API with JavaScript

 /  152 responses

A big part of working with JavaScript is knowing how to connect to APIs. As a fledgling developer, you may have been told at some point to just “play around with some APIs!” to learn what they are and how to work with them. If you’ve ever taken a look at the documentation for an API and had no idea where to start or what to do and gotten frustrated, this is the article for you.

We’re going to make a very simple web app with plain JavaScript that will retrieve information from an API and display it on the page. There will be no server, dependencies, build tools, or anything else to further muddy the waters on an already difficult and confusing topic for beginners.

View Demo App Source Code on GitHub

Prerequisites

Everything else we’ll cover along the way.

Goals

We are going to write from scratch this simple web app that connects to a Studio Ghibli API, retrieves the data with JavaScript, and displays it on the front end of a website. This is not meant to be an extensive resource on APIs or REST – just the simplest possible example to get up and running that you can build from in the future. We’ll learn:

  • What a Web API is.
  • Learn how to use the HTTP request GET with JavaScript
  • How create and display HTML elements with JavaScript.

It will look like this:

Let’s get started.

Quick overview

API stands for Application Program Interface, which can be defined as a set of methods of communication between various software components. In other words, an API allows software to communicate with another software.

We’ll be focusing specifically on Web APIs, which allow a web server to interact with third-party software. In this case, the web server is using HTTP requests to communicate to a publicly available URL endpoint containing JSON data. If this is confusing now, it will make sense by the end of the article.

You may be familiar with the concept of a CRUD app, which stands for Create, Read, Update, Delete. Any programming language can be used to make a CRUD app with various methods. A web API uses HTTP requests that correspond to the CRUD verbs.

Action HTTP Method Definition
Create POST Creates a new resource
Read GET Retrieves a resource
Update PUT/PATCH Updates an existing resource
Delete DELETE Deletes a resource

If you’ve heard REST and RESTful APIs, that is simply referring to a set of standards that conform to a specific architectural style. Most web apps do, or aim to conform to REST standards. Overall, there are a lot of terms, acronyms and concepts to understand – HTTP, API, REST – so it’s normal to feel confused and frustrated, especially when API documentation assumes you already know what to do.

Setting Up

What is our objective? We want to get the data for all Studio Ghibli films and display the titles and descriptions in a grid. For some background knowledge, Studio Ghibli is a Japanese animation studio that produced several films, such as Spirited Away, which my friend Craig inspired me to use as an example.

We’re going to start by creating an index.html file in a new directory. The project will only consist of index.html, style.css, and scripts.js at the end. This HTML skeleton just links to a CSS and JavaScript file, loads in a font, and contains a div with a root id. This file is complete and will not change. We’ll be using JavaScript to add everything from here out.

index.html
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>Ghibli App</title>
  
  <link href="https://fonts.googleapis.com/css?family=Dosis:400,700" rel="stylesheet">
  <link href="style.css" rel="stylesheet">

</head>

<body>

  <div id="root"></div>

  <script src="scripts.js"></script>
</body>

</html>

Since this article is focused on the concepts of APIs and JavaScript, I will not be explaining how the CSS works. We will create a style.css that will be used to create a grid. For brevity’s sake, I only included the most pertinent structural CSS below, but you can copy the full CSS code here.

style.css
#root {
  max-width: 1200px;
  margin: 0 auto;
}

.container {
  display: flex;
  flex-wrap: wrap;
}

.card {
  margin: 1rem;
  border: 1px solid gray;
}

@media screen and (min-width: 600px) {
  .card {
    flex: 1 1 calc(50% - 2rem);
  }
}

@media screen and (min-width: 900px) {
  .card {
    flex: 1 1 calc(33% - 2rem);
  }
}

Now we have HTML and CSS set up, so you can make scripts.js and we’ll continue from there.

Connecting to the API

Let’s take a look at the Studio Ghibli API documentation. This API was created to help developers learn how to interact with resources using HTTP requests, which is perfect for us here. Since an API can be accessed by many different methods – JavaScript, PHP, Ruby, Python and so on – the documentation for most APIs doesn’t tend to give specific instructions for how to connect.

We can see from this documentation that it tells us we can make requests with curl or regular REST calls, but we might not have a clue how to do that yet.

Obtaining the API endpoint

To get started, let’s scroll to the films section. On the right you’ll see GET /films. It will show us the URL of our API endpoint, https://ghibliapi.herokuapp.com/films. Clicking on that link will display an array of objects in JSON.

If you do not have an extension on your browser for viewing JSON files, add one now, such as JSON View. This will make reading JSON much, much easier. Remember, if you’ve never worked with JSON, read this prerequisite article.

Retrieving the data with an HTTP request

Before we try to put anything on the front end of the website, let’s open a connection the API. We’ll do so using XMLHttpRequest objects, which is a way to open files and make an HTTP request.

We’ll create a request variable and assign a new XMLHttpRequest object to it. Then we’ll open a new connection with the open() method – in the arguments we’ll specify the type of request as GET as well as the URL of the API endpoint. The request completes and we can access the data inside the onload function. When we’re done, we’ll send the request.

scripts.js
// Create a request variable and assign a new XMLHttpRequest object to it.
var request = new XMLHttpRequest();

// Open a new connection, using the GET request on the URL endpoint
request.open('GET', 'https://ghibliapi.herokuapp.com/films', true);

request.onload = function () {
  // Begin accessing JSON data here
  }
}

// Send request
request.send();

Working with the JSON response

Now we’ve received a response from our HTTP request, and we can work with it. However, the response is in JSON, and we need to convert that JSON in to JavaScript objects in order to work with it.

We’re going to use JSON.parse() to parse the response, and create a data variable that contains all the JSON as an array of JavaScript objects. Using forEach(), we’ll console log out the title of each film to ensure it’s working properly.

scripts.js
// Begin accessing JSON data here
var data = JSON.parse(this.response);

data.forEach(movie => {
  // Log each movie's title
  console.log(movie.title);
});

Using Inspect on index.html and viewing the console, you should see the titles of 20 Ghibli films. Success!

The only thing we’re missing here is some way to deal with errors. What if the wrong URL is used, or the URL broke and nothing was being displayed? When an HTTP request is made, the response returns with HTTP status codes. 404 is the most well-known response, meaning Not Found, and 200 OK is a successful request.

Let’s just wrap our code in an if statement, succeeding on any response in the 200-300 range, and log out an error if the request fails. You can mess up the URL to test the error.

scripts.js
// Begin accessing JSON data here
var data = JSON.parse(this.response);

if (request.status >= 200 && request.status < 400) {
  data.forEach(movie => {
    console.log(movie.title);
  });
} else {
  console.log('error');
}

Here is the entire code so far.

scripts.js
var request = new XMLHttpRequest();

request.open('GET', 'https://ghibliapi.herokuapp.com/films', true);
request.onload = function () {

  // Begin accessing JSON data here
  var data = JSON.parse(this.response);

  if (request.status >= 200 && request.status < 400) {
    data.forEach(movie => {
      console.log(movie.title);
    });
  } else {
    console.log('error');
  }
}

request.send();

We’ve successfully used a GET HTTP request to retrieve (or consume) the API endpoint, which consisted of data in JSON format. However, we’re still stuck in the console – we want to display this data on the front end of the website, which we’ll do by modifying the DOM.

XMLHttpRequest is a widely supported built-in method of making requests. There is also a newer Fetch API which can be used for the same purpose, which is simpler but has less browser support.

Displaying the Data

In order to display information on the front end of a site, we’ll be working with the DOM, which is actually an API itself that allows JavaScript to communicate with HTML. If you have no experience at all with the DOM, I wrote Understanding and Modifying the DOM in JavaScript for DigitalOcean that will clarify what the DOM is and how the DOM differs from HTML source code.

By the end, our page will consist of a logo image followed by a container with multiple card elements – one for each film. Each card will have a heading and a paragraph, that contains the title and description of each film. Here’s what that looks like, with only essential CSS loaded in:

If you remember, our index.html just has a root div – <div id="root"> right now. We’ll access it with getElementById(). We can briefly remove all the previous code we’ve written for now, which we’ll add back in just a moment.

scripts.js
const app = document.getElementById('root');

If you’re not 100% positive what getElementById() does, take the above code and console.log(app). That should help clarify what is actually happening there.

The first thing in our website is the logo, which is an img element. We’ll create the image element with createElement().

const logo = document.createElement('img');

An empty img is no good, so we’ll set the src attribute to logo.png. (Found here)

logo.src = 'logo.png';

We’ll create another element, a div this time, and set the class attribute to container.

const container = document.createElement('div');
container.setAttribute('class', 'container');

Now we have a logo and a container, and we just need to place them in the website. We’ll use the appendChild() method to append the logo image and container div to the app root.

app.appendChild(logo);
app.appendChild(container);

Here is the full code for that.

scripts.js
const app = document.getElementById('root');

const logo = document.createElement('img');
logo.src = 'logo.png';

const container = document.createElement('div');
container.setAttribute('class', 'container');

app.appendChild(logo);
app.appendChild(container);

After saving, on the front end of the website, you’ll see the following.

Elements
<div id="root">
  <img src="logo.png">
  <div class="container">
  </div>
</div>

This will only be visible in the Inspect Elements tab, not in the HTML source code, as explained in the DOM article I linked.

Now we’re going to paste all our code from earlier back in. The last step will be to take what we consoled out previously and make them into card elements.

Paste everything back in, but we’ll just be looking at what’s inside the forEach().

data.forEach(movie => {
  console.log(movie.title);
  console.log(movie.description);
});

Instead of console.log, we’ll use textContent to set the text of an HTML element to the data from the API. I’m using substring() on the p element to limit the description and keep each card equal length.

scripts.js
data.forEach(movie => {
  // Create a div with a card class
  const card = document.createElement('div');
  card.setAttribute('class', 'card');

  // Create an h1 and set the text content to the film's title
  const h1 = document.createElement('h1');
  h1.textContent = movie.title;

  // Create a p and set the text content to the film's description
  const p = document.createElement('p');
  movie.description = movie.description.substring(0, 300); // Limit to 300 chars
  p.textContent = `${movie.description}...`; // End with an ellipses

  // Append the cards to the container element
  container.appendChild(card);

  // Each card will contain an h1 and a p
  card.appendChild(h1);
  card.appendChild(p);
});

I’ll also replace the console’d error with an error on the front end, using the best HTML element, marquee! (I’m only doing this as a joke for fun and demonstrative purposes, do not actually use marquee in any sort of real application, or take me seriously here.)

const errorMessage = document.createElement('marquee');
errorMessage.textContent = `Gah, it's not working!`;
app.appendChild(errorMessage);

And we’re done! Here is the final scripts.js code.

scripts.js
const app = document.getElementById('root');

const logo = document.createElement('img');
logo.src = 'logo.png';

const container = document.createElement('div');
container.setAttribute('class', 'container');

app.appendChild(logo);
app.appendChild(container);

var request = new XMLHttpRequest();
request.open('GET', 'https://ghibliapi.herokuapp.com/films', true);
request.onload = function () {

  // Begin accessing JSON data here
  var data = JSON.parse(this.response);
  if (request.status >= 200 && request.status < 400) {
    data.forEach(movie => {
      const card = document.createElement('div');
      card.setAttribute('class', 'card');

      const h1 = document.createElement('h1');
      h1.textContent = movie.title;

      const p = document.createElement('p');
      movie.description = movie.description.substring(0, 300);
      p.textContent = `${movie.description}...`;

      container.appendChild(card);
      card.appendChild(h1);
      card.appendChild(p);
    });
  } else {
    const errorMessage = document.createElement('marquee');
    errorMessage.textContent = `Gah, it's not working!`;
    app.appendChild(errorMessage);
  }
}

request.send();

And with the full CSS styles, here is what the final product looks like.

Again, here is a link to the live app and the source code.

View Demo App Source Code on GitHub

Conclusion

Congratulations, you used plain JavaScript to connect to the API using HTTP requests. Hopefully you have a better understanding of what an API endpoint is, how the browser communicates with third-party API data with requests and responses, how to parse JSON into arrays and objects that JavaScript understands, and how to build a front end entirely with JavaScript.

We did this all without having to worry about anything like Node.js, npm, Webpack, React, Angular, build tools, Axios and other popular development terms, dependencies, and frameworks that may confuse you about what is happening under the hood in it’s simplest form.

I hope you found this article useful, and please feel free to share, or correct me where I’m wrong in the comments below!

Newsletter

Get updated when I create new content.
Unsubscribe whenever. Never any spam.

Note

I'm Tania. I turn down every ad, affiliate, and sponsor request I get. I write free resources that help thousands of people successfully become devs. If you enjoy my content, please consider supporting what I do.

Support my work

Write a response

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

All code will be displayed literally.

Discussion

  • Matt says:

    Very rarely leave comments on guides like this, but this is so, so great. Thanks a ton for making this easy to understand!

  • Maka says:

    Awesome explanation!

  • nkwo chidubem says:

    This is the most complete and helpful article on API I have seen, thanks for sharing.

    You are really a high opener.

    Thanks.

  • David Gilligan says:

    Excellent article! It's taken me awhile to find something that didn't use frameworks. Thank you so much.

  • Lichard Long says:

    Fantastic content.
    Great work.
    The most concise article on this topic
    Keep up.

  • moon says:

    So I have a little question about this, and I'm pretty sure the answer will lead me onto how to link to other APIs; how do you know that you have to use move.<json value>? It doesn't seem to be referenced in the API documentation, or defined in the script, so any help would be appreciated!

  • Luke says:

    The only tutorial that has made sense to me anywhere!

    I'm practicing this for a personal project to better understand API's, so I posted this in the url: https://pokeapi.co/api/v2/generation/3/ and changed the variable names but nothing comes up. To use it on a different api endpoint what else do you have to change?

    Thanks!

  • Node says:

    This is so great… I have been battling with how to do this for few years now. Thanks to you i finally understand

  • JF says:

    Thanks a lot, that was very clear!

  • Bran says:

    "We’ll create a request variable and assign a new XMLHttpRequest object to it. Then we’ll open a new connection with the open() method – in the arguments we’ll specify the type of request as GET as well as the URL of the API endpoint. The request completes and we can access the data inside the onload function. When we’re done, we’ll send the request."

    This is not accurate. We are not doing anything with open(), it is just a pointer to the function. It will be called _after_ send() executes

    • Chris S says:

      So you mean open is not a method in the XMLHttpRequest object? If we're not directly calling it, then how is the GET, getting the data to then pass on? Can you please explain how it's working if this is not the case?

      Thank you!
      Chris

  • Chris S says:

    You are super awesome!!! Thank you for the grass roots as there is NOTHING that explains it in JS like yours does! I hope you enjoy the 2 cups of coffee, or beer ????

    Cheers

  • Holliday says:

    What am I doing incorrectly? My example shows up blank? I copied everything word for word – files saved correctly. I can't figure out what I'm doing wrong.

    • Mike says:

      Have you used 'inspect' to see if there are any errors. For instance, I often fat finger the file names for scripts and or style sheets (scripts.js instead of script.js for instance). If you do that then inspect will show an error in the console.

      (To get to inspect on Chrome just right click your web page and select "inspect" from the context menu)

  • script Geek says:

    Thanks a lot …that was incredibly helpful

  • Germano says:

    The design of the page is very beautiful! I really loved all the CSS! Great tutorial!

  • dan says:

    great tuts!!!!

  • Aishwarya Thapliyal says:

    I came here while I was learning REACT and APIs, I really liked the way you write Tania.

  • Jessica says:

    This is a really great tutorial! I want to create a Pokedex application using an API and this gave me a better idea of how to do that.

  • steve says:

    Where does "movie" come from in the movie.title JS code?

    • Chris S says:

      it's just a variable defined at the forEach time. All the data it loops through after the parse will be associated, one by one, to the the class name movie and every attribute can then be called with . notation, i.e. movie.title. You can change movie to dogs and it would still work, dogs.title, as long as it's defined, by name, first at forEach.

  • Ro says:

    This is one of the clearest tutorials I've read for understanding how to use api calls in Javascript. Thanks!

  • Dona says:

    Tania, se te agracede por tan claro y didactico tutorial, me fueron de mucha utilidad. Gracias por compartir tus conocimientos.

  • Chris M. says:

    I love this tutorial. I'm working on a major app that requires several API's. I've pulled API's before, but it's always good to see someone else's techniques. Your code is well thought out, works beautifully and this tutorial is very clearly explained (as you always do).

    Thanks for sharing!

  • Patrik Horemans says:

    Hi Tania,
    Many thanks for this very clear and easy to understand practical example.
    I have only basic knowledge of js etc. (i'm ok with HTML and CSS)
    The one thing i don't understand is the movie.
    I understand that title is a part of the movie variable and therefore movie.title will represent the titles as returned by the JSON query.
    But how do you know the query will return a variable called "movie"?

    • Saeed says:

      You don't. "forEach" is going through the "data" array one by one. And "movie" is just a reference to the current object in the array that's being dealt with. I tend to call them something bit more generic like "item" but "movie" make sense here.

    • Rhiannon says:

      She created the name 'movie' on this line:
      data.forEach(movie => {

      She could have put anything else there and it would have worked just the same. 'movie' didn't come from the API.

      data.forEach(x => {
      console.log(x.title);
      console.log(x.description);
      });

      You frequently see people just using a single letter like x or y when writing lambda expressions like that, but I'm glad she went with something more descriptive like movie.

  • Tobi ibot says:

    thank you so much Tania, i just discovered page and its been really helpful. Pls keep doing more stuff. You explain sooooo well and simplify concepts will clear examples. You are truly awesome. Looking foward to more stuff

  • yaronm says:

    Hi,

    Thank you for making this great tutorial, I noticed you have a extra curly bracket on one of the code snippet on the following section: "Retrieving the data with an HTTP request"

    request.onload = function () {
    // Begin accessing JSON data here

    } // This curly bracket should not be here :)!
    }

  • kusaljay says:

    Hi Tania,
    You're a legend!
    Crystal clear explanation with only barebone JS, HTML, CSS and not muddying up with package managers and build tools.
    Just a suggestion though – It would be good if you can do a line or two about ES6 template literals in the article when we are at `${movie.description}…`. I'm new to ES6 and I couldn't figure out what's happening here but doing a bit of googling helped.
    Thanks for this article and keep up the good work. Cheers!