Skip to content

subzeroid/aiograpi

aiograpi - Asynchronous Instagram API for Python

⚠️ Telegram support group moved to https://t.me/aiograpi_support — the previous @instagrapi group has been restricted by Meta and is no longer maintained.

If you want to work with aiograpi (business interests), we strongly advise you to prefer HikerAPI project. However, you won't need to spend weeks or even months setting it up. The best service available today is HikerAPI, which handles 4–5 million daily requests, provides support around-the-clock, and offers partners a special rate. In many instances, our clients tried to save money and preferred aiograpi, but in our experience, they ultimately returned to HikerAPI after spending much more time and money. It will be difficult to find good accounts, good proxies, or resolve challenges, and IG will ban your accounts.

The aiograpi more suits for testing or research than a working business!

Video uploads can use a built-in MP4 metadata parser when you provide thumbnail=.... Automatic thumbnail generation, StoryBuilder, and video/audio composition still need the optional video dependencies, MoviePy 2.2.1, and executable ffmpeg:

pip install "aiograpi[video]"
pip install --no-deps "moviepy==2.2.1"

MoviePy 2.2.1 currently declares Pillow<12, but aiograpi keeps Pillow>=12.2.0 for security fixes; the --no-deps install keeps the safe Pillow version. If your project imports MoviePy directly, migrate any MoviePy 1.x code from moviepy.editor, set_*, resize, and subclip APIs to the MoviePy 2.x API before upgrading.

Android users should see Pydroid and ffmpeg and Termux.

We recommend using our services:

PyPI Python License Package Docs SemVer

Features:

  • Getting public data of user, posts, stories, highlights, followers and following users
  • Getting public email and phone number, if the user specified them in his business profile
  • Getting public data of post, story, album, Reels, IGTV data and the ability to download content
  • Getting public data of hashtag and location data, as well as a list of posts for them
  • Getting public data of all comments on a post and a list of users who liked it
  • Management of proxy servers, mobile devices and challenge resolver
  • Login by username and password, sessionid, 2FA, 8-digit backup codes, and Bloks 2FA fallback/helpers
  • Managing messages, reactions and threads for Direct and attach files
  • Experimental Realtime MQTT/MQTToT for Direct message sync, lightweight Direct actions, and FBNS push callbacks
  • Download and upload a Photo, Video, IGTV, Reels, Albums, Stories and Trial Reels
  • Work with Users, Posts, Comments, Insights, Collections, Location and Hashtag
  • Insights by account, posts and stories
  • Like, following, commenting, editing account (Bio) and much more else

Asynchronous Instagram Private API wrapper without selenium. Use the most recent version of the API from Instagram, which was obtained using reverse-engineering with Charles Proxy and Proxyman.

Support Python >= 3.10

