Integrating PHP applications with Instagram, Part 1

Use the Instagram API to integrate photos from Instagram with a PHP app

Instagram is a popular photo-sharing service that enables users to take photos with their smartphone and share them with others through the Web. Application developers can search and retrieve these photos, together with their associated comments and likes, through he Instagram REST API. This two-part article introduces the Instagram API and illustrates how it can be used with PHP to leverage Instagram's rich repository of user-generated content and create innovative web applications.

01 Feb 2013 - Added links to Part 2 in the Retrieving image details and Resources sections.

Share:

Vikram Vaswani, Founder, Melonfire

Photo of Vikram VaswaniVikram Vaswani is the founder and CEO of Melonfire, a consulting services firm with special expertise in open-source tools and technologies. He is also the author of the books Zend Framework: A Beginners Guide and PHP: A Beginner's Guide.



01 February 2013 (First published 18 January 2013)

Also available in Russian Japanese Vietnamese

Introduction

If you have an Android or Apple smartphone with a camera, chances are that you also have Instagram. This free application allows users to take photos, enhance them with special effects and filters, and then share them with friends using the Instagram website. Think of it like Twitter, but with photos instead of tweets. And with more than 100 million users as of September 2012, it clearly does something right.

In addition to providing a platform for users to share photos, Instagram also has a rich developer API, which allows developers to access user-generated content and create content-driven web applications around this content. This API, which follows the REST model, can be accessed through any programming language that understands JSON, including my favorite, PHP.

This two-part article will introduce you to the Instagram API, showing you how to integrate and use Instagram's user-generated content with PHP applications. It includes examples of retrieving photo and comment feeds; searching for photos by keyword, user or location; retrieving user profiles; and managing user relationships. So come on in, and get started!


Getting started

Before you begin to develop applications with the Instagram API, you need to understand how it works. Like many other web APIs, the Instagram API works over HTTP and expects an HTTP request to a designated endpoint. On receipt of this request, the API server replies to the query with a JSON feed containing the requested data. It's then possible to parse this data using either a server-side programming language (PHP or Perl, for example) or a client-side toolkit (jQuery or mooTools, for example) and extract content from it for integration into a web page.

To see how this works, first do two things:

  1. Create an Instagram account. Registration is free, and this task can be accomplished using the Instagram Android, iPhone, or iPad app. After you register using the app, take a few photos with your smartphone and upload them to your Instagram profile.
  2. Create a client application to gain access to the Instagram API. Log in to the Instagram website using the account created in the previous step and register a new client through the developer console (see Resources for a link). You'll need to enter basic client information, such as a name and description, together with a callback URL for OAuth 2.0 authentication (Figure 1).
    Figure 1. Instagram client registration (Register new OAuth Client)
    Screen capture of Instagram client registration (Register new OAuth Client)

    After this information is submitted, your client is assigned a unique client ID and secret (Figure 2). Take note of these as you'll need them to access the Instagram API using OAuth 2.0.

    Figure 2. Instagram client registration (Manage Clients)
    Screen capture of Instagram client registration (Manage Clients)

Once you know the client ID and secret, you have the tools you need to create signed OAuth 2.0 requests to the Instagram API. The OAuth 2.0 protocol and workflow are widely documented (see Resources for links to relevant documentation). This article won't go into the details; it's sufficient to note that subsequent examples demonstrate how to implement this workflow with the Instagram API.

Note also that use of the Instagram API in third-party applications is governed by the Instagram API Terms of Use. Spend a few minutes reading this document before you leap into development, to ensure that you comply with all necessary rules. You can find links to this document in Resources.


Listing popular images

Before you start the PHP code, look at how the Instagram API works. As with all REST-based services, an API method is invoked by making an HTTP request to a designated resource endpoint. This HTTP request contains one or more input parameters; the server processes these parameters and sends back a JSON response that can be parsed and used within a web page. For security, all Instagram API requests must be made over SSL.

The Instagram API offers a number of different endpoints. Endpoints are available for media, comments, likes, tags, locations, users, and user relationships. Some endpoints are accessible just by passing the client ID as a request parameter; others require a signed OAuth 2.0 request.

