Skip to main content

InstaWizard

Python client for Instagram private mobile & web API — with async and sync interfaces

PyPI Python License

🌐 Languages: English · Русский


Highlights

Common

  • ⚡ Async & sync — native async clients and synchronous wrappers out of the box
  • 💻 Mobile & web clients
    • MobileClient / SyncMobileClient — private mobile API (mimics the official Android app)
    • WebClient / SyncWebClient — web API (mimics browser behavior)
  • 🌐 HTTP proxy support — static or auto-rotating via a custom provider
  • 📱 Device / browser fingerprints — built-in presets and random generation
  • 💾 Session persistence — dump_state() / load_state(), no re-login on every run
  • 📋 Standard logging integration out of the box

All features below are available in both async and sync clients.

Mobile client

  • Login and session management
  • Profile editing (bio, name, profile picture)
  • User search; get info by user ID or username
  • Follow / unfollow, remove follower; retrieve followers and following lists
  • Direct: inbox, pending requests, send messages and reactions, group thread management
  • Media: like, unlike, save; comments — get, add, like, unlike
  • Media publishing: photos and videos to feed, Stories, carousels (albums), and Reels
  • Checkpoint / challenge detection and passing
  • Account registration via SMS / Email

Web client

  • Login and session persistence
  • Follow / unfollow
  • Like / unlike media
  • Add / like / unlike comments
  • Checkpoint / challenge detection and passing

Installation

Requires Python 3.11+

pip install insta-wizard

From GitHub (latest):

pip install git+https://github.com/5ou1e/insta-wizard.git

Quick start

Mobile (async):

import asyncio
from insta_wizard import MobileClient

async def main() -> None:
    async with MobileClient() as client:
        await client.login("USERNAME", "PASSWORD")

        me = await client.account.get_current_user()
        print("Logged in as:", me.username)

        user = await client.users.get_info_by_username("instagram")
        await client.friendships.follow(user.pk)

asyncio.run(main())

Web (async):

import asyncio
from insta_wizard import WebClient

async def main() -> None:
    async with WebClient() as client:
        await client.login("USERNAME", "PASSWORD")

        await client.likes.like("MEDIA_ID")
        await client.likes.unlike("MEDIA_ID")

asyncio.run(main())

Sync — no asyncio needed:

from insta_wizard import SyncMobileClient

with SyncMobileClient() as client:
    client.login("USERNAME", "PASSWORD")

    me = client.account.get_current_user()
    print("Logged in as:", me.username)

    user = client.users.get_info_by_username("instagram")
    client.friendships.follow(user.pk)

Proxy

The client supports routing traffic through a proxy. Currently only HTTP/HTTPS proxies are supported, with or without authentication.

from insta_wizard import MobileClient, ProxyInfo

# Supported formats: "1.2.3.4:8080", "user:pass@1.2.3.4:8080", "1.2.3.4:8080:user:pass"
proxy = ProxyInfo.from_string("user:pass@1.2.3.4:8080")

async with MobileClient(proxy=proxy) as client:
    ...
    await client.set_proxy(ProxyInfo.from_string("..."))  # change at runtime
    await client.set_proxy(None)                          # or remove it

On network errors, the client can automatically retry the request and rotate to a new proxy if needed — configure this via TransportSettings:

Automatic rotation — implement ProxyProvider and pass it via TransportSettings:

import random

from insta_wizard import TransportSettings, ProxyInfo
from insta_wizard.common.interfaces import ProxyProvider

class MyProxyPool(ProxyProvider):
    _proxies = [
        "194.67.201.14:8080:user1:pass1",
        "91.108.4.220:3128:user2:pass2",
        "185.199.229.156:7492:user3:pass3",
    ]

    async def provide_new(self) -> ProxyInfo | None:
        return ProxyInfo.from_string(random.choice(self._proxies))

settings = TransportSettings(
    network_error_retry_limit=3,   # retry each proxy 3 times before switching
    network_error_retry_delay=1.0, # wait 1 s between retries
    change_proxies=True,           # switch proxy after all retries are exhausted
    proxy_change_limit=5,          # switch at most 5 times, then raise NetworkError
    proxy_provider=MyProxyPool(),
)

async with MobileClient(transport_settings=settings) as client:
    ...

When all retry attempts are exhausted, the client calls proxy_provider.provide_new() and retries with the new proxy.


Device / browser presets

