Everything You Need to Know About Instagram API Integration

The following is a guest post by Emerson This. This is a guide for web developers interested in integrating Instagram content on websites. It was only a few months ago when Instagram changed what was possible with their API, so this serves to explain that, what is possible now, and examples of those possibilities.

Part One: Understanding the Instagram API in three minutes

In order to work with the Instagram API, sooner or later, you must find your way through the nebulous API client registration and authorization process. Understanding the API access limitations can prevent a lot of wasted time, because they often result in unexpected data rather than straight-forward authentication errors that are easier to diagnose.

The infamous June 2016 API restrictions

On June 1 2016, console errors lit up all over the world when Instagram significantly restricted access to its API. The first thing to understand is that it was a deliberate business decision by Instagram, designed to prevent their API from being used for a variety of purposes. Understanding this fact will not fix the errors in the console, but it makes the restrictions more intuitive to work around if you understand their intent.

Sandbox mode vs "live" mode

The gatekeeper between developers and full API access is called sandbox mode. The documentation presents it as a temporary step in the development process, but the overwhelming majority of projects will never leave sandbox mode because Instagram only grants full access to their API for a handful of very specific use cases:

  • “My app allows people to login with Instagram and share their own content”
  • “My product helps brands and advertisers understand, manage their audience and media rights.”
  • “My product helps broadcasters and publishers discover content, get digital rights to media, and share media with proper attribution.”

If you cannot convince the Instagram lords that your app serves one of these specific purposes, it will be rejected if you submit it to “Go live”. For this reason, it may be more intuitive to think of it as “sideline mode”.

What can you do while in sandbox mode?

Sandbox mode means that your API calls go to a magic island where only your last 20 posts exist. That’s it. No one else exists on the island, so you will not see results for anything you posted earlier, or from any other Instagram users, even if that content is public. You can invite additional “sandbox users” which will add them to your magic island, but just like you, only their most recent 20 posts exist on the island.

The sandbox island: only the first 20 posts

The island will never get very large because you can only have a total of ten sandbox users. Let this sink in for a moment. Anything you might want to do that involves content from the general public will not be possible in sandbox mode.

Sandbox mode vs scopes

One of the most common confusions about the new restrictions is conflating scopes and sandbox mode. Sandbox mode governs what your API requests can “see” diverting them to the magic island. Scopes govern what a specific token can and cannot be used for. Every token automatically starts with the basic scope. A token with only the basic scope can do very little, whether in sandbox mode or live. To view even public content, you will need to request the additional public_content scope. Where sandbox mode enters the picture is in determining what is included in “public content”. In sandbox mode, it will only include the posts on the magic island, whereas a live app can see anything that’s public (in the real world) on Instagram.

The most common misconception is that an app needs to be approved to "go live” in order to request scopes. This is incorrect. For example, while in sandbox mode, you need a token with the public_content scope to see posts by your other sandbox users just the same way approved (“live”) apps do1. Technically there is nothing a live app can do that cannot be done in sandbox mode, as long as it only involves users and content that lives on the magic island.

Watch out for old docs!

It is also worth mentioning that before June 2016 many API calls used to allow authentication with only a client_id from a registered client. Now all requests require an access_token. However there are still lots of plugins, documentation, and tutorials from before June 1 that have yet to update accordingly.

Part Two will show how to work within the API restrictions to set up the popular Instagram integrations that are still possible in sandbox mode.

Part Two: How to Use the Instagram API on Websites

Registering an API Client

Before you can do anything with the Instagram API you will need to register an API client as a developer. If you are not already registered as a developer you will be prompted to do so before proceeding to register a new API client.

Instagram's Register New Client interface

