Simple Instagram driver for Node.js


NodeJS driver for the Instagram API. In production at http://totems.coaggregating more than 200 data points per seconds


npm install instagram-node

How it works

  • First of all, you need to authentify. You can use client_id/client_secretfrom the app you are building, or an access_tokenfrom a user that use your app.
  • Some features need an access_token to work
var ig = require('instagram-node').instagram();

// Every call to `ig.use()` overrides the `client_id/client_secret`
// or `access_token` previously entered if they exist.
ig.use({ access_token: 'YOUR_ACCESS_TOKEN' });
ig.use({ client_id: 'YOUR_CLIENT_ID',
         client_secret: 'YOUR_CLIENT_SECRET' });
  • If you activated "Signed Requests", you need to sign requests that need the write access (relationship, likes, comments, ...) with:'/like/:media_id', function(req, res, next) {
    var ig = require('instagram-node').instagram({});
    ig.use({ access_token: 'YOUR_ACCESS_TOKEN' });
    ig.add_like(req.param('media_id'), {
      sign_request: {
        client_secret: 'YOUR_CLIENT_SECRET',
        // Then you can specify the request:
        client_req: req
        // or the IP on your own:
        ip: 'XXX.XXX.XXX.XXX'
    }, function(err) {
      // handle err here
      return res.send('OK');

Server-Side Authentication using OAuth and the Instagram API

Instagram uses the standard oauth authentication flow in order to allow apps to act on a user's behalf. Therefore, the API provides two convenience methods to help you authenticate your users. The first, get_authorization_url, can be used to redirect an unauthenticated user to the instagram login screen based on a redirect_uristring and an optional optionsobject containing an optional scopearray and an optional statestring. The second method, authorize_user, can be used to retrieve and set an access token for a user, allowing your app to act fully on his/her behalf. This method takes three parameters: a response_codewhich is sent as a GET parameter once a user has authorized your app and instagram has redirected them back to your authorization redirect URI, a redirect_uriwhich is the same one supplied to get_authorization_url, and a callback that takes two parameters errand result. errwill be populated if and only if the request to authenticate the user has failed for some reason. Otherwise, it will be nulland responsewill be populated with a JSON object representing Instagram's confirmation reponse that the user is indeed authorized. See instagram's authentication documentationfor more information.

Below is an example of how one might authenticate a user within an ExpressJS app.

var http = require('http');
var express = require('express');
var api = require('instagram-node').instagram();
var app = express();

app.configure(function() {
  // The usual...

  client_id: YOUR_CLIENT_ID,
  client_secret: YOUR_CLIENT_SECRET

var redirect_uri = '';

exports.authorize_user = function(req, res) {
  res.redirect(api.get_authorization_url(redirect_uri, { scope: ['likes'], state: 'a state' }));

exports.handleauth = function(req, res) {
  api.authorize_user(req.query.code, redirect_uri, function(err, result) {
    if (err) {
      res.send("Didn't work");
    } else {
      console.log('Yay! Access token is ' + result.access_token);
      res.send('You made it!!');

// This is where you would initially send users to authorize
app.get('/authorize_user', exports.authorize_user);
// This is your redirect URI
app.get('/handleauth', exports.handleauth);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));

###Using the API

Once you've setup the API and/or authenticated, here is the full list of what you can do:

/*            USERS             */
ig.user('user_id', function(err, result, remaining, limit) {});

/* OPTIONS: { [count], [min_id], [max_id] }; */
ig.user_self_feed([options,] function(err, medias, pagination, remaining, limit) {});

/* OPTIONS: { [count], [min_timestamp], [max_timestamp], [min_id], [max_id] }; */
ig.user_media_recent('user_id', [options,] function(err, medias, pagination, remaining, limit) {});

/* OPTIONS: { [count], [min_timestamp], [max_timestamp], [min_id], [max_id] }; */
ig.user_self_media_recent([options,] function(err, medias, pagination, remaining, limit) {});

/* OPTIONS: { [count], [max_like_id] }; */
ig.user_self_liked([options,] function(err, medias, pagination, remaining, limit) {});

/* OPTIONS: { [count] }; */
ig.user_search('username', [options,] function(err, users, remaining, limit) {});

/*         RELATIONSHIP         */
/* OPTIONS: { [count], [cursor] }; */
ig.user_follows('user_id', function(err, users, pagination, remaining, limit) {});

/* OPTIONS: { [count], [cursor] }; */
ig.user_followers('user_id', function(err, users, pagination, remaining, limit) {});

ig.user_self_requested_by(function(err, users, remaining, limit) {});

ig.user_relationship('user_id', function(err, result, remaining, limit) {});

ig.set_user_relationship('user_id', 'follow', function(err, result, remaining, limit) {});

/*           MEDIAS             */
/********************************/'media_id', function(err, media, remaining, limit) {});

/* OPTIONS: { [min_timestamp], [max_timestamp], [distance] }; */
ig.media_search(48.4335645654, 2.345645645, [options,] function(err, medias, remaining, limit) {});

ig.media_popular(function(err, medias, remaining, limit) {});

/*           COMMENTS           */
ig.comments('media_id', function(err, result, remaining, limit) {});

ig.add_comment('media_id', 'your comment', function(err, result, remaining, limit) {});

ig.del_comment('media_id', 'comment_id', function(err, remaining, limit) {});

/*            LIKES             */
ig.likes('media_id', function(err, result, remaining, limit) {});

ig.add_like('media_id', function(err, remaining, limit) {});

ig.del_like('media_id', function(err, remaining, limit) {});

/*             TAGS             */
ig.tag('tag', function(err, result, remaining, limit) {});

/* OPTIONS: { [min_tag_id], [max_tag_id] }; */
ig.tag_media_recent('tag', [options,] function(err, medias, pagination, remaining, limit) {});

ig.tag_search('query', function(err, result, remaining, limit) {});

/*           LOCATIONS          */
ig.location('location_id', function(err, result, remaining, limit) {});

/* OPTIONS: { [min_id], [max_id], [min_timestamp], [max_timestamp] }; */
ig.location_media_recent('location_id', [options,] function(err, result, pagination, remaining, limit) {});

/* SPECS: { lat, lng, [foursquare_v2_id], [foursquare_id] }; */
/* OPTIONS: { [distance] }; */
ig.location_search({ lat: 48.565464564, lng: 2.34656589 }, [options,] function(err, result, remaining, limit) {});

/*          GEOGRAPHIES         */
/* OPTIONS: { [min_id], [count] } */
ig.geography_media_recent(geography_id, [options,] function(err, result, pagination, remaining, limit) {});

/*         SUBSCRIPTIONS        */
ig.subscriptions(function(err, result, remaining, limit){});

ig.del_subscription({id:1}, function(err,subscriptions,limit){})

/* OPTIONS: { [verify_token] } */
ig.add_tag_subscription('funny', 'http://MYHOST/tag/funny', [options,] function(err, result, remaining, limit){});

/* OPTIONS: { [verify_token] } */
ig.add_geography_subscription(48.565464564, 2.34656589, 100, 'http://MYHOST/geography', [options,] function(err, result, remaining, limit){});

/* OPTIONS: { [verify_token] } */
ig.add_user_subscription('http://MYHOST/user', [options,] function(err, result, remaining, limit){});

/* OPTIONS: { [verify_token] } */
ig.add_location_subscription(1257285, 'http://MYHOST/location/1257285', [options,] function(err, result, remaining, limit){});


Subscriptions are callbacks from Instagram to your app when new things happen. They should be web-accessable, and return req.query['hub.challenge']on GET. Read more here. After you subscribe, Instagram will calllback your web URL whenever a new post, user action, etc happens.

You can get your subscriptions with this:

ig.subscriptions(function(err, subscriptions, remaining, limit){

You can delete all your subscriptions with this:

ig.del_subscription({ all: true }, function(err, subscriptions, remaining, limit){});

or just one with this:

ig.del_subscription({ id: 1 }, function(err, subscriptions, remaining, limit){});


When errors occur, you receive an error object with default properties, but we also add some other things:

// Available when the error comes from Instagram API
err.code;                // code from Instagram
err.error_type;          // error type from Instagram
err.error_message;       // error message from Instagram

// If the error occurs while requesting the API
err.status_code;         // the response status code
err.body;                // the received body


err.retry(); // Lets you retry in the same conditions that before


When you use functions like user_media_recentor tag_media_recent, you will get a paginationobject in your callback. This object is basically the same that Instagram would give you but there will be a next()function that let you retrieve next results without caring about anything.

var ig = require('instagram-node').instagram();

var hdl = function(err, result, pagination, remaining, limit) {
  // Your implementation here
  if( {; // Will get second page results

ig.tag_media_recent('test', hdl);


Put the following in your environment:


Then just use

make test

More infos

  • You can find more informations on the Instagram developerwebsite.
  • If you have any questions or remark, feel free to contact us at


Distributed under the MIT License.




扫码加入 JavaScript 社区



欢迎加入 JavaScript 社区