First version.
- Input: a list of user names, @names or profile addresses (
profiles); includeRecentPosts (default on), includeSimilarAccounts (default off), extractBioContacts (default on), maxProfiles, proxyConfiguration.
- One row per profile, read from what Instagram shows a visitor who is not signed in: exact follower and following counts, name, bio, bio links, verified and private flags, highlight titles, Threads name, story and reels flags — and, from the profile's public embed page, the exact post count and the six newest posts with their like and comment counts and coauthors, median likes and comments, engagement rate, posts per week, time of the last post and the paid-partnership flag. On request the "accounts you might like" list.
- A private profile is delivered as a row with its public header; the fields Instagram does not show for it are
null.
- Lines without a profile get a free status row that says why: not a profile, no account with that user name, a profile shown only to signed-in visitors, a second spelling of a profile another line names, or a profile that could not be read.
recentPostsStatus says why a row has or lacks its post figures: ok, not-offered (Instagram's embed page shows no data for this public profile), unanswered, private, off.
bioEmails lists only an address the account owner wrote into the public bio text; extractBioContacts: false leaves it null.
- How requests leave: from the run's own address; when Instagram turns that address away the Actor moves that kind of request to Apify Proxy by itself, and a profile or similar-accounts query every datacenter address has turned away goes up to twice more through a residential address if the account has them (never an embed page). The run's log and its
SOURCE_REPORT record say which road was used.
- Billing: one pay-per-event event,
profile, per delivered profile row. Status rows are free.
- Measured on 2026-10-09 in local runs through Apify datacenter proxy (150 profiles): every line gave a row; post figures for 147, an engagement rate for 145.
- Before the first upload the shared modules were brought to their state of 2026-10-09 02:57 UTC: status rows keep their place among the rows, the residential last resort is used for the query road only (never for embed pages), and a failure of the proxy tunnel is named as such.
- Requests to one address start at least 80 ms apart (12 a second): a platform run that sent about 27 a second from its own address was answered HTTP 429 after 115 requests and had to move to the proxy.
- Measured on the Apify platform on 2026-10-09 (build 0.1.1, 512 MB): 150 of 150 profiles delivered in 74 seconds from the run's own address, 147 of them with post figures; in two further runs (450 lines, 150 profiles) Instagram turned the run's address away and the Actor went on through Apify Proxy without losing a row; a run restarted part-way on our request delivered no profile twice. The runs are listed in the README.
After an independent review of the README (21 findings, _qa/q15-refutation-2026-10-09.md):
recentPostsStatus tells three cases apart where it told one: not-offered is Instagram's own "may be broken" embed page or no page at all (HTTP 404); a page that came in a form the Actor cannot read is unreadable — the row is delivered without post figures, charged, and the status message asks you to report the run. Before, every unreadable page passed as not-offered with the blame on Instagram.
- Start-up check of the embed page. A run that wants post figures also looks at one known profile's embed page before it reads anything: a page that has changed its form ends the run there, uncharged, with the "has to be updated" message. A page that is refused, does not answer or shows no data does not end the run.
engagementRate has four significant digits instead of five decimals: a large account used to get one or two digits (natgeo 0.0002, now 0.0002017), and a rate below 0.000005 used to read 0.
- A proxy set in the input is the road of every request: the run does not move to Apify Proxy or to a residential address by itself; a setting the platform refuses ends the run with a message before anything is read (it used to go on without a proxy).
- Messages: a row whose write or charge failed "may be in the dataset" (the Actor cannot tell which half failed); a run whose rows could not be written no longer says "Instagram did not answer"; a row without post figures that is run again "is a new row, charged again".
- Texts corrected: which lines get no row (the ones a limit or a stop leaves unread), what is charged (every delivered row, with or without post figures), how common shared posts are and what they do to the rate, how many posts a median can rest on, the rounding of the rate, the start-up check, the age-restricted case, Instagram's app link and post addresses given as profile lines.