Metadata-Version: 2.4
Name: getsocialapi-instagram
Version: 0.1.0
Summary: GetSocialAPI — client library for the Instagram API (no cookies, no accounts required)
Author: GetSocialAPI
License: MIT
Project-URL: Homepage, https://getsocialapi.com
Project-URL: Documentation, https://getsocialapi.com/docs/
Keywords: instagram,api,scraping,sdk,getsocialapi
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25
Dynamic: license-file

# Instagram Scraper API

[![tests](https://github.com/GetSocialAPI/Instagram-Scraper-API/actions/workflows/tests.yml/badge.svg)](https://github.com/GetSocialAPI/Instagram-Scraper-API/actions/workflows/tests.yml)
[![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
[![python](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org)

Python client for the **[GetSocialAPI](https://getsocialapi.com/)** Instagram Scraper API.

- **No cookies required** — you never provide Instagram session cookies
- **No accounts needed** — zero ban risk for your own profiles
- Raw Instagram JSON responses, REST endpoints — no transformations
- Automatic retries with `Retry-After`, typed exceptions

## Installation

```bash
pip install getsocialapi-instagram
```

## Migration from `getsocialapi` (git installs)

Before the PyPI release this SDK was installed from git as `getsocialapi`.
Old imports keep working via a deprecated shim, but please migrate:

```bash
pip uninstall getsocialapi
pip install getsocialapi-instagram
```

```python
# before
from getsocialapi import Client
# after
from getsocialapi_instagram import Client
```

## Quickstart

```python
from getsocialapi_instagram import Client

# Get your API key at https://getsocialapi.com/dashboard/
client = Client(api_key="gsa_live_...")  # or set GETSOCIALAPI_API_KEY

# Profile by numeric id (or user_by_username for usernames)
user = client.instagram.user_info(25025320)
print(user["user"]["follower_count"])

# Posts (grid)
medias = client.instagram.user_medias(25025320, count=12)

# Followers / following — paginated on unverified accounts: pass `next_max_id`
# back as `max_id`. Verified accounts (blue checkmark) expose ~50 followers max.
page = client.instagram.followers(43586162288, count=25)
page = client.instagram.followers(43586162288, max_id=page["next_max_id"])

# All comments of a post — cursor is next_min_id -> min_id (sort_order="recent" by default)
comments, cursor = [], None
while True:
    page = client.instagram.media_comments(4012386322294878415, count=50, min_id=cursor)
    comments += page["comments"]
    cursor = page.get("next_min_id")
    if not cursor:
        break
```

Base URL: `https://api.getsocialapi.com/v1` — authenticate with the API key
from your [dashboard](https://getsocialapi.com/dashboard/).

## Client

```python
Client(api_key=None, base_url="https://api.getsocialapi.com/v1", timeout=30, max_retries=3)
```

| Parameter | Default | Description |
| --- | --- | --- |
| `api_key` | env `GETSOCIALAPI_API_KEY` | your API key |
| `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 |

## Methods

| Method | Route | Description |
| --- | --- | --- |
| `profile(user_id)` | `/profile/<id>` | profile by numeric id |
| `user_info(user_id)` | `/ig/user/info/<id>` | profile by numeric id |
| `user_by_username(username)` | `/ig/user/username_info/<username>` | profile by username |
| `user_about(user_id)` | `/user/about/<id>` | About this account: country, joined, former usernames, shared-followers count, verified |
| `search_username(query, count=10)` | `/search/username/<q>` | search users, resolve username → pk |
| `similar_users(user_id)` | `/ig/user/similar/<id>` | suggested accounts |
| `user_medias(user_id, count=12, max_id=None)` | `/ig/user/media/<id>` | profile grid posts |
| `user_tags(user_id, count=12, max_id=None)` | `/ig/user/tags/<id>` | posts with the user tagged |
| `user_stories(user_id)` | `/ig/user/stories/<id>` | active stories |
| `user_highlights(user_id)` | `/ig/user/highlights/<id>` | highlights tray |
| `highlight_stories(highlight_id)` | `/ig/highlight/stories/<id>` | media of a highlight |
| `followers(user_id, count=50, max_id=None, query=None)` | `/followers/<id>` | followers list |
| `following(user_id, count=25, max_id=None, query=None)` | `/following/<id>` | following list |
| `media_info(media)` | `/ig/media/info/<pk\|shortcode>` | full media card; accepts numeric pk or shortcode |
| `media_likers(media)` | `/ig/media/likers/<pk\|shortcode>` | users who liked (up to ~100, no pagination) |
| `media_comments(media, count=None, sort_order="recent", min_id=None)` | `/ig/media/comments/<pk\|shortcode>` | media comments; cursor pagination `next_min_id` → `min_id` |
| `search_clips(keyword)` | `/ig/media/search_clips/<kw>` | search reels by keyword |
| `hashtag_info(tag)` | `/ig/hashtag/info/<tag>` | hashtag card |
| `hashtag_search(query)` | `/ig/hashtag/search/<q>` | search hashtags |
| `hashtag_posts(tag, max_id=None)` | `/v2/hashtag/posts/<tag>` | posts by hashtag |
| `location_info(pk)` | `/ig/location/info/<pk>` | location card |
| `location_media(pk, max_id=None)` | `/ig/location/media/<pk>` | media by location |

Every method returns the raw JSON of the API route as received — nothing is
unwrapped, filtered or renamed. Where the API supports pagination (`followers`*, `following`, `user_medias`,
`user_tags`, `hashtag_posts`, `location_media`), pass the cursor from the
previous response (`next_max_id`) as `max_id`.
`media_comments` paginates with a different cursor: always request with
`sort_order="recent"` (the default) and pass `next_min_id` back as `min_id`
until it comes back null — pages are chronological and disjoint. Instagram
never returns `next_max_id` for comments, so `max_id` must not be used there.
*`followers` works on unverified accounts (nearly the full list, plus the
`query` filter); verified accounts (blue checkmark) expose no more than ~50
followers — one page, no cursor, `query` ignored. For lists without cursors
(`search_clips`, `hashtag_search`) each call simply returns the service page.

Full request/response reference with live examples:
[docs.getsocialapi → API Reference](https://getsocialapi.com/docs/api/instagram/user/get_info_by_id/)
(see the Documentation section on [getsocialapi.com](https://getsocialapi.com/)).

## Errors

| 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` |

```python
from getsocialapi_instagram import NotFoundError, RateLimitError
import time

try:
    client.instagram.user_info(25025320)
except NotFoundError:
    ...  # object does not exist
except RateLimitError as e:
    time.sleep(e.retry_after)
```

Only successful responses (HTTP `200` and `404`) count against your quota.
Rate limits and plans: [pricing](https://getsocialapi.com/#pricing).

## Support

- Telegram: [@getsocialapi](https://t.me/getsocialapi)
- Email: [hello@getsocialapi.com](mailto:hello@getsocialapi.com)
- Website: [getsocialapi.com](https://getsocialapi.com/)
- Documentation: [getsocialapi.com/docs](https://getsocialapi.com/docs/)
- Status: [getsocialapi.com/status](https://getsocialapi.com/status/)

## License

MIT
