# instagrapi: a fast Python wrapper around an API nobody promised would keep working

> 6,800 stars, five open issues, and a README that spends more space on why you should not run this in production than on how to install it. That combination turns out to be the honest description of the project.

**subzeroid/instagrapi** — 🔥 The fastest and powerful Python library for Instagram Private API 2026 with HikerAPI SaaS

- Repository: https://github.com/subzeroid/instagrapi
- Website: https://subzeroid.github.io/instagrapi/
- Stars: 6,937 · Forks: 1,003
- Language: Python
- License: NOASSERTION
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/subzeroid-instagrapi

## The README's first real advice is to use something else

Most library READMEs start with what the library does. This one starts, three paragraphs down, with a warning. Private API automation is fragile in production, because account trust, proxies, device state, challenges and rate limits can change independently of the library. For account-owned business workflows, the recommendation is to prefer official Instagram APIs where they cover the use case. For production private API infrastructure, the recommendation is a hosted provider such as HikerAPI rather than maintaining accounts, proxies and challenge handling yourself.

Then comes the sentence that tells you what the project is actually for: testing, research and controlled internal automation.

That framing is worth taking seriously because the rest of the README is consistent with it. The dependencies are modern and deliberately pinned, the login path has been migrated with a written guide, and the maintainer ships releases several times a week when something breaks. Those are the behaviours of a project whose real user is a developer working on their own account in a lab, not a team running a service.

GitHub reports 6,827 stars, 984 forks and only 5 open issues for this repository, with a push on 2026-09-21. An issue count that low on a project this popular is not a sign of few users. It is a sign that most reports get closed or answered quickly by a maintainer who is already fixing something rather than triaging.

## The five-line quick start and what it hides

The entry point is deliberately tiny.

```python
from instagrapi import Client

cl = Client()
cl.login(ACCOUNT_USERNAME, ACCOUNT_PASSWORD)

user_id = cl.user_id_from_username(ACCOUNT_USERNAME)
medias = cl.user_medias(user_id, 20)
```

Five lines, and three of them are the work: construct a client, log in, resolve a numeric user id from a handle. The rest is library. What that hides is everything the project is actually good at, which is transport and session management.

The package name is `instagrapi`, the version is 3.0.12, and it requires Python 3.10 or later. The dependency list in `pyproject.toml` is short and specific: `curl_cffi` at 0.15.0 or later for HTTP/2 impersonation, `requests` for the plain HTTP path, `PySocks` for proxy support, `Pillow` at 12.2.0 or later, and `pycryptodomex` for cryptography. There is a platform-specific pydantic pin, which suggests Android is treated as a supported target rather than an afterthought.

The classifiers stop at Python 3.14, so the package is being kept current against new interpreter releases. That is a maintenance signal that matters here, because a wrapper that lags on interpreter support ages badly.

## Two transports, and why TLS impersonation is an install extra

The library speaks two different APIs over two different transports, and the split explains the packaging.

The private mobile API path uses `curl_cffi` and HTTP/2, and the README says plainly that private mobile requests use HTTP/2 through curl_cffi, included in the standard installation, so `Client()` needs no transport argument. The public web path is the sensitive one: some endpoints reject requests that do not look like they came from a browser, including at the TLS fingerprint level.

For that, impersonation is an extra rather than the default.

```bash
pip install "instagrapi[curl]"
```

```python
cl = Client(public_transport="curl", public_transport_impersonate="chrome136")
```

The design decision here is honest: fingerprinting is a workaround for a specific detection technique, and the library would rather you opt into it than carry the cost and the breakage surface by default. If you need it, you name a browser version. If you do not, you get a plain request.

Certificate verification is on by default, and the README tells you how to use a proxy CA certificate if you need one. It also tells you not to disable verification permanently, only for temporary local debugging, because disabling it lets something intercept your session. That is an unusually direct warning for a package README.

## Login got renamed, and the old name is still there

The login flow has been through a migration, and the README documents both sides of it. `login()` now uses CAA directly. The previous login behaviour is preserved as `login_legacy()`. If you have an existing integration, this is the first thing to check when you upgrade.

The session flow is the part that determines whether your automation survives. After logging in, you dump the settings to a file. On the next run, you load them and log in again, which reuses the saved session rather than re-authenticating from scratch.

```python
cl.dump_settings("session.json")

# reload later; the saved session is validated before reuse
cl = Client()
cl.load_settings("session.json")
cl.login(USERNAME, PASSWORD)
cl.dump_settings("session.json")
```

There is an important subtlety in that loop. If Instagram rejects the session with `login_required`, the library clears the stale authorization and logs in again with your credentials. That means `dump_settings()` after `login()` is not optional bookkeeping; it is how the refreshed session gets persisted for next time. Skip it and you are re-authenticating on every run, which is exactly the behaviour that triggers rate limits.

The README also marks `login_by_sessionid()` as a lightweight compatibility path rather than the main flow. That function takes a session id directly, and the README is clear that if it returns `login_required` or logs your browser out, Instagram rejected that session for the private mobile API. The recommendation is one stable password login, then reuse the dumped settings.

## Why the install instructions include a dependency conflict

The video support instructions are the most technically revealing thing in the README, because they document a conflict the project could not resolve cleanly.

```bash
pip install "instagrapi[video]"
pip install --no-deps "moviepy==2.2.1"
```