A typical Instagram response packet contains a detailed feed of photos and related information. To see an example, open your web browser and request the API endpoint https://api.instagram.com/v1/media/popular?client_id=xx (replace the xx in the URL with your Instagram client ID). This request should produce a JSON feed of the most popular images on Instagram at the moment. Take a quick glance through this output (Figure 3) to familiarize yourself with its main elements. As you can see, the response document contains a list of popular photos and provides, for each photo, the image URL (for thumbnail, low-resolution, and high-resolution versions), caption, tags, creation time, comments, likes, filter, location, short URL, user information, and more.

Figure 3. Sample Instagram API response
Screen capture of a sample Instagram API response

It's quite easy to format this information into a readable web page with PHP's json_decode() function and some basic HTML. Listing 1 illustrates this.

Listing 1. Retrieving popular images
<html>
  <head></head>
  <body>  
    <h1>Popular on Instagram</h1>  
    <?php
    // load Zend classes
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Http_Client');

    // define consumer key and secret
    // available from Instagram API console
    $CLIENT_ID = 'YOUR-CLIENT-ID';
    $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

    try {
      // initialize client
      $client = new Zend_Http_Client('https://api.instagram.com/v1/media/popular');
      $client->setParameterGet('client_id', $CLIENT_ID);

      // get popular images
      // transmit request and decode response
      $response = $client->request();
      $result = json_decode($response->getBody());
      
      // display images
      $data = $result->data;  
      if (count($data) > 0) {
        echo '<ul>';
        foreach ($data as $item) {
          echo '<li style="display: inline-block; padding: 25px"><a href="' . 
            $item->link . '"><img src="' . $item->images->thumbnail->url . 
            '" /></a> <br/>';
          echo 'By: <em>' . $item->user->username . '</em> <br/>';
          echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . '<br/>';
          echo $item->comments->count . ' comment(s). ' . $item->likes->count . 
            ' likes. </li>';
        }
        echo '</ul>';
      }

    } catch (Exception $e) {
      echo 'ERROR: ' . $e->getMessage() . print_r($client);
      exit;
    }
    ?>
  </body>
</html>

Listing 1 begins by setting up an instance of the Zend Framework auto-loader and then initializing an instance of the Zend_Http_Client class. This client is used to create and transmit a GET request to the Instagram API endpoint for popular images at https://api.instagram.com/v1/media/popular. Notice that the endpoint URL must contain the client ID generated through the Instagram developer console.

The JSON response to the request is then parsed and converted into a PHP object using PHP's json_decode() function. If you compare the code in Listing 1 to the raw JSON object displayed in Figure 3, you can see the correspondence between the object members and JSON key-value pairs. Now you can iterate over the object members, retrieve data for the individual images (such as the image URL, owner's username, creation time, comment and like count), and format this for display as a web page. Figure 4 illustrates what the output looks like.

Figure 4. Listing popular images
Screen capture of a web page that lists popular images

Searching for images by tag

As Figure 3 illustrates, you can associate each Instagram image with one or more tags, which are descriptive keywords that can be used to categorize the image. The Instagram API includes endpoints for searching and retrieving tags. The one that you'll use most often is the /tags/search endpoint, which allows you to search for tags matching a search term. Consider Listing 2, which demonstrates how to use this endpoint.

Listing 2. Searching for tags
<html>
  <head></head>
  <body>
    <h1>Instagram Tag Search</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for:
      <input type="text" name="q" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define consumer key and secret
      // available from Instagram API console
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // initialize client
        $client = new Zend_Http_Client('https://api.instagram.com/v1/tags/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('q', $_POST['q']);

        // get and display similar tags
        $response = $client->request();
        $result = json_decode($response->getBody());
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) {
            echo '<li>' . $item->name . ' (' . $item->media_count . 
              ') </li>';
          }
          echo '</ul>';
        }
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
    ?>
  </body>
</html>

Listing 2 begins by setting up a simple web form, for the user to input a search term. Once the form is submitted, a new Zend_Http_Client object is initialized and a request is created to the /tags/search endpoint, similar to that described for Listing 1. The user-entered search term passes to this endpoint as a request parameter in the "q" request argument.

The response to this request is a collection of tags matching the search term. You can decode this information and format it into a web page, producing a result like that in Figure 5:

Figure 5. Listing tags
Screen capture of sample search results for 'beach', a list of tags

