Troubleshooting
Common errors and what to do about them. If your case isn't listed, check Handle Exceptions for the full exception hierarchy or open a bug report.
Authentication
PreLoginRequired: Authentication required
You called a private method (most _v1, private_graphql_*, anything
that mutates account state) without logging in first.
client = Client()
await client.login(USERNAME, PASSWORD) # do this first
user = await client.user_info_v1("25025320")
Or restore from a saved session:
client = Client()
client.set_settings(saved_dict) # contains a valid sessionid
user = await client.user_info_v1("25025320")
BadCredentials: Both username and password must be provided
Empty / missing username or password. Check env vars are loaded.
BadPassword
Wrong password, OR Instagram flagged your account and silently invalidated the password. If the same credentials work in the IG app, you've been flagged — wait 24-48 hours, change IP, log in via app first.
TwoFactorRequired
Pass verification_code= to login():
await client.login(USER, PASS, verification_code="123456")
For TOTP-based 2FA, generate the code from the seed:
code = client.totp_generate_code(seed)
await client.login(USER, PASS, verification_code=code)
ChallengeRequired
Instagram wants you to solve a challenge (email/SMS code, photo verification, phone confirmation). See Challenge Resolver for the flow. Often triggered by:
- New IP / device combination they haven't seen.
- Datacenter proxy (they fingerprint).
- Too many requests in a short window.
LoginRequired (after a successful login)
Your sessionid expired or was invalidated server-side. Re-login:
await client.login(USER, PASS, relogin=True)
Some private_graphql_* endpoints surface this via the 0.6.5+ body-error
promotion — you'll get LoginRequired, not generic ClientForbiddenError,
so your retry logic can branch on it correctly.
Network & TLS
httpx.ConnectError / httpx.ReadError
Connection-level failure. Most common causes:
- Proxy is dead or wrong port.
- Proxy provider rate-limited you (try other accounts in your pool).
- Instagram blocked the proxy IP — switch to residential.
ssl.SSLCertVerificationError / TLS handshake failures
Since 0.6.6 aiograpi verifies TLS by default. If your proxy is a known SSL-MITM (corporate inspection gateway), opt out after construction:
client = Client()
client.private.verify = False
client.public.verify = False
client.graphql.verify = False
Don't blindly disable on residential proxies — that's how MITM attackers intercept your sessionid.
AuthRequiredProxyError: 302 Found
Your proxy provider redirected you to their captive portal. Usually means:
- Out of bandwidth quota.
- Subscription expired.
- Proxy creds invalid.
Open the proxy's management URL (often the redirect target) to confirm.
IG-side rate limits & blocks
PleaseWaitFewMinutes
Self-explanatory. Wait, don't retry-loop. aiograpi already retries with backoff on 429, so this means you've exhausted that and Instagram wants you to actually pause.
ClientThrottledError (HTTP 429)
You're hitting the endpoint too fast. Slow down:
client.delay_range = [3, 6] # random delay 3-6s between requests
RateLimitError
Account-level rate limit (vs endpoint-level ClientThrottledError).
Different account, different proxy, or wait it out.
ProxyAddressIsBlocked
Instagram has blocklisted your proxy IP. Switch to a different (preferably residential) IP.
FeedbackRequired
Instagram thinks your account is doing automated activity (likes, follows, DMs). Stop those operations on this account for 24-72 hours. The account isn't banned, just on a behavioural watch.
Data / parsing
pydantic.ValidationError: N validation errors for User/Media/...
Should be rare since 0.7.0 — PreLoginRequired now fires upfront for
unauthenticated calls instead of letting them reach the extractor.
If you see this on an authenticated call:
- Instagram changed the response shape. File a bug with the full traceback
and the response body (
client.last_json, redacted). - Your
last_jsonmay have a clue:print(client.last_json)after the failure.
ClientGraphqlError: Missing 'data' in GraphQL response
GraphQL endpoint returned an error envelope. The doc_id may have rotated
(IG re-registers queries periodically). Capture a fresh client_doc_id
from a current Instagram-app build and pass it explicitly:
data = await client.private_graphql_followers_list(
user_id="25025320",
rank_token=rank_token,
client_doc_id="<fresh capture>",
)
See Private GraphQL & doc_id for the rotation playbook.
ClientNotFoundError on /media/.../comments/
Could be a real "media doesn't exist", or could be a masked challenge.
Since 0.4.1 aiograpi promotes 404 b"Not Found" to ChallengeRequired
on the private path; since 0.6.5 it does the same on the
private_graphql_* path. If you're on an older version, upgrade — you
may be silently dropping work that's actually a challenge.
Uploads
PhotoConfigureError / VideoConfigureError / AlbumConfigureError
Instagram accepted the upload but the configure call failed. Common causes:
- Image / video doesn't meet IG specs (aspect ratio, codec, size).
- Account flagged — uploads work less reliably than reads on flagged accounts.
- Cross-region upload (uploaded from one IP, configured from another).
VideoTooLongException
Self-explanatory. Trim or split.
Resource leak warnings on upload retries
Since 0.4.1 aiograpi closes file handles in finally: blocks across
photo/video/album/clip/story/igtv. If you see ResourceWarning: unclosed file
on 0.0.x, upgrade.
Setup
pip install aiograpi succeeds but import aiograpi fails on httpx
requirements.txt pins httpx==0.28.1. If pip resolved a different
version due to a constraint elsewhere in your project, force-pin:
aiograpi==0.7.1
httpx==0.28.1
RuntimeError: This event loop is already running
You're calling await ... outside an async function. Wrap in
asyncio.run(main()) or use nest_asyncio for Jupyter.
mypy complains about cross-mixin attributes
Known issue (.mypy-baseline = 1095). aiograpi mixins reference each
other's attributes (self.user_id, self.private_request) which mypy
sees as [attr-defined] because each mixin is checked in isolation.
We ratchet the baseline down per release. For now, suppress with
# type: ignore[attr-defined] if you subclass.
When in doubt
- Check
client.last_json— Instagram's actual response body is often more informative than the exception class. - Check
client.last_response.status_codeandclient.last_response.url. - Run
tests/live/smoke.pyon your environment to confirm the basic flow works at all. - File a bug report —
include the traceback (redact creds),
aiograpi.__version__, Python version, OS, and proxy type. The issue template has all of this.