I previously wrote a post about how I was syncing Instagram posts to a Ghost blog.

When I transferred everything over to a new EC2 instance, I noticed that my Instagram posts weren't synced correctly.

The way I was doing things was not using official Instagram APIs (they didn't have one at the time). It essentially amounted to scraping data (using a third party library) and Instagram was inevitably going to put a stop to things like this.

It is completely plausible that using methods to hide ones identity could get around any rate limit or IP bans imposed by Instagram but at the end of the day this was meant to be a simple set and forget script running in the background. I forgot about it, it stopped working, and I didn't notice.

I don't want to have to maintain it.

I was researching Instagrams current API situation and noted that they now have the Instagram Basic Display API.

The Instagram Basic Display API allows users of your app to get basic profile information, photos, and videos in their Instagram accounts.

After a brief investigation it was apparent that I could now pull photos from my Instagram account (or anyone elses if they authenticated themselves). I could then post the photos to my Ghost blog (this) in a similar way to how I did it before.

Ghost API

As well as changes to the availability of an Instagram API, Ghost have also updated their API offering and provide a number of packages to simplify interacting with it.

Ghost offers both a Content API and an Admin API. I chose to use their Javascript client to interact with their admin-api to upload photos/videos and submit posts.


As before the (conceptual) process was simple:

  • Get photo data from Instagram
  • Download the photos
  • Upload photos to my server (specifically the Ghost directory using their API)
  • Submit 'posts' to my Ghost blog through their API.

I achieved this with a single, simple node script. It's a bit scrappy but it does the job. A brief explanation can be found below.

I created an Instagram App in the Facebook developer console (as outlined here) and created a test user (this suffices for my needs as I only need to get my own data). You could however implement the full authorisation flow to collect data from other users Instagram profiles.

I pulled data from the API and stored it in a mysql database. This allows me to keep track of what data I have pulled from Instagram and as to whether I have posted it to my blog. It also allows me to process data in a recoverable manner based on the type of Instagram post.

I downloaded the photos to my server using a simple npm package that I found with a quick search (why reinvent the wheel).

At this point I realised that I also posted videos to Instagram. I similarly downloaded these.

Next I uploaded these photos/videos to my ghost directory on my web server. Annoyingly the ghost API has only been built to allow image uploads. It checks for the file format in a configuration file, so a quick modification of the allowed file types will allow you to upload mp4 videos.

Finally you send a POST request to the posts API endpoint with the title, post data, tags, publication date etc.

I choose to add an instagram tag to all posts pulled from Instagram such that I can filter them out from the main display of posts (using a routes.yaml file) so that I don't spam readers with my (more regular) Instagram posts. Readers specifically have to visit my Instagram page to see Instagram posts.

One constraint that I did come up against was the format of the post that I was submitting to the API. Initially I tried to submit my post formatted as html such that I could simply append img and video tags for each Instagram post item. Unfortunately the html to mobiledoc functionality of the client wasn't working with video tags and as such I decided to manually build the mobiledoc data for my posts.