Instagram Business Account Media Analytics Extractor

Comprehensive Data Extraction for Instagram Posts, Including Likes, Comments, Views, Reach, and Total Interactions

Category: Social Media Analytics, API Integration, Data Extraction, Python Development
Tools & Technologies: Python, Instagram Graph API (via Facebook Graph API), `requests`, `json`, Data Processing, API Automation, Visual Studio Code, Google Colab

Status: Completed

Introduction

This project leverages the Instagram Graph API (accessed through the Facebook Graph API) to provide a detailed analytics suite for Instagram business accounts. It efficiently retrieves account information, lists recent media posts with their basic engagement counts (likes, comments), and crucially, fetches comprehensive insights for each media item. This includes metrics like views, reach, saves, shares, and total interactions, while gracefully handling metrics that may not be available for older posts. The output is structured for clarity, offering both raw data for archival and a summarized view of key performance indicators, enabling a deep understanding of content performance on Instagram.


Aim and Objectives

Aim:
To develop a Python script for extracting comprehensive analytics of Instagram business account media using the Instagram Graph API.

Objectives:

  1. Fetch basic account information (username, followers, media count).
  2. Retrieve a list of recent Instagram posts with captions, media URLs, and engagement counts (likes, comments).
  3. Fetch detailed insights for each media post, including views, reach, saves, shares, and total interactions.
  4. Handle cases where specific metrics are unavailable for certain posts by indicating "Not Available".
  5. Structure the collected data into a comprehensive format for analysis and reporting.
  6. Save the analytics data into JSON files.

Features & Deliverables

  • Account Information: Retrieves essential details like username, follower count, and media count.
  • Media List: Fetches recent posts with captions, media URLs, timestamps, like counts, and comment counts.
  • Detailed Post Insights: Collects metrics such as views, reach, saves, shares, and total interactions for each post.
  • Graceful Metric Handling: Accurately reports "Not Available" for metrics not supported by a particular post.
  • Comprehensive Analytics: Organizes data into `post_details`, `insights`, and a `summary` object for each media item.
  • Data Persistence: Generates `instagram_analytics.json` (comprehensive analytics) and `instagram_analytics_all_data.json` (all fetched data).

Code Implementation

The project employs a Python class, `InstagramGraphAPI`, designed to interact with the Instagram Graph API. It uses the `requests` library for API calls and `json` for data handling. The script is structured to fetch account info, media lists, and detailed insights for individual media items, with robust error management.

View Python Script (Instagram Analytics)
import requests
import json
from datetime import datetime

class InstagramGraphAPI:
    def __init__(self, access_token, instagram_business_account_id):
        self.access_token = access_token
        self.instagram_business_account_id = instagram_business_account_id
        self.base_url = "https://graph.facebook.com/v19.0"

    def get_account_info(self):
        url = f"{self.base_url}/{self.instagram_business_account_id}"
        params = {'fields': 'username,name,profile_picture_url,followers_count,follows_count,media_count', 'access_token': self.access_token}
        response = requests.get(url, params=params)
        return self._handle_response(response)

    def get_media_list(self, limit=25):
        url = f"{self.base_url}/{self.instagram_business_account_id}/media"
        params = {'fields': 'id,caption,media_type,media_url,permalink,timestamp,username,like_count,comments_count', 'limit': limit, 'access_token': self.access_token}
        response = requests.get(url, params=params)
        return self._handle_response(response)

    def get_media_insights(self, media_id):
        all_possible_metrics = ['views', 'reach', 'saved', 'likes', 'comments', 'shares', 'total_interactions']
        formatted_insights = {}
        for metric in all_possible_metrics:
            url = f"{self.base_url}/{media_id}/insights"
            params = {'metric': metric, 'access_token': self.access_token}
            response = requests.get(url, params=params)
            insight_data = self._handle_response(response, supress_error_print=True)
            if insight_data and 'data' in insight_data and insight_data['data']:
                value = insight_data['data'][0].get('values', [{}])[0].get('value', 0)
                formatted_insights[metric] = value
            else:
                formatted_insights[metric] = "Not Available"
        return formatted_insights

    def get_media_details(self, media_id):
        url = f"{self.base_url}/{media_id}"
        params = {'fields': 'id,caption,media_type,media_url,permalink,timestamp,username,like_count,comments_count,ig_id', 'access_token': self.access_token}
        response = requests.get(url, params=params)
        return self._handle_response(response)

    def get_comprehensive_post_analytics(self, media_id):
        post_details = self.get_media_details(media_id)
        if not post_details:
            return None
        insights = self.get_media_insights(media_id)
        comprehensive_data = {
            'post_details': post_details,
            'insights': insights if insights else "Insights could not be fetched.",
            'summary': {
                'likes': post_details.get('like_count', 0),
                'comments': post_details.get('comments_count', 0),
                'views': insights.get('views', 0) if insights else 0,
                'reach': insights.get('reach', 0) if insights else 0,
                'saved': insights.get('saved', 0) if insights else 0,
                'shares': insights.get('shares', 0) if insights else 0,
                'total_interactions': insights.get('total_interactions', 0) if insights else 0,
            }
        }
        return comprehensive_data

    def _handle_response(self, response, supress_error_print=False):
        if response.status_code == 200:
            return response.json()
        if not supress_error_print:
            try:
                error_data = response.json()
                error_message = error_data.get('error', {}).get('message', 'No error message provided.')
                print(f"API Error ({response.status_code}): {error_message}")
            except json.JSONDecodeError:
                print(f"API Error ({response.status_code}): {response.text}")
        return None

