HARVESTMYDATA
by HarvestMyData

Instagram Put a Login Wall on web_profile_info in September 2026. Here's the Header Pair That Still Works.

instagramscrapingtechnicalweb_profile_info

What broke

In February we published a breakdown of i.instagram.com/api/v1/users/web_profile_info/, the one endpoint that still returned full Instagram profile JSON without a login. That article is still accurate about the response format and the HTTP/2 requirement. It is no longer accurate about the headers.

Around the second week of September 2026 the endpoint started answering every logged-out request with this:

HTTP/3 401
{"message":"Please wait a few minutes before you try again.","require_login":true,"igweb_rollout":true,"status":"fail"}

The message text is the same one Instagram uses for rate limiting, which sends people chasing proxies. It is not a rate limit. The body carries require_login: true and igweb_rollout: true, and the response comes back in ~140 ms from Instagram's application tier (x-stack: distillery), the same for a fresh residential IP as for a datacenter IP. It is a login wall, rolled out server-side.

There was a warning sign in July: business accounts started returning 400 {"message":"Asset asset://laser.provider/ig_business_category_subvertical has been deleted. You cannot use this schema"} while personal accounts still worked. Several scraper maintainers logged the same error. In hindsight that was the first stage of the same rollout, hitting the profile type with the most data first.

What we tested (and what did not help)

We run this endpoint at volume, so we tried everything before accepting the wall. Every one of these returned the identical 401 body:

  • The February headers (desktop web app ID 936619743392459, Mac Safari-style user agent)
  • A full Chrome 131 user agent that matches the TLS fingerprint
  • A complete browser header set: sec-ch-ua, Sec-Fetch-*, Origin, Referer, X-ASBD-ID, X-IG-WWW-Claim, X-Requested-With
  • Guest cookies from a homepage visit (csrftoken, mid, ig_did, datr) with a matching X-CSRFToken
  • The www.instagram.com host instead of i.instagram.com
  • Safari, Safari iOS, Firefox and Edge TLS impersonation with matching user agents
  • HTTP/2 forced instead of HTTP/3, and no Brotli
  • The iOS web app ID 1217981644879628
  • Three residential proxy networks, US-pinned exits, and a direct connection

Two variations produced a different error instead of a fix. Forcing HTTP/1.1 gives an empty 429. Sending the Android web app ID with a normal browser user agent gives 400 {"message":"useragent mismatch"}. That second error turned out to be the clue.

The combination that works

Instagram validates the app ID against the user agent. The Android web app ID is only accepted when the request looks like it comes from the Instagram Android app's embedded WebView. Pair those two and the endpoint answers logged-out again:

X-IG-App-ID: 3419628305025917
User-Agent: Mozilla/5.0 (Linux; Android 14; SM-S921B Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.0.0 Mobile Safari/537.36 Instagram 340.0.0.36.90 Android (34/14; 480dpi; 1080x2340; samsung; SM-S921B; e1s; s5e9945; en_US; 629151101)

Everything else from the February setup stays the same: Accept: */*, Accept-Language, Accept-Encoding: gzip, deflate, br, HTTP/2 or HTTP/3 via curl_cffi with Chrome impersonation, one fresh connection per request through a rotating residential proxy. It works on both i.instagram.com and www.instagram.com, with desktop or Android Chrome TLS impersonation, and through every proxy we tried.

The response schema is unchanged: data.user with is_business_account, is_professional_account, category_name, biography, follower and following counts, and the timeline media edges. The business accounts that had been failing with the "asset deleted" 400 since July return 200 with this pair too, including very large ones like nike and natgeo.

One thing the February article stated too loosely: logged out, this endpoint does not return business_email or contact_phone_number. Reading an account's public email still requires an authenticated session, which is what paid Instagram data APIs provide. Treat this endpoint as the profile and classification step, not the contact step.

How it holds up at volume

Numbers from our production workers in the ten days after the switch:

TestResult
60 profiles, 20 concurrent, fresh IP per request49 OK, 5 scattered 401, 3 timeouts, 2 empty bodies
12,368 followers enriched (one paid job)0 errors after retries, 18 minutes end to end
31,012 followers enriched0 errors, 31 minutes
250,000 followers enriched1 error, 4 hours 2 minutes

The scattered 401s are per-IP and go away on retry with a new connection, so a retry budget of three to five attempts absorbs them completely. Throughput is unchanged from before the wall.

A logged-out fallback if this pair dies too

Instagram's web GraphQL profile query still answers without a session at the time of writing:

POST https://www.instagram.com/graphql/query
Content-Type: application/x-www-form-urlencoded
X-IG-App-ID: 936619743392459
X-FB-LSD: <any random string>

lsd=<same string>&doc_id=7663723823674585&variables={"id":"<user pk>","render_surface":"PROFILE"}

It needs the numeric user ID rather than the username, and any value works for lsd as long as the header and the form field match. It returns biography, bio links, external URL, category, is_business, is_private and the counts, about 3 KB per profile. is_professional_account is always null when logged out and the business fields are thinner, so it is a weaker classification signal. Keep it as a fallback, not a replacement.

What this means in practice

  • If your enrichment pipeline started returning 100% 401 in September, it is not your proxies. Swap the app ID and user agent first.
  • Do not trust the "Please wait a few minutes" text. Read the body for require_login.
  • App ID and user agent are validated as a pair. Changing one without the other gets you useragent mismatch.
  • Expect this to move again. The July business-account 400 and the September wall were two months apart. Build the header set as configuration, not constants, and keep a small probe script that runs the full matrix so the next change costs an hour, not a week.

Summary

The desktop web app ID for web_profile_info is login-walled as of September 2026. The Android web app ID (3419628305025917) paired with the Instagram in-app Android WebView user agent still returns complete profile JSON logged out, through residential proxies, at the same throughput as before, including for the business accounts that had been failing since July. Public emails were never in the logged-out response; that step needs an authenticated session.

We built HarvestMyData to handle all of this for you.

No proxies, no code, no account needed.