How to authenticate Instagram in a command line application

Instagram

Instagram uses OAuth to authenticate, meaning it can be kind of a drag to use its API if you don't want to build a web application. Building the simplest interface you can build to achieve your application's goals is one of the best ways to streamline your development process. And the simplest and cheapest interface is often the command line.

But because the OAuth handshake requires a web callback to operate, it can be cumbersome to build this authentication into a command line application. Below, I'll show you how to do it with only a little bit of annoyance.

Create an Instagram API Client

First, you'll want to go ask Instagram nicely for an API Client ID so you can get access to the Instagram API. Go to their developer portal and click 'Manage Clients' to add a new one.

When asked for URL's, feel free to use non-existent domains. I use guilded.dev for mine.

In the Security tab, be sure to uncheck "Disable implicit OAuth". This will allow you to connect to the API without requiring an explicit server-side post, meaning we can hijack the access token from the callback URL:

Uncheck 'Disable implicit OAuth'

Make a Firm Handshake

So what are you to do when you can't redirect your terminal window to Instagram so you can authorize your account? A little bit of copy-pasta. Here's what we're going to do:

  1. Generate an Instagram authorization URL and ask the user to paste it into their browser.
  2. The user will authenticate their Instagram account like usual. They'll be redirected to our dummy Redirect URI.
  3. We'll prompt the user for their newly-issued access token. Because we unchecked "Disable implicit OAuth" in our Instagram client configuration, the access token will be appended to the redirect URI. We'll ask them kindly to copy and paste it into the terminal.
  4. We'll be authenticated to Instagram in the terminal!
require 'instagram'

Instagram.configure do |config|
  config.client_id = "YOUR CLIENT ID"
  config.client_secret = "YOUR CLIENT SECRET"
end

# Generate an Instagram authorization URL
puts "Visit the Instagram OAuth URL below to get started:\n"
puts "" + ::Instagram.authorize_url(
  redirect_uri: "http://guilded.dev/instagram/callback"
  response_type: 'token'
)

# Prompt the user for their newly-issued access token.
puts "Enter the access token at the end of the redirect URL.\nYou'll find it after the '#access_token=' in the URL."
access_token = gets.strip

# Create an Instagram client with the access token.
client = Instagram.client(access_token: access_token)

Now you should have an authenticated Instagram client. Use the Ruby Instagram API as usual:

for media_item in client.user_recent_media
  puts media_item.images.thumbnail.url
end

Store Your Access Token

Of course, requiring entering the access token each time we use our Instagram command line application is going to annoy our user. What if we could store the access token on the first authentication so we could use it for subsequent runs?

For this example, we'll store the access token in a file called .instagram-access-token. Depending on your application, you might want to use an existing YAML configuration file or another method.

require 'instagram'

# Configure the Instagram gem the same way we did above:
Instagram.configure do |config|
  config.client_id = settings.instagram_client_id
  config.client_secret = settings.instagram_client_secret
end

# If there's an access token saved to the file, then read it.
if File.exists?(".instagram-access-token")
  access_token = File.read(".instagram-access-token")
else
  # Otherwise, generate one
  puts "Visit the Instagram OAuth URL below to get started:\n"
  puts "" + ::Instagram.authorize_url(
    redirect_uri: "http://guilded.dev/instagram/callback"
    response_type: 'token'
  )

  # Prompt the user for their newly-issued access token.
  puts "Enter the access token at the end of the redirect URL.\nYou'll find it after the '#access_token=' in the URL."
  access_token = gets.strip

  # And save the token to the file for the next use:
  File.open(".instagram-access-token", 'w') do |file|
    file.write(access_token)
  end
end

# Create an Instagram client with the access token.
client = Instagram.client(access_token: access_token)

As you can see above, we first check to see if there's an access token saved in our .instagram-access-token file. If there is, we skip the handshake process altogether. If not, we initiate the handshake.

Note that for the purposes of simplifying the example, I've left out some error handling for invalid access tokens. You'll want to verify that the access token stored is valid and go through the handshake process again if you cannot connect.

Conclusion

Building a command line application for Instagram is fairly easy, assuming you're able to build the authentication in a way that doesn't confuse your user. If you're just building a tool for personal use, this is a great way to create real value without incurring the burden of building a full-blown web application.

If you have questions or if something is unclear, please leave a comment below and I'll do my best to answer you.