def setup_instagram_api():
    ACCESS_TOKEN = "YOUR_ACCESS_TOKEN" # Replace with your Access Token
    INSTAGRAM_BUSINESS_ACCOUNT_ID = "YOUR_INSTAGRAM_BUSINESS_ACCOUNT_ID" # Replace with your Instagram Business Account ID
    if not ACCESS_TOKEN or not INSTAGRAM_BUSINESS_ACCOUNT_ID:
        print("!!! ERROR: Credentials are not set in setup_instagram_api() !!!")
        return None
    return InstagramGraphAPI(ACCESS_TOKEN, INSTAGRAM_BUSINESS_ACCOUNT_ID)

if __name__ == "__main__":
    print("Instagram Graph API Analytics Fetcher")
    print("=" * 50)
    api = setup_instagram_api()
    terminal_log_data = {}
    if api:
        account_info = api.get_account_info()
        if account_info:
            print(json.dumps(account_info, indent=2))
            terminal_log_data['account_info'] = account_info
        media_list = api.get_media_list(limit=10)
        if media_list:
            print(json.dumps(media_list, indent=2))
            terminal_log_data['media_list'] = media_list
        if media_list and 'data' in media_list:
            all_posts_analytics = []
            print("\\n\\n--- Comprehensive Analytics for all posts ---")
            for post in media_list['data']:
                post_analytics = api.get_comprehensive_post_analytics(post['id'])
                if post_analytics:
                    all_posts_analytics.append(post_analytics)
            print(json.dumps(all_posts_analytics, indent=4))
            terminal_log_data['comprehensive_analytics'] = all_posts_analytics
            with open("instagram_analytics.json", 'w') as f:
                json.dump(all_posts_analytics, f, indent=4)
            print("\\n==================================================")
            print(f"SUCCESS: Comprehensive analytics saved to instagram_analytics.json")
            with open("instagram_analytics_all_data.json", 'w') as f:
                json.dump(terminal_log_data, f, indent=4)
            print(f"SUCCESS: Full terminal log saved to instagram_analytics_all_data.json")
            print("==================================================")
        else:
            print("\\nCould not find any media to analyze.")
    else:
        print("\\nAPI initialization failed. Please check your credentials.")

Results & Impact

  • Detailed Media Performance: Provided granular insights into the performance of individual Instagram posts, enabling content strategy optimization.
  • Account Health Overview: Captured essential account-level metrics for monitoring growth and engagement trends.
  • Data-Driven Decisions: Enabled users to make informed decisions based on concrete performance data, identifying high-performing content and engagement patterns.
  • Automated Data Collection: Streamlined the process of gathering Instagram analytics, saving significant manual effort.

Console Output Preview (Instagram Analytics)


Instagram Graph API Analytics Fetcher
==================================================

Fetching Account Info...
{
  "username": "jessetamuno",
  "name": "Jesse",
  "followers_count": 0,
  "follows_count": 3,
  "media_count": 3,
  "id": "17841475434985932"
}