The reason is spelled out: MoviePy 2.2.1 declares `Pillow<12`, but instagrapi keeps `Pillow>=12.2.0` for security fixes. Installing with `--no-deps` keeps the safe Pillow version and skips MoviePy's attempt to downgrade it. If your project imports MoviePy directly, the README tells you to migrate any 1.x code that uses `moviepy.editor`, `set_*`, `resize` or `subclip` to the 2.x API before upgrading.

That is a maintenance burden being passed to the user with documentation rather than hidden. It also tells you something about priorities: the Pillow floor is a security decision, and the project would rather ask you to work around MoviePy than ship an older image library.

The video extras also need an `ffmpeg` executable on the path, and automatic thumbnail generation, `StoryBuilder` and audio composition all depend on it. If you only upload photos, none of this applies. The README distinguishes the built-in MP4 metadata parser, which works with a `thumbnail` you supply, from the parts that need the full dependency chain.

## Version floor, license gap, and a homepage that points somewhere else

Three small inconsistencies are worth knowing before you depend on this.

The Python floor moved. Python 3.9 support was dropped in 2.5.0, and the README gives a reason that is rare to see: upstream security patches for Pillow 12.x and pytest 9.x are not backported to Python 3.9, so the conditional pins would be permanently exposed to known CVEs. If you need 3.9, the instruction is to pin `instagrapi==2.4.5`. That is a security-driven deprecation of a runtime version rather than a feature decision, and it is documented clearly enough that you can plan around it.

The license is ambiguous across sources. GitHub reports the license field as unrecognised, the README carries a license badge linking to a LICENSE file, and `pyproject.toml` declares MIT. If you need a machine-readable license for compliance, the package metadata is the more reliable of the two.

The homepage is also inconsistent. GitHub's homepage field points at the documentation site on GitHub Pages, the README badges point at the same site, and `pyproject.toml` lists instagrapi.com as the project homepage. The documentation site is where the guides actually live, including the login migration guide, the public transport guide and the Android instructions for Pydroid and Termux. Go there rather than to the commercial domain when you want reference material.

The last release worth noting is 3.0.12, which fixes a curl-adapter version requirement for public transport. All three of the most recent releases are fixes rather than features, all within a single day, which is what a library responding to a breaking upstream looks like from the outside.

## Conclusion

instagrapi is what it claims to be, with one important asterisk: it is a wrapper around an interface Instagram reserves the right to change at any moment, so its real quality is judged by how quickly it absorbs those changes. The repository is unusually honest about that. It names its own failure modes, steers business workflows toward official APIs, points production users at a hosted provider, and treats a saved session as something that can be invalidated between runs. The engineering underneath is more careful than the category usually deserves: HTTP/2 through curl_cffi, optional browser TLS impersonation, a login migration path, and a documented session lifecycle. Read the stability note before anything else, decide whether testing and research is your actual use case, and if it is, pin a version and keep the session file out of your repository.

## FAQ

### Is the Instagram API free?

Meta's official Instagram APIs are free to call within their rate limits, but they expose a deliberately narrow slice of functionality, and business use is generally gated by a business account and review. This library is not the official API. It wraps the private mobile API and the public web endpoints, which carry no price but also no compatibility promise and none of the stability guarantees of a supported interface.

### What is the Instagram API used for?

In this library's case, the surface it covers is user lookups, media listing and download, feed and story uploads, Reels, direct messages, comments, notes, locations and insights. Those primitives cover what people build when they want to archive their own account, run a research crawler, or automate posting on an account they own. The README positions the library for testing, research and controlled internal use rather than for a customer-facing product.

### How do I get the official Instagram Graph API?

You create a Meta developer app, add the Instagram product, and request the permissions your use case needs through Meta's business or login flow. That path is slower and more restrictive than this library, and the README explicitly recommends it for account-owned business workflows where it covers the requirement. The private API route this project takes needs no such approval, which is the trade you are making.

### Is Instagram built using Python?

No. Instagram's own backend is not publicly documented and is not written in Python as far as anyone outside can verify. What exists in Python is client libraries like this one, plus the many scripts people write against the private API. The confusion is understandable because Python is the dominant language for Instagram automation tooling, but the language of the service and the language of the tooling are unrelated.

### How do I stop my instagrapi session from expiring every run?

Dump the settings after every login and load them before the next one. If Instagram rejects the saved session with login_required, the library re-authenticates with your credentials, which means the dump call is what persists the refreshed session. Calling dump_settings after login is the difference between reusing a session and re-authenticating on every single run.

### Can I run instagrapi on Android?

There are documentation pages for both Pydroid and Termux, so Android is treated as a real target rather than an accident. The practical constraints are the ones any non-desktop environment brings: you need ffmpeg if you touch video features, and the pydantic dependency is pinned differently on Android than elsewhere, which suggests that pin exists precisely to work around a platform difference.

## Sources

- [Issues](https://github.com/subzeroid/instagrapi/issues)
- [Project website](https://subzeroid.github.io/instagrapi/)
- [README](https://github.com/subzeroid/instagrapi/blob/master/README.md)
- [Releases](https://github.com/subzeroid/instagrapi/releases)
- [subzeroid/instagrapi on GitHub](https://github.com/subzeroid/instagrapi)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/subzeroid-instagrapi
