· 5 min read python instagram fediverse indieweb

Giving up on Instagram and moving to a federated web

I created my first website on GeoCities in 1996 to show off some of my photography. At the time, it was a lot of metalheads at shows because that was my scene. I wish I had a copy of it because it was glorious. It was filled with animated gifs and was part of a webring, and it supported Netscape and Internet Explorer - take that modern web! Apologies if you didn’t experience that time.

A couple people on stage during a concert. The exposure is a bit long leading to multiple ghost outlines of each person.
An early photograph of mine. It is so old that it was shot on film. This was probably digitized in 2002 and I thought to myself, "Yeah a 300kb image will be enough for the long term. It was not."

For the following 2+ decades, although I’ve always had my own website, I continuously used other services to share content. Myspace, Friendster, Orkut, Jaiku, Twitter, Flickr - I was on ALL of them. When Instagram launched, I was one of the android folks that had to wait patiently for it to make it to my device.

Software morals

I’m a big proponent of open source / libre software and have been doing my best since the early 2000s to always choose it over anything proprietary - so my morals have been conflicted over the use of things like Facebook and Instagram, in particular. I stopped using Facebook many years ago, despite the attempts of my father every time I see him. A coworker referred to me as a tech-hippie.

Instagram was so easy

A few years ago, I decided that I was going to take a photo every day that was worth sharing and unfortunately I used Instagram to document that process. It was so easy to post and to get engagement. So here I am trying to close down my account and trying to figure out how to move all those photos to my own website because…

IndieWeb

I’m nostalgic for the early web, where we all had our own unique spaces outside of social networks. While you all have been out protesting reddit and looking for places to make new communities, I was working on making this site a part of the federated web. I’m sure I’ll follow up with more about in the near future - this is about how I migrated off of Instagram and am finally trying to take back my own content. No one captures my feelings about the web more than Catherynne Valente in her article: Stop Talking to Each Other and Start Buying Things. Go read it.

The migration plan

All I needed was to get all my data out of Instagram and into Hugo templates, so my plan was pretty simple:

  1. Export all my data from Instagram in JSON (they make it easy, but the process always changes so just Google DuckDuckGo it.)
  2. Copy all the images onto my website (I use Hugo, so I dropped all of them into my image folder basically. Lol.)
  3. Write some code to parse the JSON, grab the metadata that I would need, and then output individual markdown files in the template that Hugo would expect.
  4. Spend several hours using a combination of ChatGPT and Google to figure out how to write code that’s not JavaScript (hey, I don’t venture out much.)
  5. Publish!

Using Python to Create Hugo Posts

And this is how I pulled it off.

import json
import datetime
import os

# Read the JSON file
with open('posts_1.json') as file:
    data = json.load(file)

# Iterate over the data and grab everything we will need
for i, item in enumerate(data, start=1):
    media = item['media'][0]
    uri = media['uri']
    title = media['title']
    timestamp = media['creation_timestamp']

    # Name the file that we will be creating (Note, these files are created in
    # the same directory as the python script)
    filename = f"instagram_{i}.md"

    # The timestamp in the JSON isn't what I need for Hugo, so reformat!
    dt = datetime.datetime.fromtimestamp(timestamp)
    formatted_dt = dt.strftime('%Y-%m-%dT%H:%M:%S%z')

    # Images have the directory structure defined in the URL when getting this
    # data. I'm removing it so that it is just the actual file name. Hugo's
    # templates take care of where that image is (I copied all the images to
    # that folder).
    image_name = os.path.basename(uri)
    image_name = os.path.splitext(image_name)[0]

    # Create the markdown file in the format / template that Hugo would expect.
    # with open(filename, 'w') as md_file:
        md_file.write(f"---\n")
        md_file.write(f"title: 'Instagram-{i}'\n")
        md_file.write(f"date: {formatted_dt}-04:00\n")
        md_file.write(f"draft: false\n")
        md_file.write(f"statusimage: '{image_name}.jpg'\n")
        md_file.write(f"categories: ["photos"]\n")
        # You should get the point here...
        md_file.write(f"---\n")

# When it's done, let's not only inform ourselves that it worked, but let's also
# add in some words of encouragement.
print("Wow, I did it. I made all the files for you. You're so smart, now go do more amazing things.")

The big reveal

So, that was only half the battle. I spent a good number of hours actually coding an image gallery. In the end, I was able to get 1500 images moved over. So that this was all actually worth it, check out my collection of photos.

For now, there is still work to do. The thumbnail images are huge and need to be optimized, and I will need to do a better job curating the good ones. However, from here on out, the next time you see an image of mine on the internet, its home will be here, on my own website.