Fetching Recent Media (with like/comment counts)...
{
  "data": [
    {
      "id": "17877864126242839",
      "caption": "Success. An unlimited solution to failure.",
      "media_type": "IMAGE",
      "media_url": "https://scontent-sea1-1.cdninstagram.com/v/t51.75761-15/509631581_17844790116514500_2333752081183462716_n.webp?stp=dst-jpg_e35_tt6&_nc_cat=101&ccb=1-7&_nc_sid=18de74&_nc_eui2=AeF6T7jWsokMY9cNbfWk-YgWEfaSYqbPRmsR9pJips9Ga5wFpZhdo6S2mPImkqcsckNy8KbgiqgXMlvrJxzh0Vr1&_nc_ohc=tNU5haqNjuAQ7kNvwHPQew-&_nc_oc=AdkyVFdkmCYsorXtS8kG4O82LG4kmvbwlMa4c13YWG-4_7Sx1FwkknvOffGNd5qCwis&_nc_zt=23&_nc_ht=scontent-sea1-1.cdninstagram.com&edm=AM6HXa8EAAAA&_nc_gid=E525gQSPmU9uBNe2xf1Y2w&oh=00_AfMwl6M9D4XLCfAliSieoXVRNoBFxbxiLIvM6eIA6O1Rww&oe=686A9895",
      "permalink": "https://www.instagram.com/p/DLMz4i8MMKS/",
      "timestamp": "2025-06-22T10:44:17+0000",
      "username": "jessetamuno",
      "like_count": 2,
      "comments_count": 1
    },
    {
      "id": "18052397816580584",
      "caption": "Success definition - get to the top.",
      "media_type": "IMAGE",
      "media_url": "https://scontent-sea1-1.cdninstagram.com/v/t51.75761-15/503709091_17844635391514500_1950202779653720190_n.webp?stp=dst-jpg_e35_tt6&_nc_cat=104&ccb=1-7&_nc_sid=18de74&_nc_eui2=AeG2mW36WdAvKliwT_ore2wPXCTAFKjgmXpcJMAUqOCZeiO1jGYPWqYN6RnTZum6aGVuLh9Gl_UxLJwWoRxA_pdB&_nc_ohc=SZ9WDccxsp8Q7kNvwHDOGAC&_nc_oc=AdmLy4_tq1F47pudhc4AfKNGHTfEiL7uJfkWH17jpczpNW-dWzjKe9Dg4pHt2eLhy-Y&_nc_zt=23&_nc_ht=scontent-sea1-1.cdninstagram.com&edm=AM6HXa8EAAAA&_nc_gid=E525gQSPmU9uBNe2xf1Y2w&oh=00_AfND6_J3dFWceE6LJ4hyFYNJs5JygDWe9UXI6j6ce2uM9w&oe=686A9033",
      "permalink": "https://www.instagram.com/p/DLKs4NFMf0g/",
      "timestamp": "2025-06-21T15:04:35+0000",
      "username": "jessetamuno",
      "like_count": 2,
      "comments_count": 2
    },
    {
      "id": "18070330238488583",
      "caption": "You got to be serious, please take note.",
      "media_type": "IMAGE",
      "media_url": "https://scontent-sea5-1.cdninstagram.com/v/t51.75761-15/509927686_17844623778514500_8993150707441366049_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=103&ccb=1-7&_nc_sid=18de74&_nc_eui2=AeFm3kZF_A3Bo0GAi31cEGoByvLIk7nQinPK8siTudCKc2BnXB1lc-JbSel51dXqIqDzV2dnWehSIJ1E4C7JO1WQ&_nc_ohc=exJID7w7iUcQ7kNvwG_SOVw&_nc_oc=Adlc_oKJt7sPo_AwXU4FiTbBFlZtbN_7aa_qU9mWIu3vS61U2MU9hNVHG38Y_YVYX5E&_nc_zt=23&_nc_ht=scontent-sea5-1.cdninstagram.com&edm=AM6HXa8EAAAA&_nc_gid=E525gQSPmU9uBNe2xf1Y2w&oh=00_AfPOzh-IEjjftwIwvowtkfzysOsTJZoYCE8hrZdWBqZo8Q&oe=686A9DC8",
      "permalink": "https://www.instagram.com/p/DLKlQjyNNJe/",
      "timestamp": "2025-06-21T13:58:00+0000",
      "username": "jessetamuno",
      "like_count": 2,
      "comments_count": 2
    }
  ],
  "paging": {
    "cursors": {
      "before": "QVFGbXdEd3dCNEpMRlNhLWhGS2Y0UGVuNWwxb0VmR1ZAkTHd1WWQ4Vk1fNlhhanI2RFV6ZAVJLM2RzRTl6UDk2SUc0dE13YXZAOWW1BWGdJaGZAyc18tWWJDVUhR",
      "after": "QVFGbVFTeXJxaHh6Tm81OTVYaGZAiSzlYcXc0YXVld01ZAWnR4ZAlhZAb1BRNnptOFVEVDNqZAHFHTU9zcmlGalp5RGEwVVNQYk1LQk9zYTNPdy1CQjhBWFd5QTJB"
    }
  }
}