For any other languages (e.g. C++, C#, F#, D, Golang, Erlang, Elixir, Nim, Haskell, Lisp, Closure, Julia, R, Java, Kotlin, Scala, OCaml, JavaScript, Crystal, Ruby, Rust, Swift, Objective-C, Visual Basic, .NET, Pascal, Perl, Lua, PHP and others), I suggest using instagrapi-rest

Support chat in Telegram: https://t.me/aiograpi_support and GitHub Discussions

Features

  1. Performs Web API or Mobile API requests depending on the situation (to avoid Instagram limits)
  2. Login by username and password, including 2FA, 8-digit backup codes, Bloks 2FA fallback/helpers, and by sessionid (and uses Authorization header instead Cookies)
  3. Challenge Resolver have Email and SMS handlers
  4. Support upload a Photo, Video, IGTV, Reels, Albums and Stories
  5. Support work with User, Media, Comment, Insights, Collections, Location (Place), Hashtag and Direct Message objects
  6. Like, Follow, Edit account (Bio) and much more else
  7. Insights by account, posts and stories
  8. Build stories with custom background, font animation, link sticker and mention users
  9. Realtime MQTT for Direct message sync, lightweight Direct MQTT actions, and FBNS push notifications
  10. Account registration and captcha passing will appear

Versioning policy

Starting with 1.0.0, aiograpi follows Semantic Versioning for the Python library API surface. Instagram's private API still rotates doc_ids, deprecates endpoints, and changes response shapes without notice, so 1.0.0 is not a promise that every Instagram-side flow will stay stable forever.

What you can rely on instead:

  • Breaking library API changes use major releases when they are under our control.
  • Instagram-driven endpoint removals are flagged in the CHANGELOG with migration notes.
  • Deprecated methods stay around for ≥2 minor releases with DeprecationWarning before removal — you'll get loud warnings, not surprise AttributeErrors.
  • Live CI smoke runs on every push: tests/live/smoke.py against a real account through a real proxy. If we ship something that breaks the basic happy path, CI catches it.
  • Migration Guide at docs/migration.md — breaking changes are documented with before/after examples.

What's new in 1.0.0 and recent releases

  • 1.3.0 upstream sync — synced through instagrapi 2.9.0, adding experimental modern CAA email signup via signup_caa_email(...), the mobile graphql_www Bloks app wrapper, and per-request private headers/domain routing for Bloks calls.
  • 1.2.x upstream sync — synced through instagrapi 2.8.19, adding Direct media share to existing threads, clearer Direct message request privacy errors, private-first high-level user/media/story lookups, sessionid username recovery via private stream, clearer Bloks redirect challenge handling, clip_share_to_fb_destination(...) for confirmed Reel Facebook destinations, hashtag private section fixes, private business contact field mapping, story metadata extraction, and private incomplete-read retry handling.
  • 1.1.0 MQTT/FBNS sync — synced with instagrapi 2.8.2, adding experimental async Realtime MQTT/MQTToT, Direct message sync, lightweight Direct MQTT actions, FBNS push token registration/callbacks, phone confirmation, followed hashtag helpers, feed-media share-to-story, opaque Bloks challenge context handling, and clearer Reel upload failure details.
  • 1.0.0 SemVer baseline — synced with instagrapi 2.7.0, removed the dead public ?__a=1 API surface, kept media_info_gql() GraphQL-only, and moved high-level hashtag/location helpers to authenticated private/mobile flows.
  • Sync with instagrapi 2.6.x — current Android app profile defaults, override_app_version constructor support, Trial Reels, current Reel rupload flow, Reel pin/unpin, Reel Facebook cross-post payload helpers, feed photo/carousel music, music Notes, archive readers, tagged media pagination, Direct reactions, thread title updates, message request helpers, single-message lookup, and Direct unsend.
  • Android/Pydroid/Termux-friendly video uploads — when you pass thumbnail=..., aiograpi can read MP4 dimensions/duration without importing MoviePy/ffmpeg. The optional video dependencies plus MoviePy 2.2.1 cover automatic thumbnails, StoryBuilder, prepare_video(), and audio/video composition.
  • Modern dev toolinguv.lock, Ruff formatting/checks, updated test pins, and an upstream sync tracking workflow.
  • Sync with instagrapi 2.4.4 — every mixin and infrastructure module ported, plus three new mixins: ExploreMixin, FundraiserMixin, and opt-in CaptchaHandlerMixin.
  • doc_id GraphQL primitiveClient.public_doc_id_graphql_request(doc_id, variables) and Client.private_graphql_query_request(...) for the new i.instagram.com/graphql/query surface IG migrated to. New high-level methods: user_info_v2_gql, user_info_by_username_v2_gql, private_graphql_followers_list / following_list / clips_profile / inbox_tray_for_user, private_graphql_memories_pog / realtime_region_hint / top_audio_trends_eligible_categories, plus fbsearch_keyword_typeahead / fbsearch_typeahead_stream / fbsearch_item, feed_user_stream_item, media_comment_infos. All live-verified.
  • Pure helpers go sync (breaking from 0.0.x): media_pk_from_code, media_code_from_pk, media_pk, share_info, share_code_from_url, share_info_by_url, highlight_pk_from_url, handle_challenge_result, challenge_resolve_new_password_form no longer require await. See Migration Guide for the full list.
  • CI publish-on-tag with PyPI trusted publishing — push a version tag, GitHub Actions builds, publishes, and creates a release.

Full per-release notes: CHANGELOG.md. Migrating from 0.0.x? See the Migration Guide.

Installation

pip install aiograpi

Optional public web TLS impersonation support is available as an extra:

pip install "aiograpi[curl]"

Use it only for public web endpoints that are sensitive to browser TLS fingerprints:

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

See the public transport guide for live comparison results and caveats.

TLS certificate verification is enabled by default. For a trusted debugging MITM proxy, prefer Client(tls_verify="/path/to/proxy-ca.pem"); use Client(tls_verify=False) only for temporary local debugging because it allows session interception.

Realtime MQTT and Direct

aiograpi 1.1.0 adds experimental async Realtime MQTT/MQTToT helpers. They can receive Direct message sync payloads, publish lightweight Direct actions over MQTT, and subscribe to FBNS push notifications.

from aiograpi import Client

cl = Client()
await cl.login(USERNAME, PASSWORD)


def handle_message(payload):
    print(payload)


cl.realtime_on("message", handle_message)
rt = await cl.realtime_connect()
await rt.direct_subscribe()

await rt.direct_send_text(thread_id, "Hello from MQTT")

while True:
    await cl.realtime_read_once()

See the Realtime MQTT guide for Direct sync, MQTT Direct actions, and FBNS push examples.

Basic Usage

from aiograpi import Client

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

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

Runnable Examples

Practical async scripts live in examples/README.md. They cover session login, public lookups, media downloads, feed uploads, Reels and Trial Reels, story uploads, Direct messages, proxies, and optional curl-backed public transport.

Session Persistence

Logging in fresh on every run is the fastest way to get your account flagged. Persist the session and reuse it:

from aiograpi import Client

cl = Client()
await cl.login(USERNAME, PASSWORD)
cl.dump_settings("session.json")

# reload later without entering credentials again
cl = Client()
cl.load_settings("session.json")
await cl.login(USERNAME, PASSWORD)

If you want explicit control over the loaded session object:

from aiograpi import Client

cl = Client()
cl.set_settings(cl.load_settings("session.json"))
await cl.login(USERNAME, PASSWORD)

Login by sessionid

from aiograpi import Client

cl = Client()
await cl.login_by_sessionid("<your_sessionid>")

login_by_sessionid() is a lightweight compatibility path. For long-lived automation prefer the regular login()dump_settings()load_settings() / set_settings() flow.

If a browser/web sessionid returns login_required or logs the browser out, Instagram rejected that session for the private mobile API. Use a stable password login once, save settings with dump_settings(), and reuse those settings instead of repeatedly importing browser cookies.

Typical Tasks

List and download another user's posts

target_id = await cl.user_id_from_username("target_user")
posts = await cl.user_medias(target_id, amount=10)
for media in posts:
    await cl.photo_download(media.pk)

Search a location by name

places = await cl.location_search("Times Square")
print(places[0].name, places[0].pk)

Followers via the new private GraphQL surface

import uuid

data = await cl.private_graphql_followers_list(
    user_id="25025320",
    rank_token=str(uuid.uuid4()),
    order="date_followed_latest",
)
# Raw GraphQL envelope: {"data": {...}, "status": "ok", ...}

See Private GraphQL & doc_id for the full new-mobile-API surface (followers, clips, search, inbox).

Additional example (story upload with mentions / hashtags / media)
from aiograpi import Client
from aiograpi.types import StoryMention, StoryMedia, StoryLink, StoryHashtag

cl = Client()
await cl.login(USERNAME, PASSWORD, verification_code="<2FA CODE HERE>")

media_pk = await cl.media_pk_from_url('https://www.instagram.com/p/CGgDsi7JQdS/')
media_path = await cl.video_download(media_pk)
subzeroid = await cl.user_info_by_username('subzeroid')
hashtag = await cl.hashtag_info('dhbastards')

await cl.video_upload_to_story(
    media_path,
    "Credits @subzeroid",
    mentions=[StoryMention(user=subzeroid, x=0.49892962, y=0.703125, width=0.8333333333333334, height=0.125)],
    links=[StoryLink(webUri='https://github.com/subzeroid/aiograpi')],
    hashtags=[StoryHashtag(hashtag=hashtag, x=0.23, y=0.32, width=0.5, height=0.22)],
    medias=[StoryMedia(media_pk=media_pk, x=0.5, y=0.5, width=0.6, height=0.8)]
)

Documentation

Contributing

List of contributors

Releasing

Releases are automated via the publish.yml GitHub Actions workflow with PyPI trusted publishing. To cut a new release:

  1. Bump version = in pyproject.toml.
  2. Add a section to CHANGELOG.md.
  3. Commit and push to main.
  4. Tag: git tag -a 0.x.y -m "Release 0.x.y" && git push origin 0.x.y.

The workflow then builds sdist + wheel, verifies the tag matches pyproject.toml, publishes to PyPI, and creates the GitHub release with both artefacts attached — no API tokens needed.