Python SDK
The official Python client for the GetSocialAPI Instagram API. It proxies requests to the API, handles auth, retries and pagination — you get raw Instagram JSON.
- No cookies required — you never provide Instagram session cookies
- No accounts needed — zero ban risk for your own profiles
- Automatic retries with
Retry-Afteron 429/503, typed exceptions
Source code: github.com/GetSocialAPI/Instagram-Scraper-API
Installation
pip install getsocialapi
Or from GitHub:
pip install git+https://github.com/GetSocialAPI/Instagram-Scraper-API.git
Requires Python 3.9+ and requests.
Client
from getsocialapi import Client
client = Client(api_key="gsa_live_...")
| Parameter | Default | Description |
|---|---|---|
api_key | env GETSOCIALAPI_API_KEY | your API key from the dashboard |
base_url | API endpoint | override only for testing |
timeout | 30 | per-request timeout, seconds |
max_retries | 3 | retries on 429/503/5xx and network errors |
client.health()
# {"ok": True, "state": "ready"}
Profile
# By username or numeric id (routed automatically)
user = client.instagram.user("durov")
user["user"]["follower_count"]
# By numeric id only (canonical)
client.instagram.user_info(25025320)
# By username
client.instagram.user_by_username("instagram")
# Search users: resolve username -> pk
results = client.instagram.search_username("durov", count=10)
results["users"][0]["pk"]
# Suggested / similar accounts
client.instagram.similar_users(25025320)
The profile object contains pk, username, full_name, biography, follower_count, following_count, media_count, is_private, is_verified, account_type (1=personal, 2=business, 3=creator), profile_pic_url_hd and more — the untouched Instagram payload.
search_username returns matches sorted by relevance — the exact match is usually first. Verify it by comparing the username field.
User content
pk = 25025320
# Profile grid posts
medias = client.instagram.user_medias(pk, count=12)
medias["items"][0]["code"] # shortcode for /p/<code>/
medias["items"][0]["media_type"] # 1=photo, 2=video, 8=carousel
medias["next_max_id"] # cursor for the next page
medias["more_available"]
# Posts where the user is tagged
client.instagram.user_tags(pk, count=12)
# Active stories: reel is None when there are none
client.instagram.user_stories(pk)
# Highlights tray (use tray[].id below)
client.instagram.user_highlights(pk)
# Media of one highlight
client.instagram.highlight_stories("18223279177302854")
Followers and following
followers = client.instagram.followers(pk, count=50)
followers["users"][0]["username"]
followers["next_max_id"] # cursor
followers["has_more"]
client.instagram.following(pk, count=50)
query searches by name inside the list (pages of 25; count/max_id of the outer call are ignored in query mode):
client.instagram.followers(pk, query="anna")
Lists "breathe" — deduplicate by pk when aggregating. To reach the hidden part of a private-ish list (visible < follower_count), iterate query over two-character fragments [a-z0-9_].
Media
# Full media card (pk without the _userid suffix)
client.instagram.media_info("4003541350560126622")
# Users who liked (Instagram returns a fixed slice, ~50)
client.instagram.media_likers("4003541350560126622")
# Comments
comments = client.instagram.media_comments("4003541350560126622", count=12)
comments["caption"] # the author's top-level caption
comments["comments"][0]["comment_like_count"]
# Replies to a comment
client.instagram.media_comment_replies(
"4003541350560126622", comment_id=18106304318363310
)
# Search reels by keyword in the caption
client.instagram.search_clips("sunset", count=12)
Note: Instagram closed the full list of comment likers server-side — only the comment_like_count counter is available.
Hashtags
client.instagram.hashtag_info("#gymgirl") # leading # is trimmed
client.instagram.hashtag_search("gym", count=12)
client.instagram.hashtag_posts("gymgirl", count=30)
hashtag_posts returns a normalized classic media list (like user_medias).
Locations
client.instagram.location_info(213069402) # card (pk = facebook_places_id)
client.instagram.location_media(213069402, count=12) # sections grid
There is no location-name search route yet — find pk externally (external_id = facebook_places_id).
Pagination
Every list method accepts max_id — pass next_max_id from the previous response until it is None (or has_more / more_available becomes False).
The SDK ships generators that do this for you and deduplicate by pk:
for follower in client.instagram.iter_followers(25025320):
print(follower["username"])
for media in client.instagram.iter_medias(25025320):
print(media["code"])
for comment in client.instagram.iter_media_comments("4003541350560126622"):
print(comment["text"])
Available: iter_medias, iter_followers, iter_following, iter_hashtag_posts, iter_media_comments, iter_location_media.
Errors
from getsocialapi import NotFoundError, RateLimitError
import time
try:
client.instagram.user_info(25025320)
except NotFoundError:
... # object does not exist — do not retry
except RateLimitError as e:
time.sleep(e.retry_after) # seconds from Retry-After
| Exception | HTTP | Notes |
|---|---|---|
GetSocialAPIError | — | base class; also network errors |
APIKeyError | 401 | invalid or missing key |
BadRequestError | 400 | .field points to the bad parameter |
NotFoundError | 404 | object does not exist — never retried |
RateLimitError | 429 | .retry_after seconds |
ServiceUnavailableError | 503 | no live accounts, .retry_after |
InstagramError | any | upstream Instagram error, .status |
Retries are automatic for 429/503/502/504 (up to max_retries), honoring Retry-After.
Validation
Client-side checks raise ValueError before any network call:
count— integer 1–50- ids /
pk— digits, up to 20 characters username— 1–64 characters- tag — 1–64 characters (leading
#trimmed) - keyword — 1–100 characters, spaces are URL-encoded automatically