Instaloader
Overview
Seção intitulada “Overview”Instaloader is a Python tool for downloading Instagram profiles, posts, stories, and reels while preserving metadata. It’s designed for OSINT research, academic purposes, and understanding Instagram’s data structures. The tool operates through public Instagram APIs and respects terms of service when used appropriately.
Installation
Seção intitulada “Installation”Linux (Debian/Ubuntu)
Seção intitulada “Linux (Debian/Ubuntu)”sudo apt-get update
sudo apt-get install python3 python3-pip
pip3 install instaloader
brew install python3
pip3 install instaloader
Windows
Seção intitulada “Windows”# Python 3.6+ required
python -m pip install instaloader
FROM python:3.11-slim
RUN pip install instaloader
ENTRYPOINT ["instaloader"]
Build from Source
Seção intitulada “Build from Source”git clone https://github.com/instaloader/instaloader.git
cd instaloader
python3 -m pip install -e .
Verify Installation
Seção intitulada “Verify Installation”instaloader --version
instaloader -h
Basic Usage
Seção intitulada “Basic Usage”| Command | Description |
|---|---|
instaloader profile_name | Download profile |
instaloader --login username | Login with username |
instaloader --stories profile_name | Download stories |
instaloader --igtv profile_name | Download IGTV/reels |
instaloader "#hashtag" | Download hashtag posts |
instaloader @username | Download profile by handle |
Command-Line Options
Seção intitulada “Command-Line Options”Profile Options
Seção intitulada “Profile Options”--profile-pic Download profile picture
--stories Download stories
--highlights Download story highlights
--tagged Download tagged photos
--igtv Download IGTV/reels
--no-videos Skip video files
--no-captions Skip captions
--no-metadata-json Don't save JSON metadata
Authentication
Seção intitulada “Authentication”--login USERNAME Login with username
--password PASSWORD Provide password (not recommended)
--session FILE Use saved session file
--load-cookies FILE Load cookies from file
--save-cookies FILE Save cookies for reuse
Download Filtering
Seção intitulada “Download Filtering”-C, --count Maximum posts to download
--latest-stamps FILE Only posts newer than timestamp
--post-filter Python expression for filtering
--skip-posts Skip posts
--geotags Download geotag data
Output Options
Seção intitulada “Output Options”-d, --dirname Custom output directory
-f, --filename Custom filename format
--flat-out Flat directory structure
--no-profile-pic Skip profile picture
--metadata-local Store metadata locally
--quiet Minimal output
--verbose Verbose output
Authentication
Seção intitulada “Authentication”Session Management
Seção intitulada “Session Management”First-Time Login
Seção intitulada “First-Time Login”# Interactive login with browser
instaloader --login username
# Follow prompts:
# 1. Enter password
# 2. Complete 2FA if prompted
# 3. Session automatically saved
Reuse Saved Session
Seção intitulada “Reuse Saved Session”# Session stored in config directory
# ~/.local/share/instaloader/
# or ~/.config/instaloader/
# Login returns session file
instaloader --login username
# Subsequent runs use cached session
instaloader username
Save Session Explicitly
Seção intitulada “Save Session Explicitly”# Save session for later use
instaloader --login username --save-session session.json
# Load specific session
instaloader --session session.json profile_name
Cookie-Based Authentication
Seção intitulada “Cookie-Based Authentication”# Export cookies from browser
# Use browser extension (e.g., EditThisCookie)
# Save as cookies.txt
# Use exported cookies
instaloader --load-cookies cookies.txt profile_name
Profile Analysis
Seção intitulada “Profile Analysis”Download Complete Profile
Seção intitulada “Download Complete Profile”Basic Profile Download
Seção intitulada “Basic Profile Download”# Download all public posts
instaloader profile_name
# Output structure:
# profile_name/
# ├── 2024-01-15_ABC123_0.jpg
# ├── 2024-01-15_ABC123_0.txt (caption)
# ├── 2024-01-15_ABC123_0.json (metadata)
# └── profile.json (profile info)
Profile with Metadata
Seção intitulada “Profile with Metadata”# Download including all metadata
instaloader --profile-pic --stories \
--no-captions profile_name
# profile.json contains:
# - username
# - full_name
# - biography
# - follower_count
# - following_count
# - is_private
# - business_category_name
# - external_url
# - contact_email
Extract Profile Information
Seção intitulada “Extract Profile Information”Profile Metadata Analysis
Seção intitulada “Profile Metadata Analysis”#!/usr/bin/env python3
import json
# Load profile metadata
with open('profile_name/profile.json', 'r') as f:
profile = json.load(f)
# Extract key information
print(f"Username: {profile['username']}")
print(f"Full Name: {profile['full_name']}")
print(f"Biography: {profile['biography']}")
print(f"Followers: {profile['follower_count']}")
print(f"Following: {profile['following_count']}")
print(f"Posts: {profile['edge_owner_to_timeline_by_timeline']['edges'].__len__()}")
print(f"Website: {profile['external_url']}")
print(f"Contact: {profile['contact_email']}")
print(f"Business Category: {profile['business_category_name']}")
Download Stories
Seção intitulada “Download Stories”Story Collection
Seção intitulada “Story Collection”# Download all stories
instaloader --stories profile_name
# With metadata
instaloader --stories --metadata-local profile_name
# Only latest stories
instaloader --stories --count 10 profile_name
# Stories saved with timestamps
# profile_name/stories/
# ├── 2024-01-15_120000_story.jpg
# ├── 2024-01-15_120000_story.json
Story Timestamp Analysis
Seção intitulada “Story Timestamp Analysis”#!/usr/bin/env python3
import os
import json
from datetime import datetime
story_dir = "profile_name/stories"
for filename in sorted(os.listdir(story_dir)):
if filename.endswith('.json'):
with open(os.path.join(story_dir, filename)) as f:
data = json.load(f)
# Extract timestamp
taken_at = data.get('taken_at_timestamp', 0)
timestamp = datetime.fromtimestamp(taken_at)
print(f"{filename}: {timestamp}")
Download Highlights
Seção intitulada “Download Highlights”Story Highlights Preservation
Seção intitulada “Story Highlights Preservation”# Download story highlights
instaloader --highlights profile_name
# Output: profile_name/stories/highlight_name/
# Contains:
# - Highlight cover image
# - All stories in highlight
# - Metadata files
# Access saved highlights
ls -la profile_name/stories/highlight_*
Hashtag and Location Analysis
Seção intitulada “Hashtag and Location Analysis”Hashtag Research
Seção intitulada “Hashtag Research”Download Hashtag Posts
Seção intitulada “Download Hashtag Posts”# Download posts with hashtag
instaloader "#hashtag"
# Limit results
instaloader "#hashtag" --count 100
# Filter by date
instaloader "#hashtag" \
--post-filter "date > datetime(2024,1,1)"
Hashtag Analysis Script
Seção intitulada “Hashtag Analysis Script”#!/usr/bin/env python3
import json
import os
from collections import defaultdict
hashtag = "hashtag"
hashtag_dir = hashtag.replace("#", "")
# Analyze posts
engagement = defaultdict(int)
authors = set()
for filename in os.listdir(hashtag_dir):
if filename.endswith('.json'):
with open(os.path.join(hashtag_dir, filename)) as f:
post = json.load(f)
authors.add(post['owner']['username'])
engagement[post['owner']['username']] += (
post['edge_liked_by']['edge_likedby_count'] +
post['edge_media_to_caption']['edges'].__len__()
)
# Print top contributors
print(f"Total unique authors: {len(authors)}")
print("\nTop 10 contributors:")
for author, score in sorted(engagement.items(),
key=lambda x: x[1],
reverse=True)[:10]:
print(f"{author}: {score} engagements")
Location Research
Seção intitulada “Location Research”Download Location Posts
Seção intitulada “Download Location Posts”# Note: Instaloader has limited location support
# Alternative: Manual location lookup
# Find posts from location
# Typically requires manual browsing or API
# Workaround: Download posts mentioning location
instaloader -C 100 \
--post-filter "location == 'Location Name'"
Advanced Workflows
Seção intitulada “Advanced Workflows”OSINT Intelligence Gathering
Seção intitulada “OSINT Intelligence Gathering”Complete Profile Intelligence
Seção intitulada “Complete Profile Intelligence”#!/bin/bash
TARGET="target_username"
OUTPUT_DIR="osint_results"
mkdir -p "$OUTPUT_DIR"
echo "[*] Gathering OSINT on $TARGET"
# 1. Download profile
echo "[*] Downloading profile..."
instaloader --login your_username --profile-pic \
--stories "$TARGET" -d "$OUTPUT_DIR"
# 2. Extract metadata
echo "[*] Extracting metadata..."
python3 << 'EOF'
import json
import os
profile_file = f"$OUTPUT_DIR/$TARGET/profile.json"
if os.path.exists(profile_file):
with open(profile_file) as f:
profile = json.load(f)
intel = {
'username': profile['username'],
'full_name': profile['full_name'],
'bio': profile['biography'],
'followers': profile['follower_count'],
'following': profile['following_count'],
'website': profile['external_url'],
'email': profile['contact_email'],
'business': profile['business_category_name']
}
with open(f"$OUTPUT_DIR/intelligence.json", 'w') as out:
json.dump(intel, out, indent=2)
print("[+] Intelligence extracted")
EOF
echo "[*] OSINT complete. Results in $OUTPUT_DIR/"
Social Network Analysis
Seção intitulada “Social Network Analysis”#!/usr/bin/env python3
import json
import os
from collections import Counter
def analyze_social_network(profile_dir):
"""Analyze follower/following relationships"""
profile_file = os.path.join(profile_dir, 'profile.json')
with open(profile_file) as f:
profile = json.load(f)
# Extract relationships
followers = profile['follower_count']
following = profile['following_count']
print(f"Profile: {profile['username']}")
print(f"Followers: {followers}")
print(f"Following: {following}")
print(f"Engagement Ratio: {followers / max(following, 1):.2f}")
# Analyze posts
posts = profile['edge_owner_to_timeline_by_timeline']['edges']
engagement_scores = []
for post in posts[:20]: # Last 20 posts
node = post['node']
likes = node['edge_liked_by']['count']
comments = node['edge_media_to_caption']['edges'].__len__()
engagement = likes + (comments * 2) # Weight comments higher
engagement_scores.append(engagement)
avg_engagement = sum(engagement_scores) / len(engagement_scores)
print(f"\nAverage engagement (last 20): {avg_engagement:.0f}")
print(f"Engagement rate: {(avg_engagement / followers * 100):.2f}%")
# Usage
analyze_social_network('target_username')
Content Analysis
Seção intitulada “Content Analysis”Post Metadata Extraction
Seção intitulada “Post Metadata Extraction”#!/usr/bin/env python3
import json
import os
from datetime import datetime
from collections import defaultdict
def analyze_posts(profile_dir):
"""Analyze post patterns and content"""
posts_dir = os.path.join(profile_dir)
post_types = defaultdict(int)
posting_hours = defaultdict(int)
engagement_by_type = defaultdict(list)
for filename in os.listdir(posts_dir):
if not filename.endswith('.json'):
continue
filepath = os.path.join(posts_dir, filename)
with open(filepath) as f:
try:
post = json.load(f)
except:
continue
# Determine post type
is_video = post.get('is_video', False)
post_type = 'video' if is_video else 'image'
post_types[post_type] += 1
# Extract timestamp
timestamp = datetime.fromtimestamp(post['taken_at_timestamp'])
posting_hours[timestamp.hour] += 1
# Engagement metrics
likes = post.get('edge_liked_by', {}).get('count', 0)
comments = post.get('edge_media_to_comment', {}).get('count', 0)
engagement_by_type[post_type].append(likes + comments)
# Print analysis
print(f"Content breakdown:")
for post_type, count in post_types.items():
print(f" {post_type}: {count}")
print(f"\nPosting frequency by hour (UTC):")
for hour, count in sorted(posting_hours.items()):
print(f" {hour:02d}:00 - {hour:02d}:59: {count}")
print(f"\nAverage engagement by type:")
for post_type, scores in engagement_by_type.items():
avg = sum(scores) / len(scores) if scores else 0
print(f" {post_type}: {avg:.0f}")
# Usage
analyze_posts('target_username')
Video and Media Download
Seção intitulada “Video and Media Download”Download Video Content
Seção intitulada “Download Video Content”# Download IGTV/Reels
instaloader --igtv target_username
# Download all media including videos
instaloader --no-captions target_username
# Video files saved as MP4
# With metadata in JSON files
Media Organization
Seção intitulada “Media Organization”#!/bin/bash
# Organize downloads by type
SOURCE="target_username"
OUTPUT="organized_media"
mkdir -p "$OUTPUT"/{photos,videos,stories,metadata}
# Separate by file type
for file in "$SOURCE"/*.jpg; do
[ -f "$file" ] && cp "$file" "$OUTPUT/photos/"
done
for file in "$SOURCE"/*.mp4; do
[ -f "$file" ] && cp "$file" "$OUTPUT/videos/"
done
for file in "$SOURCE"/*.json; do
[ -f "$file" ] && cp "$file" "$OUTPUT/metadata/"
done
# Stories
if [ -d "$SOURCE/stories" ]; then
cp -r "$SOURCE/stories" "$OUTPUT/stories"
fi
echo "[+] Media organized in $OUTPUT/"
Rate Limiting and Ethics
Seção intitulada “Rate Limiting and Ethics”Responsible Usage
Seção intitulada “Responsible Usage”Request Rate Limiting
Seção intitulada “Request Rate Limiting”# Add delay between requests
instaloader --sleep-after-login 30 username
# Throttle requests
instaloader --max-request-retries 3 username
# Reasonable delays prevent detection
# 5-10 second delays between bulk operations
Session Best Practices
Seção intitulada “Session Best Practices”# Use persistent session
# Rotate user agents
# Don't run in parallel
# Respect Instagram's robots.txt
# Follow API rate limits
# Archive sessions for reuse
Legal Considerations
Seção intitulada “Legal Considerations”Terms of Service Compliance
Seção intitulada “Terms of Service Compliance”Instagram Terms Restrictions:
- Don't download content without authorization
- Don't bypass security measures
- Don't use for spam/harassment
- Respect privacy settings
Legal Usage:
- Personal research
- Academic purposes
- Authorized security assessments
- Public content only
- Attribution of content
Troubleshooting
Seção intitulada “Troubleshooting”Authentication Issues
Seção intitulada “Authentication Issues”Login Failures
Seção intitulada “Login Failures”# Clear old session
rm -rf ~/.local/share/instaloader/
# Re-authenticate
instaloader --login username --password password
# If 2FA enabled
# Respond to browser prompt
instaloader --login username
Session Expired
Seção intitulada “Session Expired”# Save fresh session
instaloader --login username --save-session fresh.json
# Use explicit session
instaloader --session fresh.json profile_name
Download Issues
Seção intitulada “Download Issues”No Results
Seção intitulada “No Results”# Verify profile exists
instaloader --login user target_username --count 1
# Check profile visibility
# Private accounts require following
# Test with public profile first
# Verify credentials
instaloader --login user --test-login
Partial Downloads
Seção intitulada “Partial Downloads”# Resume interrupted download
instaloader --login user profile_name
# Force re-download
rm profile_name/*.json
instaloader --login user profile_name
Rate Limiting
Seção intitulada “Rate Limiting””Too Many Requests”
Seção intitulada “”Too Many Requests””# Reduce request frequency
# Add delays between operations
sleep 30
# Try again later
instaloader --sleep-after-login 60 profile_name
# Use different session
instaloader --session backup.json profile_name
Advanced Python Usage
Seção intitulada “Advanced Python Usage”Custom Instaloader Scripts
Seção intitulada “Custom Instaloader Scripts”#!/usr/bin/env python3
import instaloader
from pathlib import Path
# Initialize loader
L = instaloader.Instaloader()
# Login
L.login("username", "password")
# Download profile
profile = instaloader.Profile.from_username(L.context, "target")
# Access profile attributes
print(f"Username: {profile.username}")
print(f"Followers: {profile.followers}")
print(f"Followed by: {profile.followed_by}")
# Iterate posts
for post in profile.get_posts():
print(f"Post: {post.caption[:50]}")
print(f"Likes: {post.likes}")
print(f"Comments: {post.comments}")
# Download specific post
L.download_post(post, target='./downloads')
# Logout
L.close()
Data Export
Seção intitulada “Data Export”Format and Structure
Seção intitulada “Format and Structure”JSON Metadata Format
Seção intitulada “JSON Metadata Format”{
"node": {
"id": "post_id",
"taken_at_timestamp": 1234567890,
"caption": "Post caption text",
"edge_liked_by": {"count": 1000},
"edge_media_to_comment": {"count": 50},
"owner": {
"username": "author"
}
}
}
Export to CSV
Seção intitulada “Export to CSV”#!/usr/bin/env python3
import json
import csv
import os
def export_to_csv(profile_dir, output_file):
"""Export posts to CSV"""
rows = []
for filename in os.listdir(profile_dir):
if not filename.endswith('.json'):
continue
with open(os.path.join(profile_dir, filename)) as f:
post = json.load(f)
rows.append({
'timestamp': post['taken_at_timestamp'],
'caption': post['caption'][:100],
'likes': post['edge_liked_by']['count'],
'comments': post['edge_media_to_comment']['count'],
'author': post['owner']['username']
})
# Write CSV
with open(output_file, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=rows[0].keys())
writer.writeheader()
writer.writerows(rows)
# Usage
export_to_csv('target_username', 'posts.csv')
Resources
Seção intitulada “Resources”- Official Documentation: https://instaloader.github.io/
- GitHub Repository: https://github.com/instaloader/instaloader
- Community Discussions: GitHub Issues & Discussions
- Similar Tools: IG-Story-Downloader, Bulk Instagram Image Downloader
- Academic References: Social Media OSINT Papers
Version Information
Seção intitulada “Version Information”Current stable: Instaloader 4.13+ Language: Python 3.6+ Cross-platform: Linux, macOS, Windows Dependencies: requests License: MIT Active Development: Community-maintained