In many cases, you are interested in the images associated with the tags rather than the tags. That's where the /tags/[tag-name]/media/recent endpoint comes in. As you might guess from the endpoint structure, it produces a list of images recently tagged with the specified tag name. Listing 3 illustrates tags in action, by creating a simple application to search Instagram for photos by tag.

Listing 3. Searching for images by tag
<html>
  <head></head>
  <body>
    <h1>Instagram Photo Search by Tag</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for:
      <input type="text" name="q" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define consumer key and secret
      // available from Instagram API console
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // initialize client
        $client = new Zend_Http_Client('https://api.instagram.com/v1/tags/'. 
          $_POST['q'] . '/media/recent');
        $client->setParameterGet('client_id', $CLIENT_ID);

        // get images with matching tags
        // transmit request and decode response
        $response = $client->request();
        $result = json_decode($response->getBody());
        
        // display images
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) {
            echo '<li style="display: inline-block; padding: 25px"><a href="' . 
              $item->link . '"><img src="' . $item->images->thumbnail->url . 
              '" /></a> <br/>';
            echo 'By: <em>' . $item->user->username . '</em> <br/>';
            echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . '<br/>';
            echo $item->comments->count . ' comment(s). ' . $item->likes->count . 
              ' likes. </li>';
          }
          echo '</ul>';
        }

      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
    ?>
  </body>
</html>

Listing 3 is a hybrid of Listing 1 and Listing 2. It presents a web form for the user to enter a search term. It then uses that search term as a tag, sending a request to the /tags/[tag-name]/media/search endpoint to find a list of matching photos. The resulting object collection is then processed as in Listing 1, to generate a page containing thumbnail images and basic profile information. Figure 6 shows an example of the result.

Figure 6. Listing images by tag
Screen capture of results page that lists images by tag

Searching for images by location

Just as you can search for images by tag, you also can search for images by location. The /media/search endpoint accepts "lat" and "long" parameters and produces a list of images matching that latitude and longitude. To illustrate, consider Listing 4, which allows the user to enter latitude/longitude coordinates and then generates a list of images in or around the specified area.

Listing 4. Searching for images by location
<html>
  <head></head>
  <body>
    <h1>Instagram Photo Search by Location</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Latitude: <input type="text" name="lat" />  
      Longitude: <input type="text" name="long" /> 
      <input type="submit" name="submit" value="Search!" />      
    </form>
    <?php
    } else {
    ?>
    <h1>Search results for 'lat:<?php echo $_POST['lat']; ?>, 
      long:<?php echo $_POST['long']; ?>'</h1>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // define consumer key and secret
      // available from Instagram API console
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // initialize client
        $client = new Zend_Http_Client('https://api.instagram.com/v1/media/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('lat', $_POST['lat']);
        $client->setParameterGet('lng', $_POST['long']);

        // get images matching specified location
        $response = $client->request();
        $result = json_decode($response->getBody());
        
        // display images
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) {
            echo '<li style="display: inline-block; padding: 25px"><a href="' . 
              $item->link . '"><img src="' . $item->images->thumbnail->url . 
              '" /></a> <br/>';
            echo 'By: <em>' . $item->user->username . '</em> <br/>';
            echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . '<br/>';
            echo $item->comments->count . ' comment(s). ' . $item->likes->count . 
              ' likes. </li>';
          }
          echo '</ul>';
        }

      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
    ?>
  </body>
</html>

Figure 7 illustrates the result of a search for images at 18.9218 N, 72.8347 E, which corresponds to the location of the Gateway of India in Mumbai.

Figure 7. Listing images by location
Screen capture of page that lists images by location

Note that you can increase the diameter of the search area, from 1 km to 5 km, by appending a "distance" parameter to the request. While not demonstrated here, Instagram also provides a /locations API endpoint, which you can use to retrieve information about a specific location.


Retrieving image details

The previous examples demonstrated how to search for and retrieve collections of images matching specific criteria. Instagram also provides the /media/[media-id] endpoint, which you can use to obtain detailed information about a specific image. Consider Listing 5, which illustrates the type of information available through this endpoint.