The most delicate part of configuring an API client is entering the correct values in the Valid redirect URIs field. This is a whitelist of URIs which Instagram will use during the authentication workflow. The URI matching algorithm is very strict. So you need to make sure that one of the URIs you enter here is exactly the same as the URI you pass in the redirect_uri parameter when requesting a token (described below). For example, if you enter http://mysite.com/oauth and then try to request a token using mysite.com/oauth or http://mysite.com/oauth/, it will fail.

A registered API client gets assigned a client ID and a client secret. As the name implies, do not share your client secret. You will use both of these to request tokens from Instagram.

Generating an access token

As discussed above, you will need to generate a token to authenticate requests to the Instagram API. There are basically two ways to do this: you can request tokens programmatically or manually. Both approaches require you to have first registered an API client (described above).

Generating Instagram tokens programmatically using Oauth 2 workflow

Instagram's implementation of Oauth 2 is very standard, so if you have any experience with this authentication pattern it will be very familiar. There is good documentation in the official docs which walks through the exact sequence of requests and parameters. Here's a quick summary:

  1. Direct your user to Instagram's authorization URL
  2. The user grants authorization
  3. Instagram redirects the user back to your site with a code
  4. Send the code back to Instagram in exchange for the token

Generating Instagram tokens manually

In situations where you do not need to access the API dynamically as different users you can generate a token manually.

If you have a tool to make POST requests and a public endpoint set up to receive the redirection from Instagram, you could generate a token by manually making each request in the previous sequence. But this can be tedious, especially for a small project where you just need one token.

The easiest way to do this is to use a token generating tool like this. Before the June 2016 restrictions kicked in, there were many resources like this to choose from, but you will find that many of them broke when the restrictions started. InstagramToken.com still works, and it also allows you to generate tokens with specific scopes (explained in Part One) which is important if you are trying to do anything besides request your own content.

How to Invite Sandbox Users

Sandbox users are other Instagram users that you invite to your client. The main reason to do this is so that your app will then be able to “see” their last twenty posts in addition to your own. This is explained in Sandbox mode vs "live" mode above.

You invite sandbox users from the Sandbox tab of the Edit Client UI.

Sandbox tab of Edit Client UI

A couple of quick notes on the behavior around inviting sandbox users (valid as of August 28, 2016):

  1. Invitees do not receive a notification when you invited them2. You will need them to log into Instagram and then visit this page. They will then have to submit a short, vague form to register as a developer. If they are not developers they will be confused by these questions. Fortunately, the answers do not seem to matter.
  2. They also may not need to have them accept your invite at all. Right now, “sandbox users” don’t need to accept the invitation in order to be able to show their content via a client in sandbox mode. It seems to start working even while their invitation is “pending”.

A quick security warning: it is not generally a best practice to make client side requests with an API token because it is like a password and can easily be read from the source code by a malicious user. However, when in sandbox mode, the tokens can do very little, so the stakes are pretty low.

How to find your user ID

It is surprisingly difficult to find a user's numeric ID, which is necessary for many popular types of requests. There were a handful of online resources built to facilitate this, but most were broken at the time of writing this. Smash Balloon has a free tool that seems to be working at the moment. It is also not very difficult find an ID yourself if you know where to look.

To find a users numeric Instagram ID first visit the user's public Instagram page: https://instagram.com/<username>. View the source code of this page and locate the large <script> block near the bottom of the page. Inside you will find a large window._sharedData object definition. The first instance of id will be the user's numeric ID. There is also a user_id property under the owner node for each media object.

Looking at the source code of Instagram user page to find the user ID

Part Three: Recipes for Doing Stuff with the Instagram API

How to show your Instagram feed on your website

This use case is not one of the chosen few that will be approved to "go live" but fortunately this is one of the few things you can still (mostly) do while in sandbox mode. You will need a registered API client ID and an access token (both are explained above).

Let's use the popular Instafeed library to add your Instagram feed to a website.

First download the library manually or with bower: bower install instafeed.js. Then load the scripts before the </body> at the bottom of your page. Also insert <div id="instafeed"></div> wherever you want the stream of images to appear.

  <div id="instafeed"></div>
  <script src="path/to/instafeed.min.js"></script>
