Skip to main content

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-After on 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_...")
ParameterDefaultDescription
api_keyenv GETSOCIALAPI_API_KEYyour API key from the dashboard
base_urlAPI endpointoverride only for testing
timeout30per-request timeout, seconds
max_retries3retries 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.

Resolving a username

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
ExceptionHTTPNotes
GetSocialAPIError—base class; also network errors
APIKeyError401invalid or missing key
BadRequestError400.field points to the bad parameter
NotFoundError404object does not exist — never retried
RateLimitError429.retry_after seconds
ServiceUnavailableError503no live accounts, .retry_after
InstagramErroranyupstream 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