login_required: how to recover the instagrapi session in Python
Maintained by the instagrapi contributors · Library on GitHub
Updated
You had a worker happily running for several hours — pulling user feeds, downloading media, posting comments, whatever the job was — and then the next call into instagrapi raised instagrapi.exceptions.LoginRequired: login_required. The previous call worked. Your credentials are correct. Your session.json exists on disk. None of that matters because what just happened is a session-lifecycle event, not an authentication problem and not a fingerprint problem. Instagram decided, mid-flight, that the cookie your client was sending is no longer valid, and the very next request after that decision came back with the login_required envelope.
This page is specifically about the runtime case where an established session dies, not the startup case where login itself fails. The two look superficially similar in tracebacks but the fix paths are entirely different. We will walk through the symptoms, look at the exact frame that raises, list the three reasons Instagram invalidates a live session, and finish with the relogin() recovery flow that refreshes the cookie jar without disturbing the device fingerprint that prevents challenge_required from cascading on top.
Symptoms
LoginRequired is raised on a non-login API call after the client has already been logged in successfully. The cl.user_id attribute is populated. Earlier calls in the same process worked. The exception fires from inside private_request, the low-level HTTP wrapper, after the response comes back with a 401 or 403 and a body whose message field contains the literal string login_required.
- The exception fires on a feature call (
user_medias,user_info,media_info,user_followers) — never onlogin()itself. - The same
Clientobject was working minutes or hours earlier in the same process. cl.last_response.status_codeis typically 401, occasionally 403 with the same body shape.cl.last_response.json()['message']contains the stringlogin_required; sometimes also alogout_reasonfield with values likesignature_revoked,password_changed, orconcurrent_session.- Catching the exception and immediately retrying the same call without intervention raises
LoginRequiredagain — the cookie is dead, not flapping.
Real-world traceback
Traceback (most recent call last):
File "scraper.py", line 28, in <module>
medias = cl.user_medias(USER_PK, amount=50)
File ".../instagrapi/mixins/user.py", line 195, in user_medias
items = self.user_medias_v1(user_id, amount)
File ".../instagrapi/mixins/private.py", line 311, in private_request
raise LoginRequired(response=response)
instagrapi.exceptions.LoginRequired: login_required
The frame that matters is instagrapi.mixins.private.private_request. That function is the funnel through which every authenticated API call passes; it is responsible for deciding whether the response Instagram returned is a real payload, a rate-limit envelope, or a session-death envelope. When it sees the login_required marker in the response body, it raises LoginRequired directly without retrying. This is intentional — silently re-logging in from inside the wrapper would risk exhausting the user’s 2FA codes or escalating to challenge_required on a flaky network blip, so the library hands the decision back to your code.
Why it happens
Sessions die for a small set of well-defined reasons, and you can usually figure out which one by inspecting the logout_reason field of cl.last_response.json(). The three causes below cover the overwhelming majority of production hits.
1. Server-side session revocation
This is the cause most teams find baffling because nothing changed on the client. Instagram independently invalidates the session token from the server side whenever the account owner takes a security action: changing the password, tapping “Log out of all sessions” in the security settings, enabling or disabling two-factor auth, or accepting a security alert in the mobile app. Instagram also revokes sessions automatically when its risk model decides retroactively that the session looked suspicious — this is the signature_revoked case and it can fire hours after the original login. From the worker’s perspective, nothing happened; from Instagram’s perspective, the cookie was poisoned and the next request had to reject it. The fix is not to prevent revocation (you mostly cannot) but to detect it cheaply and recover.
2. Concurrent requests on the same session from different IPs
If you accidentally run the same session.json from two places at once — your laptop and your server, or two replicas of the same Kubernetes pod — Instagram sees a single account hitting two IPs concurrently and treats it as session hijack. The token gets revoked in flight; whichever process is mid-request gets the login_required response and the other process gets it on its next call. This is especially easy to hit when you copy a session between machines for testing and forget to stop the original. Concurrency is fine across sessions and across accounts; what kills the cookie is the same cookie on two IPs.
3. Stale session age
Cookies have a finite useful life. The hard cap is roughly 90 days, but practical lifetime is shorter — typically 7 to 30 days for an active session, less for an account with low engagement signals. When a worker comes back online after a weekend or a long deploy gap, the first call will often raise login_required simply because the cookie aged out. The fix is the same as for revocation, but the prevention is different: keep your worker calling once an hour or so to keep the cookie warm, and re-dump after every successful call so the local copy stays current.
Fix in instagrapi
The recovery pattern for login_required has one rule that matters more than anything else: call relogin(), not login(). The two look interchangeable but they are not. login() discards the device fingerprint and re-runs the bootstrap handshake, which often triggers challenge_required because Instagram sees a “new device” logging in. relogin() reuses the existing fingerprint and only refreshes the cookie jar — exactly what you want.
-
Catch
LoginRequiredand re-login on the sameClientinstance. This preserves the device fingerprint stored incl.settings. Re-dump immediately after recovery so the on-disk session reflects the new cookies. The retry on the original call should now succeed.from instagrapi.exceptions import LoginRequired try: medias = cl.user_medias(USER_PK, amount=50) except LoginRequired: cl.relogin() cl.dump_settings("session.json") medias = cl.user_medias(USER_PK, amount=50) -
Wrap critical actions in a re-login decorator. Once you have more than one call site that needs recovery, ad-hoc try/except blocks become a maintenance problem. A small decorator centralizes the pattern. Note the
attemptsguard — without it, a permanently-revoked session can trigger an infinite re-login loop.import functools from instagrapi.exceptions import LoginRequired def auto_relogin(attempts: int = 1): if attempts < 0: raise ValueError("attempts must be >= 0") def deco(fn): @functools.wraps(fn) def wrapper(cl, *args, **kw): for attempt in range(attempts + 1): try: return fn(cl, *args, **kw) except LoginRequired: if attempt >= attempts: raise cl.relogin() cl.dump_settings("session.json") return wrapper return deco @auto_relogin() def fetch_user_feed(cl, pk): return cl.user_medias(pk, amount=50) -
Avoid concurrent use of the same session. This is a process-design fix, not an instagrapi API call. One
session.jsonper process; if you scale horizontally, give each replica its own dumped session for a different account. For a fuller treatment of how to structure the dump/load cycle across restarts, see the session persistence guide.
Deep dive
It is worth spelling out exactly why relogin() is preferred over login() here, because the distinction is not obvious from the method names. Both perform a credentials POST under the hood, but login() first calls pre_login_flow(), which regenerates several device IDs if the client believes it is a fresh install. relogin() skips that bootstrap and posts credentials against the existing fingerprint — same device_id, same phone_id, same uuid. From Instagram’s perspective, relogin() looks like the legitimate user re-entering their password on a known device, which is a low-suspicion event. login() from the same situation looks like a brand-new device asking for a session, which is exactly the pattern that fires challenge_required. Calling login() to recover from login_required is therefore the most common way to turn a 30-second recovery into a multi-hour incident.
One more nuance: if relogin() itself fails — Instagram has decided the credentials are not enough and wants a challenge or a 2FA code — it will raise ChallengeRequired or TwoFactorRequired, not LoginRequired. Your decorator should let those propagate; they need a different handler entirely, and silently swallowing them inside a LoginRequired catch will mask the real problem.
Related errors
- challenge_required: how to fix the Instagram challenge in instagrapi (Python) Fix instagrapi's challenge_required error in Python: SMS/email codes, TOTP fallback, and why session reuse stops it from coming back.
- please_wait_a_few_minutes: instagrapi rate limit and how to recover please_wait_a_few_minutes is Instagram's soft rate limit. instagrapi raises PleaseWaitFewMinutes — sleep, slow down, rotate proxy, persist.
Related guides
- Persisting instagrapi sessions: file, Redis, and Postgres patterns Reuse instagrapi login sessions across runs and processes: dump_settings, load_settings, and storing the session blob in Redis or Postgres.
- Handling instagrapi 2FA and challenge_required errors in Python Resolve instagrapi 2FA prompts and challenge_required errors: SMS, email, and TOTP flows with working callback handlers.
- Instagram Private API in Python: a practical guide with instagrapi How to use Instagram's private (mobile) API from Python with instagrapi. Login, session reuse, fetching media, posting, and avoiding common errors.
Frequently asked
What does login_required mean in instagrapi?
login_required is Instagram's signal that the session token in your cookie jar is no longer valid — usually because Instagram invalidated it (password change, suspicious activity, server-side logout). instagrapi raises LoginRequired when the next API call returns this signal.
Is login_required the same as ClientLoginRequired?
No. ClientLoginRequired is a separate class for login-flow failures during the credential POST itself. login_required specifically means an established session died mid-flight and needs to be re-established without re-running the full login handshake.
Why did my login_required hit after only a few hours?
Either Instagram invalidated the session as a security action, or the same session was used from two IPs in quick succession, which Instagram treats as a hijack attempt and revokes. login_required is the next call after that revocation.
How do I recover from login_required without losing the device fingerprint?
Keep the dumped session.json — it stores the device fingerprint independently of the cookie jar. Call cl.relogin() on the same Client instance to refresh only the cookies, then re-dump. The fingerprint stays intact, so this recovery does not re-trigger challenge_required or 2FA prompts.
Skip the infra?
Managed Instagram API — same endpoints, sessions and proxies handled.
Try HikerAPI → Full comparison