--- Comprehensive Analytics for all posts ---
[
    {
        "post_details": {
            "id": "17877864126242839",
            "caption": "Success. An unlimited solution to failure.",
            "media_type": "IMAGE",
            "media_url": "https://scontent-sea1-1.cdninstagram.com/v/t51.75761-15/509631581_17844790116514500_2333752081183462716_n.webp?stp=dst-jpg_e35_tt6&_nc_cat=101&ccb=1-7&_nc_sid=18de74&_nc_eui2=AeF6T7jWsokMY9cNbfWk-YgWEfaSYqbPRmsR9pJips9Ga5wFpZhdo6S2mPImkqcsckNy8KbgiqgXMlvrJxzh0Vr1&_nc_ohc=tNU5haqNjuAQ7kNvwHPQew-&_nc_oc=AdkyVFdkmCYsorXtS8kG4O82LG4kmvbwlMa4c13YWG-4_7Sx1FwkknvOffGNd5qCwis&_nc_zt=23&_nc_ht=scontent-sea1-1.cdninstagram.com&edm=AEQ6tj4EAAAA&_nc_gid=8dMpBGkSbpzALV-vQ7AnxQ&oh=00_AfPYl4lSHryyG5EL-A6FhpbGwFZl7C5IOU_-RCAaYalr-w&oe=686A9895",
            "permalink": "https://www.instagram.com/p/DLMz4i8MMKS/",
            "timestamp": "2025-06-22T10:44:17+0000",
            "username": "jessetamuno",
            "like_count": 2,
            "comments_count": 1,
            "ig_id": "3660528783325184658"
        },
        "insights": {
            "views": 1,
            "reach": 1,
            "saved": 0,
            "likes": 2,
            "comments": 1,
            "shares": 0,
            "total_interactions": 3
        },
        "summary": {
            "likes": 2,
            "comments": 1,
            "views": 1,
            "reach": 1,
            "saved": 0,
            "shares": 0,
            "total_interactions": 3
        }
    },
    {
        "post_details": {
            "id": "18052397816580584",
            "caption": "Success definition - get to the top.",
            "media_type": "IMAGE",
            "media_url": "https://scontent-sea1-1.cdninstagram.com/v/t51.75761-15/503709091_17844635391514500_1950202779653720190_n.webp?stp=dst-jpg_e35_tt6&_nc_cat=104&ccb=1-7&_nc_sid=18de74&_nc_eui2=AeG2mW36WdAvKliwT_ore2wPXCTAFKjgmXpcJMAUqOCZeiO1jGYPWqYN6RnTZum6aGVuLh9Gl_UxLJwWoRxA_pdB&_nc_ohc=SZ9WDccxsp8Q7kNvwHDOGAC&_nc_oc=AdmLy4_tq1F47pudhc4AfKNGHTfEiL7uJfkWH17jpczpNW-dWzjKe9Dg4pHt2eLhy-Y&_nc_zt=23&_nc_ht=scontent-sea1-1.cdninstagram.com&edm=AEQ6tj4EAAAA&_nc_gid=Un_4XhTX6cM6WXpbpuAJ2Q&oh=00_AfN4lCqqBJhag_vDHNfgTs_8fu06sS5tw8RkNW7TtiWLyQ&oe=686A9033",
            "permalink": "https://www.instagram.com/p/DLKs4NFMf0g/",
            "timestamp": "2025-06-21T15:04:35+0000",
            "username": "jessetamuno",
            "like_count": 2,
            "comments_count": 2,
            "ig_id": "3659935023574940960"
        },
        "insights": {
            "views": 3,
            "reach": 0,
            "saved": 0,
            "likes": 2,
            "comments": 2,
            "shares": 0,
            "total_interactions": 4
        },
        "summary": {
            "likes": 2,
            "comments": 2,
            "views": 3,
            "reach": 0,
            "saved": 0,
            "shares": 0,
            "total_interactions": 4
        }
    },
    {
        "post_details": {
            "id": "18070330238488583",
            "caption": "You got to be serious, please take note.",
            "media_type": "IMAGE",
            "media_url": "https://scontent-sea5-1.cdninstagram.com/v/t51.75761-15/509927686_17844623778514500_8993150707441366049_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=103&ccb=1-7&_nc_sid=18de74&_nc_eui2=AeFm3kZF_A3Bo0GAi31cEGoByvLIk7nQinPK8siTudCKc2BnXB1lc-JbSel51dXqIqDzV2dnWehSIJ1E4C7JO1WQ&_nc_ohc=exJID7w7iUcQ7kNvwG_SOVw&_nc_oc=Adlc_oKJt7sPo_AwXU4FiTbBFlZtbN_7aa_qU9mWIu3vS61U2MU9hNVHG38Y_YVYX5E&_nc_zt=23&_nc_ht=scontent-sea5-1.cdninstagram.com&edm=AM6HXa8EAAAA&_nc_gid=svFZ8tHFvvUYpd4VOSTo0A&oh=00_AfPE-ic0lecktEPNWKnQMw1nKlwEge11U8Qih5avtAtoaA&oe=686A9DC8",
            "permalink": "https://www.instagram.com/p/DLKlQjyNNJe/",
            "timestamp": "2025-06-21T13:58:00+0000",
            "username": "jessetamuno",
            "like_count": 2,
            "comments_count": 2,
            "ig_id": "3659901512847774302"
        },
        "insights": {
            "views": "Not Available",
            "reach": "Not Available",
            "saved": "Not Available",
            "likes": "Not Available",
            "comments": "Not Available",
            "shares": "Not Available",
            "total_interactions": "Not Available"
        },
        "summary": {
            "likes": 2,
            "comments": 2,
            "views": "Not Available",
            "reach": "Not Available",
            "saved": "Not Available",
            "shares": "Not Available",
            "total_interactions": "Not Available"
        }
    }
]

