How I Got Here
Started using Instaloader to download Instagram content. Worked fine for a few hours, then suddenly everything started failing with 429 errors.
Spent days trying different approaches. Some worked temporarily, most didn't. Here's what I learned through trial and error.
โ ๏ธ Important Note
Instagram's rate limits change frequently. What works today might not work next month. This is just my experience from late 2025 to early 2026.
Problem 1: 429 Error After a Few Requests
This was the first problem I hit. Downloaded maybe 10-20 posts, then:
QueryReturnedNotFoundException: HTTP Error Code: 429
Or sometimes just:
429 Too Many Requests
What I Tried (That Didn't Work)
- Waiting 60 seconds between requests - still got blocked
- Using different targets (different profiles) - didn't help
- Clearing session file - no effect
- Rotating user agents - Instagram doesn't care
What Actually Worked
After much testing, I found the combination that works:
import instaloader
import time
import random
L = instaloader.Instaloader()
# Load session if exists
try:
L.load_session_from_file('your_username', 'session_file')
except:
pass
# Add delay between requests
L.context.quiet = True
def download_with_delay(profile):
try:
# Random delay 3-8 seconds
time.sleep(random.uniform(3, 8))
# Download with metadata only (faster, less API calls)
profile = instaloader.Profile.from_username(L.context, profile)
# Download posts one by one with longer delays
for post in profile.get_posts():
time.sleep(random.uniform(5, 10))
L.download_post(post, target=profile.username)
# Stop after 50 posts to avoid hitting limits
if post.shortcode == list(profile.get_posts())[49].shortcode:
break
except Exception as e:
print(f"Error: {e}")
# Wait longer on error
time.sleep(60)
Key points:
- Random delays: 3-8 seconds between requests, 5-10 seconds when downloading posts
- Limit batch size: Stop after 50 posts per session
- Error handling: Wait 60 seconds on any error
- Session persistence: Load session from file to avoid re-login
Problem 2: Login Required Even for Public Profiles
Suddenly Instaloader started asking for login even though I was accessing public profiles:
LoginRequiredException: Login required to access this profile
What I Discovered
Instagram enforces login more aggressively when:
- You access too many different profiles in a short time
- Your IP has been flagged for suspicious activity
- You're accessing the same profile repeatedly
What Actually Worked
import instaloader
# Login with session file
L = instaloader.Instaloader()
# Login once and save session
L.login('your_username', 'your_password')
L.save_session_to_file('session_file')
# Now you can access public profiles
# But still need delays and limits!
๐ก Tip
Once logged in, you can access private profiles you follow. But rate limits become stricter. Download less content per session.
Problem 3: Session Expires After a Few Hours
Session file works for a while, then suddenly:
BadResponseException: 400 Bad Request
What Actually Worked
import instaloader
import os
L = instaloader.Instaloader()
# Check if session file exists and is recent
session_file = 'session_file'
if os.path.exists(session_file):
file_age = time.time() - os.path.getmtime(session_file)
# Session is only valid for ~6 hours
if file_age > 6 * 60 * 60:
os.remove(session_file)
print("Session expired, logging in again")
# Try to load session, login if needed
try:
L.load_session_from_file('your_username', session_file)
except:
L.login('your_username', 'your_password')
L.save_session_to_file(session_file)
Sessions seem to last 6-12 hours before expiring. After that, you need to log in again.
Problem 4: IP Address Blocked
This is the worst one. Got my IP blocked entirely:
ConnectionError: Failed to establish connection
Or the browser shows "Access Denied" when trying to access Instagram from that IP.
How I Found Out
Opened Instagram in a regular browser using the same network connection - got the access denied page. Confirmed the IP was blocked.
What Actually Worked
โ ๏ธ Bad News
Once your IP is blocked, there's not much you can do. Options:
- Wait 24-48 hours (block might expire)
- Use a different network (home vs mobile data)
- Use proxies (expensive but works)
- Use VPN (hit or miss, Instagram blocks many VPN IPs)
Proxy Setup
import instaloader
# With HTTP proxy
L = instaloader.Instaloader(
proxy_config={
'http': 'http://proxy-server:port',
'https': 'https://proxy-server:port'
}
)
# Or with SOCKS proxy
L = instaloader.Instaloader(
proxy_config={
'http': 'socks5://proxy-server:port',
'https': 'socks5://proxy-server:port'
}
)
# Test the proxy
try:
profile = instaloader.Profile.from_username(L.context, 'instagram')
print("Proxy works!")
except:
print("Proxy failed or blocked")
โ ๏ธ Proxy Costs
Good proxies cost money. Free proxies are almost always already blocked by Instagram. Expect to pay $50-200/month for residential proxies that work.
Problem 5: Challenge Required
Sometimes Instagram throws a challenge instead of just blocking:
TwoFactorAuthRequiredException: Challenge required
This means Instagram wants you to verify your account via SMS or email.
What Actually Worked
import instaloader
L = instaloader.Instaloader()
# Enable two-factor handling
L.interactive_login('your_username') # Prompts for 2FA code
# Save session after successful login
L.save_session_to_file('session_file')
After doing this once, Instagram trusts your session more. Still need to respect rate limits though.
What Actually Works (in 2026)
Conservative Approach
import instaloader
import time
import random
L = instaloader.Instaloader()
# Load or create session
try:
L.load_session_from_file('username', 'session')
except:
L.login('username', 'password')
L.save_session_to_file('session')
def safe_download(profile_name, max_posts=30):
try:
profile = instaloader.Profile.from_username(L.context, profile_name)
count = 0
for post in profile.get_posts():
if count >= max_posts:
break
# Random delay 5-15 seconds
delay = random.uniform(5, 15)
print(f"Waiting {delay:.1f}s...")
time.sleep(delay)
L.download_post(post, target=profile_name)
count += 1
# Random longer pause every 10 posts
if count % 10 == 0:
long_pause = random.uniform(30, 60)
print(f"Long pause: {long_pause:.1f}s")
time.sleep(long_pause)
print(f"Downloaded {count} posts from {profile_name}")
except Exception as e:
print(f"Error: {e}")
# Wait 5 minutes on error
time.sleep(300)
# Use it
safe_download('target_profile', max_posts=30)
Key Settings That Work for Me
- Delays: 5-15 seconds random between posts
- Long pause: 30-60 seconds every 10 posts
- Batch limit: 30-50 posts max per profile
- Session: Reload from file, re-login every 6 hours
- Error wait: 5 minutes if anything fails
When to Just Give Up
Sometimes nothing works. Signs you should stop:
- Your IP gets blocked repeatedly (even after waiting 24h)
- 429 errors happen immediately after logging in
- Account gets temporarily locked
- You're downloading thousands of posts per day (this is not normal use)
At this point, consider:
- Using official Instagram API (requires approval)
- Buying access from a data provider
- Accepting that you can't download that much content