Tutorials

How to Scrape Instagram Data with Python in 2026

Learn how to reliably extract public data from Instagram using Python. Master dynamic content rendering and handle rate limits securely.

Yash Dubey
Yash Dubey

April 23, 2026

5 min read
4 views

Disclaimer: This guide covers extracting publicly accessible data. Always review a site's robots.txt and Terms of Service before scraping.

Extracting structured data from Instagram requires handling dynamic web applications. The platform relies on JavaScript to render content and loads data asynchronously via GraphQL. A standard HTTP GET request returns a bare HTML shell.

This guide details the technical pipeline for retrieving public profile metrics, hashtag data, and post metadata using Python. We cover handling headless browsers, locating embedded JSON state, and managing request infrastructure.

1. Why collect social data from Instagram?

Engineering teams build data pipelines for Instagram to support internal analytics. Raw social data feeds multiple business functions when collected responsibly from public pages.

Brand monitoring Companies track brand sentiment across public posts and comments. Analyzing public engagement metrics provides a quantitative baseline for marketing campaigns.

Influencer discovery Agencies aggregate public follower counts, engagement ratios, and niche keywords. This data helps identify accounts that match specific audience criteria without manual review.

Competitive analysis Retailers monitor competitor accounts to track post frequency, public hashtag strategies, and engagement trends. Structured extraction converts social activity into queryable database rows.

2. Technical challenges

Scraping Instagram presents specific infrastructure hurdles. The platform employs sophisticated access controls to prevent automated abuse.

Dynamic Rendering Instagram operates as a Single Page Application (SPA). Content does not exist in the initial HTML payload. The browser must execute React JavaScript bundles, which trigger subsequent XHR/Fetch requests to GraphQL endpoints. Your scraping infrastructure must execute JavaScript to see the data.

Rate Limiting Aggressive IP-based rate limits apply to all endpoints. Sending too many requests from a single datacenter IP results in HTTP 429 Too Many Requests or HTTP 403 Forbidden responses.

Client Fingerprinting Modern web applications analyze TLS handshakes, HTTP/2 frames, and browser fingerprints (like Canvas rendering or WebGL). Mismatches between a stated user-agent and the actual TLS fingerprint flag the request as automated. Using an Anti-bot bypass API handles the network-level fingerprinting required to access public endpoints cleanly.

99.2%Public Data Success Rate
1.8sAvg Render Time

3. Quick start with AlterLab API

Building and maintaining a headless browser cluster is expensive. The Getting started guide shows how to offload browser management. You send the target URL. The API returns the rendered HTML or structured JSON.

Install the Python client:

Bash
pip install alterlab

Request a public Instagram profile. We set render_js=True to execute the React application before returning the markup.

Python
import alterlab

client = alterlab.Client("YOUR_API_KEY")

# Request rendering of the SPA
response = client.scrape(
    "https://www.instagram.com/instagram/", 
    render_js=True,
    wait_for=2000 # Wait 2 seconds for initial GraphQL requests to settle
)

print(f"Status: {response.status_code}")
print(f"Content length: {len(response.text)}")

If you prefer shell scripts or are integrating into a different backend, the REST endpoint accepts standard HTTP POST requests.

Bash
curl -X POST https://api.alterlab.io/v1/scrape \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.instagram.com/instagram/", 
    "render_js": true,
    "wait_for": 2000
  }'

4. Extracting structured data

Once you have the rendered HTML, you need to extract the fields. Relying on CSS selectors (.x1lliihq or similar auto-generated class names) is brittle. Utility classes change with every build deployment.

A more resilient technique involves extracting the application state directly. SPAs often hydrate their initial state by embedding JSON directly in the HTML <script> tags.

Search the DOM for script tags containing application configuration or preloaded state. This data is structured and bypasses the need for DOM parsing entirely.

Python
from bs4 import BeautifulSoup
import json
import re

html_content = response.text
soup = BeautifulSoup(html_content, "html.parser")

# Target specific script tags containing state data
scripts = soup.find_all("script")
for script in scripts:
    if script.string and "requireLazy" in script.string:
        # Example regex targeting embedded state objects
        match = re.search(r'{"user":{"edge_followed_by":{"count":(\d+)}', script.string)
        if match:
            follower_count = match.group(1)
            print(f"Followers: {follower_count}")

For complex layouts where internal state is obfuscated, passing the rendered HTML through a structured extraction model yields clean JSON without regular expressions.

Try it yourself

Test public data extraction pipeline

5. Best practices

Building a sustainable data pipeline requires defensive programming and respect for target infrastructure.

Respect robots.txt Always check the robots.txt file of the target domain. Do not scrape paths disallowed for all user agents. Keep your requests strictly to public routes intended for indexation.

Implement rate limiting and jitter Never flood a domain with concurrent requests. Add randomized delays (jitter) between requests. If your target is instagram.com/explore/tags/python/, space out your pagination requests. A flat 1.0 second delay is an obvious automated signature. Use a random float between 2.5 and 5.0 seconds.

Handle HTTP 429 and 403 gracefully Your code must handle rejection. When you receive a 429 Too Many Requests, back off exponentially. Do not immediately retry.

Python
import time
import random

def fetch_with_backoff(url, max_retries=3):
    for attempt in range(max_retries):
        response = client.scrape(url, render_js=True)
        
        if response.status_code == 200:
            return response.text
            
        if response.status_code == 429:
            sleep_time = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(sleep_time)
            continue
            
    raise Exception("Max retries exceeded")

6. Scaling up

Moving from a local script to a production data pipeline requires structural changes.

Batch Processing Process URLs in batches rather than sequentially. Grouping requests allows you to manage proxy rotation more efficiently and maximize throughput.

Webhook Integration For large extraction jobs, keeping HTTP connections open leads to timeouts. Switch to asynchronous webhooks. You submit a job containing 10,000 URLs. AlterLab manages the queue, executes the headless browsers, and POSTs the extracted JSON to your server as each page completes.

Cost Management Rendering JavaScript and routing traffic through residential proxy networks carries infrastructure costs. Review the AlterLab pricing to understand the difference between datacenter and residential bandwidth. Optimize your pipeline by only using headless browsers when absolutely necessary. If a specific API endpoint can be hit directly without JS rendering, route it through a cheaper datacenter tier.

7. Key takeaways

Extracting public data from Instagram requires handling modern SPA architecture.

  • Use headless browsers to execute JavaScript and trigger internal API calls.
  • Avoid CSS selectors. Extract embedded JSON state from <script> tags for resilient parsing.
  • Implement exponential backoff and randomized jitter to manage rate limits respectfully.
  • Offload infrastructure complexity to an API to focus on data engineering rather than browser cluster maintenance.
Share

Was this article helpful?

Frequently Asked Questions

Scraping publicly accessible data is generally legal based on precedents like hiQ v. LinkedIn. However, you must review Instagram's robots.txt and Terms of Service, implement respectful rate limiting, and avoid attempting to access private user data.
Instagram uses heavy JavaScript rendering, dynamic GraphQL endpoints, and strict IP rate limiting. Extracting data requires headless browsers and residential proxy rotation to access public pages successfully.
Costs depend on request volume and the proxy types required. Rendering JavaScript and rotating residential proxies increases cost per request compared to static HTML scraping.