</body>

Next you will need to initialize Instafeed with another small script telling it which posts you want to show.

  <div id="instafeed"></div>
  <script src="path/to/instafeed.min.js"></script>
  <script>
    var feed = new Instafeed({
      get: 'user',
      userId: USER_ID, // Ex: 1374300081
      accessToken: 'YOUR_ACCESS_TOKEN'
    });
    feed.run();
  </script>
</body>

This can be used to show the last 20 posts of any users that have accepted the invitation to be a sandbox user for your API client.

Why you can’t (really) show a list of tags anymore

Technically you can request posts with a particular tag. Nothing stops you from using the same workflow as shown above. Instafeed supports tag searches already, so you could just pass the following settings:

var feed = new Instafeed({
  get: 'tagged',
  tagName: 'TAG', Ex: // 'cat'
  accessToken: 'YOUR_ACCESS_TOKEN'
});

However, if you are in sandbox mode you probably will not see the results you expect!

Tags exist because they group content from different users. Remember from Part One that sandbox mode means your API requests are diverted to a magic island where only the last 20 posts by you and your few sandbox users exist. This means if you make a request for posts tagged #cat (which has ~90M posts), but you and your sandbox users have not used that tag within your last 20 posts, the API request will succeed, but return zero results.

The bottom line is that the tag feed will probably only be meaningful if you are displaying a tag that is unique and frequently used by you and your sandbox users.

How to embed a single post on your website

Instagram wants you to use their official embed widget or either of their embed endpoints, which do not require an access token.

The easiest way to get the embed widget code snippet is from the [· · ·] button in the bottom corner of a post. Click it to reveal the code snippet that you can copy/paste into your HTML.

The Instagram single photo embed code is found within this menu.

The snippet will output something like this.

What the Instagram single photo widget looks like.

If you're thinking "but that doesn't match the rest of my site." That's the point. It's not an accident that the API doesn't just return a URL to an image file. ;)

How to add a like or follow button

This falls in the same category of the tag feed above. Technically you can add/remove likes in sandbox mode, but there are very few use cases that make much sense because in sandbox mode your API access is restricted to your sandbox users. This means if you add a "like" or "follow" button to your site, it will only allow your sandbox users to like each others' posts.

If the limitations of sandbox mode are not a deal-breaker, then a like button is as simple as sending a POST request to the /media/<MEDIA_ID>/likes endpoint. The following example uses jQuery to make the HTTP request, but you can substitute your preferred tool.

<button id="like-btn" data-media-id="123456789">Like</button>

<script>
  function sendLike(event) {
    // Find the media ID in a data attribute for the button
    var mediaId = $(event.target).data('media-id');
    var token = 'YOUR_TOKEN';

    // Build the url
    var url = 'https://api.instagram.com/v1/media/';
    url += mediaId;
    url += '/likes?access_token=' + token;

    // Make the request and handle the response
    $.post(url).then(function(){
      // success
      function() { console.log('like request succeeded'); },
      // fail
      function() { console.log('like request failed'); }
    });
  }
  $('#like-btn').click(sendLike);
</script>

In this code we register a listener for a click event on the button. The callback function sendLike() finds the media ID in a data attribute of the button and uses it to build the URL before posting the request.

Conclusion

If you made it this far you understanding the Instagram API restrictions, and you know which integrations are possible while in the restrictive sandbox mode. If I missed something, drop a comment or find me on Twitter: @emersonthis.


1 I suspect this confusion stems from the fact that Instagram’s client management UI has a tab that looks as if it is for requesting scopes, which is disabled while in sandbox mode. This is not how scopes are granted. Rather, this how how live apps get authorized by Instagram to request specific scopes (aka permissions) from users.

2 It possible that notifications were filtered by spam, or that Instagram forgot to build this.