You can configure device settings for the client (user-agent, fingerprint, etc.). If not set explicitly, a default preset will be selected automatically.

Mobile (Android):

from insta_wizard import AndroidDeviceInfo, MobileClient
from insta_wizard.mobile.models.android_device_info import AndroidPreset

device = AndroidDeviceInfo.from_preset(AndroidPreset.SAMSUNG_A16)
device = AndroidDeviceInfo.from_preset(AndroidPreset.PIXEL_8, locale="en_US", timezone="America/New_York")
device = AndroidDeviceInfo.random()  # picks a random preset from real Android devices

async with MobileClient(device=device) as client:
    ...

Available presets: SAMSUNG_A16, SAMSUNG_S23, SAMSUNG_A54, PIXEL_8, REDMI_NOTE_13_PRO

Web (browser):

from insta_wizard import BrowserDeviceInfo, WebClient
from insta_wizard.web.models.device_info import BrowserPreset

device = BrowserDeviceInfo.from_preset(BrowserPreset.CHROME_143_WIN11)
device = BrowserDeviceInfo.random()  # picks a random preset from real browser configurations

async with WebClient(device=device) as client:
    ...

Available presets: CHROME_143_WIN11, CHROME_143_MACOS


Session state

Persist a session between runs — no need to re-login every time:

import asyncio, json
from insta_wizard import MobileClient

async def main() -> None:
    async with MobileClient() as client:
        await client.login("USERNAME", "PASSWORD")

        with open("session.json", "w", encoding="utf-8") as f:
            json.dump(client.dump_state(), f)

asyncio.run(main())

Restore on the next run:

import asyncio, json
from insta_wizard import MobileClient

async def main() -> None:
    async with MobileClient() as client:
        with open("session.json", encoding="utf-8") as f:
            client.load_state(json.load(f))

        me = await client.account.get_current_user()  # already authenticated

asyncio.run(main())

State is a plain Python dictionary. Proxy and transport settings are not included — pass those to the constructor as usual.


Logging

Clients log via Python's standard logging module by default. To enable output:

import logging

logging.basicConfig(level=logging.INFO)

To use a custom logger or disable logging entirely:

from insta_wizard import MobileClient, NoOpInstagramClientLogger

async with MobileClient(logger=NoOpInstagramClientLogger()) as client:
    ...

See examples/logging_setup.py for a custom logger example.


Commands

Commands are typed wrappers around individual Instagram API calls that return the raw response as-is. In some cases it may be useful to call them directly via client.execute():

from insta_wizard.mobile.commands.user.usernameinfo import UserUsernameInfo

raw = await client.execute(UserUsernameInfo(username="someuser"))

To browse all available commands:

from insta_wizard.mobile import print_help  # or insta_wizard.web

print_help()  # prints a table: command name, module, signature

Examples

See the examples/ folder for ready-to-run scripts covering device presets (mobile and web), proxy setup and rotation, session persistence, and common client flows.


Roadmap

  • Login checkpoint passing
  • Broader API coverage

Disclaimer

This library is a developer tool for building personal integrations and exploring the Instagram API. It is not intended for spam, automation at scale, or any activity that violates Instagram's Terms of Service. We are not affiliated with Meta or Instagram. Use only with accounts and data you have authorization to access.


License

MIT — see LICENSE

Metadata

Release files for insta-wizard 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for insta-wizard 0.1.7
File Size Uploaded
insta_wizard-0.1.7.tar.gz 161.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for insta-wizard 0.1.7
File Interpreter ABI Platform
insta_wizard-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 478.4 kB

Release files / insta_wizard-0.1.7.tar.gz

Download URL insta_wizard-0.1.7.tar.gz
Size 161.4 kB
Tags Source
SHA-256 checksum
How to use checksums
4fe3978d07d7b27adf0f951f48ad890bc79f6ff3bbf109303c95a76ae9efc55e
BLAKE2b-256 checksum
How to use checksums
8872aca5b1a1366406b4b5609887ba37c8a2f1da061d147b01c9e547e279e052
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release files / insta_wizard-0.1.7-py3-none-any.whl

Download URL insta_wizard-0.1.7-py3-none-any.whl
Size 317.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
033d708402a96cc84abdae670063eda7239a2db19338694dc377a1597578e955
BLAKE2b-256 checksum
How to use checksums
cb19ede27bdb6b2ed2393400b97cda2eb1b661674c31173e9c6cb447f6624c93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.1.7 This release

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page