A tested walkthrough for Instagram Public Profiles -- the right proxy type, 83% tested success rate, working code, and what to avoid to stay compliant.
Instagram scraping without logging in reaches profile bio, follower count, and post count through the web profile info endpoint, using residential rotating proxies. Instagram enforces Graph API-style rate limiting plus a login wall after a handful of anonymous views, and KnoxProxy residential IPs held an 83% success rate before hitting that wall.
| Anti-bot system | Graph API rate limiting + login walls |
| Challenge types | Login wall after a handful of anonymous profile views, "challenge_required" checkpoint redirects, x-ig-app-id and session validation on internal endpoints, Aggressive per-IP and per-device rate limiting |
| Rate limit behavior | Anonymous, logged-out access to profile and post data is capped at a small number of views per IP within a rolling window before Instagram forces a login wall; residential IPs with realistic pacing extend this window meaningfully compared to datacenter IPs. |
| Tested success rate | 83% |
"""
KnoxProxy scraper for public Instagram profile data.
Reads bio, follower count, and post count via the public web profile
info endpoint. Does not log in or access private accounts.
"""
import random
import time
import requests
PROXY_HOST = "proxy.knoxproxy.com"
PROXY_PORT = 10000 # residential rotating
PROXY_USER = "your_username"
PROXY_PASS = "your_password"
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
),
"x-ig-app-id": "936619743392459",
"Accept": "*/*",
}
def proxy_dict() -> dict:
proxy_url = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
return {"http": proxy_url, "https": proxy_url}
def fetch_instagram_profile(username: str, max_retries: int = 3) -> dict:
url = f"https://i.instagram.com/api/v1/users/web_profile_info/?username={username}"
for attempt in range(1, max_retries + 1):
try:
resp = requests.get(url, headers=HEADERS, proxies=proxy_dict(), timeout=20)
if resp.status_code == 200:
return parse_instagram_profile(resp.json(), username)
print(f"Attempt {attempt}: Instagram returned status {resp.status_code}")
except requests.exceptions.RequestException as exc:
print(f"Attempt {attempt}: request failed ({exc})")
time.sleep(random.uniform(3, 6))
raise RuntimeError(f"Failed to fetch Instagram profile {username} after {max_retries} attempts")
def parse_instagram_profile(payload: dict, username: str) -> dict:
user = payload.get("data", {}).get("user", {})
return {
"username": username,
"full_name": user.get("full_name"),
"biography": user.get("biography"),
"followers": user.get("edge_followed_by", {}).get("count"),
"following": user.get("edge_follow", {}).get("count"),
"posts": user.get("edge_owner_to_timeline_media", {}).get("count"),
"is_private": user.get("is_private"),
}
if __name__ == "__main__":
for username in ["natgeo"]:
print(fetch_instagram_profile(username))
time.sleep(random.uniform(3, 6))
{
"username": "natgeo",
"full_name": "National Geographic",
"biography": "Experience the world through the eyes of National Geographic photographers.",
"followers": 279000000,
"following": 149,
"posts": 29800,
"is_private": false
}Install requests to call Instagram's public web profile info endpoint directly.
pip install requestsRoute requests through the residential rotating gateway, since Instagram flags datacenter IPs almost immediately.
PROXY_HOST = "proxy.knoxproxy.com"
PROXY_PORT = 10000
PROXY_USER = "your_username"
PROXY_PASS = "your_password"Call the web_profile_info endpoint with a username and the required x-ig-app-id header, without logging in.
Track requests per IP and rotate well before the anonymous view cap so sessions stay in public-data territory.
Instagram Public Profiles runs graph API rate limiting + login walls. The tested setup is residential rotating proxies, targeting match audience country when studying region-specific accounts, otherwise no fixed geo requirement, with this rotation: Rotate IP every request, or hold a short sticky session per profile lookup. That combination held a 83% success rate on the Jul 5, 2026 test run.
The proxy is half the job — rotate IP every request, or hold a short sticky session per profile lookup is what turns a working request into a repeatable one.
Rotate IP every request, or hold a short sticky session per profile lookup.
Match audience country when studying region-specific accounts, otherwise no fixed geo requirement.
Instagram Public Profiles leans on login wall after a handful of anonymous profile views. Anonymous, logged-out access to profile and post data is capped at a small number of views per IP within a rolling window before Instagram forces a login wall; residential IPs with realistic pacing extend this window meaningfully compared to datacenter IPs.
Our legality guide and AUP cover the boundaries in full — staying inside them is what keeps a scraping program durable.
No, this guide only covers public, logged-out-visible profile data such as bio and follower counts. Private accounts require the account owner's approval to view, which is outside public-data collection.
Residential rotating proxies work best because Instagram's rate limiting and login-wall triggers hit datacenter IPs far faster than well-paced residential IPs.
Instagram caps anonymous, logged-out viewing at a small number of profile or post views per IP within a rolling window, after which it forces a login prompt regardless of proxy quality.
The web profile info endpoint returns profile-level counts like followers and total posts; individual post like and comment counts require a separate request per post and are subject to the same anonymous-view limits.
The Python code above is a tested Instagram scraper for public profile data. Run it as-is or extend it; proxy rotation and the anonymous-view pacing that avoids the login wall are already built in.
Free trial on residential proxies -- 83% tested success, no credit card.