Listing 5. Retrieving image data
<html>
  <head>
    <style>
    #container {
      margin: 0 auto;    
    }
    #info {
      float: left; 
      width: 300px;
      padding-right: 20px;
    }
    #image {
      float: left; 
      width: 320px;
      padding-right: 20px;
    }    
    #comments {
      clear: both;
    }
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .profile {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>  
    <h1>Instagram Image Detail</h1>
    <?php
    // load Zend classes
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Http_Client');

    // define consumer key and secret
    // available from Instagram API console
    $CLIENT_ID = 'YOUR-CLIENT-ID';
    $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

    try {
      // define image id
      $image = '338314508721867526';
    
      // initialize client
      $client = new Zend_Http_Client('https://api.instagram.com/v1/media/' . $image);
      $client->setParameterGet('client_id', $CLIENT_ID);

      // get image metadata
      $response = $client->request();
      $result = json_decode($response->getBody());
      
      // display image data
    ?>
      <div id="container">
        <div id="info">
          <h2>Meta</h2>  
          <strong>Date: </strong> 
          <?php echo date('d M Y h:i:s', $result->data->created_time); ?>
          <br/>
          <strong>Creator: </strong>
          <?php echo $result->data->user->username; ?>
          (<?php echo !empty($result->data->user->full_name) ? 
            $result->data->user->full_name : 'Not specified'; ?>)
          <br/>
          <strong>Location: </strong>
          <?php echo !is_null($result->data->location) ?
          $result->data->location->latitude . ',' . 
            $result->data->location->longitude : 'Not specified'; ?>
          <br/>
          <strong>Filter: </strong>
          <?php echo $result->data->filter; ?>
          <br/>
          <strong>Comments: </strong>
          <?php echo $result->data->comments->count; ?>
          <br/>
          <strong>Likes: </strong>
          <?php echo $result->data->likes->count; ?>
          <br/>
          <strong>Resolution: </strong>
          <a href="<?php echo $result->data->images
            ->standard_resolution->url; ?>">Standard</a> | 
          <a href="<?php echo $result->data->images
            ->thumbnail->url; ?>">Thumbnail</a>
          <br/>
          <strong>Tags: </strong>
          <?php echo implode(',', $result->data->tags); ?>
          <br/>
        </div>
        <div id="image">
          <h2>Image</h2>  
          <img src="<?php echo $result->data->images
            ->low_resolution->url; ?>" /></a>
        </div>
        <div id="comments">
          <?php if ($result->data->comments->count > 0): ?>
          <h2>Comments</h2>
          <ul>
            <?php foreach ($result->data->comments->data as $c): ?>
              <div class="item"><img src="<?php echo $c
                ->from->profile_picture; ?>" class="profile" />
              <?php echo $c->text; ?> <br/>
              By <em> <?php echo $c->from->username; ?></em> 
              on <?php echo date('d M Y h:i:s', $c->created_time); ?>
              </div>
              
              </li>
            <?php endforeach; ?>
          </ul>
          <?php endif; ?>
        </div>      
      </div>
    <?php
    } catch (Exception $e) {
      echo 'ERROR: ' . $e->getMessage() . print_r($client);
      exit;
    }
    ?>
  </body>
</html>

After loading the Zend_Http_Client library, Listing 5 creates a request for the /media/[media-id] endpoint, with the media ID embedded in the request URI. The media ID is typically included with each search result, together with other photo meta-data.

The response to a /media/[media-id] API request is a JSON document containing detailed information on the specified image. This information includes the image creation date and time, the username of the creator, the latitude and longitude at which the photo was taken, the Instagram filter used on the photo, and the number of likes and comments. The returned data also includes URLs to three versions of the image—a thumbnail, a low-resolution version, and a high-resolution version—together with a list of associated tags. A list of recent comments is appended to the JSON document; as you'll see from the listing and output, you can process this list to display comments on the photo, together with the commenting user's name and profile picture.

Figure 8 displays the output of Listing 5. As the output illustrates, the Instagram API makes it possible to display all of the information that you would find in the Instagram application and website, through a custom PHP application.

Figure 8. Displaying image details
Screen capture of page that displays image details

This is just the tip of the iceberg. The Instagram API also lets developers access the authenticated user's photo feed, search for photos by user, create follower relationships between users, and more. In most cases, these user-scope operations can only be performed using signed OAuth 2.0 requests, which requires the developer to implement an OAuth 2.0 workflow. This, and other aspects of the Instagram API, will be discussed in the second part of this article, so be sure to come back for that.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into XML on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Open source, Web development
ArticleID=854964
ArticleTitle=Integrating PHP applications with Instagram, Part 1
publish-date=02012013