How to Create an Instagram Photo Printing App in Node.js

Instagram API Lob API Nodejs Tutorial

In this tutorial, I will walk you through the process of creating a Node.js web application that will print and mail a 4x4 Instagram photo. The web application will allow a user to log in to their Instagram account, randomly choose a recent photo from their Feed, and then provide a shipping address to mail the photo.

View Demo

The app will be written in Node.js and will use the very popular Express.js Framework. We will be starting with a blank project, and by the end will have a fully functioning web application.
We will be using two main APIs to build this application. The Instagram API, which will allow us to log in to an Instagram account and select images from a user’s recent feed, and the Lob Print & Mail API, which will handle the printing and shipping of our 4x4 Instagram photos.

NOTE: This whole project is available in a public repository on GitHub. I suggest downloading it first and taking a look at the code before continuing the tutorial.

The Main Pieces


You will need the following before you can start this tutorial:

  • A basic understanding of Node.js and JavaScript.
  • A basic understanding of how JavaScript Promises work. If you haven’t used them before don’t worry, here’s a quick guide.
  • NPM and Node.js installed.
  • A Lob API Key.
  • A registered Instagram Developer account.

Instagram Registration

In order to use the Instagram API, you need to first register your application at the developer center. Once you have registered your application, they will provide you with a client_id and a client_secret, which we will need later.

Part of the registration form will ask for a redirect_uri. This is where the user will be redirected after they successfully sign into their Instagram account. For now, set this value to http://localhost:3000/handleauth, which will point to our local app during development.

Lob Registration

Sign up for a free Lob account by visiting the registration page. Once registered, you can find your Test API Key on the settings page. The Test API Key works the same as the Live, but no mail is actually printed or shipped until you use your Live API Key.

Create Project

If you already have an express.js project setup you can skip the the next section. If not, open up a terminal and let’s get started. 

mkdir instagram && cd instagram
npm init

When you run npm init it will ask you a bunch of questions; just press enter for all of them except when it asks you for entry point: (index.js); set that to app.js.

Install Dependencies

npm i express --save
npm i bluebird --save
npm i body-parser --save
npm i cookie-parser --save
npm i instagram-node --save
npm i jade --save
npm i lob --save

These are all the node modules we will be using to create the Instagram photo printing app.

Create Server

Create a file called app.js file in the root directory of your project.

var express       = require('express');
var path          = require('path');
var cookieParser  = require('cookie-parser');
var bodyParser    = require('body-parser');
var instagram     = require('./instagram');
var app           = express();

/* App Setup */
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(bodyParser.urlencoded({ extended: false }));

/* Include our Instagram Module */
app.use('/', instagram);

app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'),  Function() {
  console.log('Express server listening on port ' + server.address().port);

module.exports = app;

Notice we are telling the app to run on port 3000. This matches up with the redirect URL you submitted when registering your Instagram app.

Template Files

Create a folder called views in the root directory of your project, next to the app.js file. This is where we will place the following Jade template files. If you haven’t used Jade before it’s a pretty simple templating engine that comes by default with Express.js. Learn more here.

We are also using Bootstrap to provide basic styling and layout for the application. Check out the Bootstrap website for more information on the CSS classes we are using in the template files.


Create a file called layout.jade with the following code. This is the basic HTML structure for our app.

doctype html
    title Instagram Photo Printer
    link(rel='stylesheet', href='')


        a.navbar-brand(href="/") Instagram Photo Printer

    div. Container
      block content


Create a file called index.jade inside the views folder with the following code. Notice that we are using a template variable called showLogin. If this is true, we are going to show the user a button so that they can log in to their Instagram account. Otherwise, we will show them a random picture from their account and shipping form for their Instagram photo.

Don’t worry too much about this right now. It will make more sense once we start writing code.

extends layout

block content

  if showLogin
        h1 Instagram Photo Printer
        p Before you can print and mail a photo, you need to authorize your Instagram account.
        a(href="/authorize-user" class="btn btn-primary") Login to Instagram
        img(src= image, width="250px")
          a.btn.btn-default(href="/") Random Photo

        h1 Print & Mail Photo

        form(action="/send-photo", method="post")
          div(class="form-group col-md-12")
            label Name
          div(class="form-group col-md-12")
            label Address
          div(class="form-group col-md-4")
            label City
          div(class="form-group col-md-4")
            label State
          div(class="form-group col-md-4")
            label Zip
          div(class="form-group col-md-12")
            input(type="hidden", value=image, name="image")
            button(type="submit", class="btn btn-primary") Mail Photo >


The last template file we will need is complete.jade, which will show a success message and a preview link once the user has successfully filled out the form. If there was an error, it will show that as well.

extends layout

block content
      if error
          p= error
          p Success! Your photo has been sent. You can see a preview here:
            a(href=url, target="_blank")= url

      a.btn.btn-primary(href="/") Send Another Photo

Be sure to read the next Photos article: How to Create Responsive Image Breakpoints with the Cloudinary API