==================================================
SUCCESS: Comprehensive analytics saved to instagram_analytics.json
SUCCESS: Full terminal log saved to instagram_analytics_all_data.json
==================================================

Process / Methodology

API Interaction and Data Retrieval

  • Instagram Graph API: Accessed Instagram's business features through the Facebook Graph API (v19.0).
  • Authentication: Used an Access Token associated with an Instagram Business Account.
  • Account Information: Fetched details like username, follower count, and media count using the Business Account ID.
  • Media Listing: Retrieved a list of recent media items (posts, stories, reels) using the `/media` endpoint, including fields like `id`, `caption`, `media_type`, `media_url`, `permalink`, `timestamp`, `username`, `like_count`, and `comments_count`.
  • Media Insights: For each media item, called the `/insights` endpoint to fetch specific metrics such as `views`, `reach`, `saved`, `likes`, `comments`, `shares`, and `total_interactions`.

Data Processing and Structuring

  • Comprehensive Post Analytics: For each media item, a detailed dictionary was created containing `post_details` (from `get_media_details`) and `insights` (from `get_media_insights`).
  • Summary Generation: A `summary` object was generated for each post, extracting key engagement metrics (likes, comments, views, reach, saved, shares, total interactions).
  • Unavailable Metrics: Implemented logic to mark metrics as "Not Available" if the API did not return a value for a specific post, ensuring data completeness.
  • Error Handling: Utilized a `_handle_response` method to manage API errors and provide informative feedback.

Output Generation

  • Comprehensive Analytics: Saved the processed data into `instagram_analytics.json`, providing a structured list of analytics for each media item.
  • Raw Data Archival: Created `instagram_analytics_all_data.json` to store all fetched data, including account information and the raw media list, for complete historical records.

Challenges & Solutions

  • Challenge: Some metrics (like 'shares') might not be available for older posts or specific media types.
    Solution: The `get_media_insights` function is designed to check the API response and assign "Not Available" to metrics that are not returned, ensuring the output is consistent and informative.
  • Challenge: Managing API access tokens and Business Account IDs correctly.
    Solution: Strict adherence to API documentation for authentication and endpoint usage, with placeholders for sensitive credentials in the code.
  • Challenge: Parsing varied data structures returned by the API.
    Solution: Employed robust JSON parsing and dictionary access with `.get()` methods to safely extract data, preventing errors from missing keys.

What I Learned

  • Gained practical experience with the Instagram Graph API for business analytics.
  • Mastered techniques for fetching and processing diverse social media data.
  • Enhanced skills in handling API responses, including error conditions and missing data points.
  • Understood the importance of structured data output for effective analysis and reporting.

Demonstration / Access


Future Enhancements

  1. Implement an automated scheduler for regular data collection.
  2. Develop a web-based dashboard for interactive visualization of Instagram analytics.
  3. Integrate sentiment analysis for comments to gauge audience reaction.
  4. Expand to include analytics for Instagram Stories and Reels.

Thank You for Reviewing My Instagram Analytics Project

I appreciate you exploring my work on the Instagram Graph API. This project highlights my ability to extract meaningful insights from social media platforms, essential for effective digital marketing and content strategy.

For any questions or collaboration opportunities, please reach out via my Contact section. Your feedback is invaluable.

Best regards,
Damilare Lekan Adekeye