All notable changes to this actor are documented here.
-
Offline Mode no longer rejects a saved profile over "Min Engagement Rate (%)" just because its posts were never downloaded, when "Calculate Engagement Rate (ER)" is off. A normal run with engagement analysis off doesn't apply that filter to such a profile, but re-filtering saved profiles treated the filter as needing posts and rejected every one of them — so a free re-filter could come back empty where the same filters in a normal run return rows. Those profiles are now judged the way a normal run judges them.
-
The same fix for a run that resumes after a restart. With that combination of settings, results the run had already found, but whose posts hadn't been downloaded, were discarded instead of being restored. They are now restored.
- Clarified wording in the README, the input form and the storage record descriptions. Nothing changes in how the actor runs, what it returns or what it costs.
- The empty-run explanation promised in 0.0.26 now actually reaches the results. In that build the row was written but never emitted — it was placed earlier in the run than the explanation it carries, so the check that guards it was always false. The run's status line worked; the results row did not. Nothing else changed.
-
A brief hiccup no longer makes a real, public account look deleted. When an account can't be looked up on the first try, it is now double-checked through a second, independent route before being reported as unreachable. Accounts that really are deleted, private, or mistyped are still reported exactly as before.
-
Honest wording above the filter section. It used to say filters "save on processing costs". They don't: filters run after each profile is read, so they shape your results, not your bill. The Pricing section has always said this; the input form now agrees with it.
-
A run that returns nothing now says why in the results themselves. Until now the explanation went to the run log, the status page and the USER_MESSAGE record — none of which an API or MCP caller receives. An empty run now also returns one row carrying the same explanation, and the run's status line carries its headline.
-
Clearer wording when nothing could be scraped. The end-of-run note no longer says "Nothing was charged" on runs where some accounts were read and then rejected by your filters — reading is what the charge is for, so the note now says which part was charged and which wasn't.
When a run cannot finish because something outside this actor refuses the request, it now
says so in one plain sentence instead of passing along whatever text came back. Input
fields, output columns, defaults and pricing are unchanged from 0.0.24.
- Creator accounts were being reported as personal, and the account-type filter dropped them.
Instagram has three kinds of account — business, creator and personal — and the first two are
both professional: both can publish a Contact button with an email or a phone number. This actor
had been reading a single business/not-business signal, so every creator fell into the personal
bucket. On 60 accounts taken from this actor's own search results, 53% were creators — the
majority. Business only was discarding all of them, and Personal only was returning them
under the wrong name.
- Account Type column, on every analyzed row:
business, creator or personal, read from
Instagram's own account type. The README has listed this column for some time; it now exists. It
is the last column, so every column you already read keeps its position.
- Two new choices in Filter by Account Type: Creator only, and Professional (business or
creator) for when you want everyone with a Contact button and do not care which kind. Searching
for influencers? Choose Creator — the old advice to choose Personal was wrong.
Documentation only. The Related actors table now lists Instagram Email Scraper, for the
contact details a list of usernames publishes — email, phone, website and business category,
one row per account. No change to this actor's behaviour, input, output or prices.
Documentation only. The Related actors table now lists Instagram Comments Scraper, for
reading what a post's comments say — every comment and reply as a row, with @mentions and
#hashtags in their own columns. No change to this actor's behaviour, input, output or prices.
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.20. Saved tasks continue to work identically.
The rows explaining what the free plan held back were never reaching you.
On the free plan the actor adds a row per search term that still had accounts left when the run
stopped, saying how many more there were. Those rows were being written in a shape the dataset's
own column types reject — three columns are declared numeric, and a text placeholder in any one
of them makes the whole batch refused. So they vanished, and quietly: the failure was only a
warning in the run log, while the README and the dataset schema both said the rows were there.
This has been true since the actor was published.
A blank cell now takes the form its column actually accepts: "N/A" in a text column, null in
a numeric one. Nothing about your result rows changes. A test now checks every cell of these
rows against the published column types on every commit — nothing in this actor read its own
dataset schema before, which is how a shipped feature stayed dead with a green test suite.
- Related actors section updated to include Instagram Likes Scraper — paste a post or reel
link and get the accounts that liked or commented on it, enriched the same way this actor
enriches its own results.
- If a billing call fails mid-run, the run now shuts down in an orderly way instead of stopping
dead. Everything already collected is saved to the dataset and the run summary, and profiles the
platform did not actually bill for are no longer counted as charged.
- A failure during start-up — before the first profile is read — no longer ends the run without
explanation. The reason is now written to the log and to the run's status.
- The live status page can no longer take the run down with it if its port is unavailable.
- Runs now get 1 GB of memory by default instead of 512 MB. The busiest run measured used 87% of
the old ceiling, and a run that runs out of memory stops without saving anything.
- A run that returned nothing because of the last-post filter now says what the rejected profiles
actually looked like — "7 of 10 had no posts we could read, and this filter needs posts to judge
an account" — instead of naming the filter and stopping there. The sentence was already written
and could never appear, so every zero-row run caused by that filter gave you the filter's name
and no number to move.
- Correction to the 0.0.13 note on the Business-Address filter: full country names DO match
outside the US, Canada, Mexico and India — Instagram writes the city line as "Berlin, Germany"
or "Lagos, Nigeria", country spelled out in English; in the US, Canada, Mexico and India it
ends in the state ("Miami, Florida"). Abbreviations like "USA" or "UAE" are not what the field
carries.
- The filter's input-form description, the README guidance and the run messages now teach the
shape that works: a comma-separated list of several cities plus the region written out in full,
in Instagram's own spelling, accents included.
- When some profiles did publish an address and your terms simply missed them, the closing
message now says so and suggests the towns-plus-region list instead of staying generic.
- The location filter is now called "Filter by Business Address — professional accounts only",
because that is what it reads. Instagram publishes an address only on professional accounts that
filled it in, so ordinary creators have none at all and this filter rejects every one of them.
Write city names: the field holds a city, so "Miami" can match and "USA" never will.
- A run whose location filter cannot match anything now stops after the first 25 profiles instead
of paying its way through the whole search and reporting an empty result at the end. If none of
those 25 publishes a business address, the run says so, tells you how much of the search it
declined to pay for, and points at the field to clear. The profiles already fetched stay saved,
so you can clear the filter and re-filter them for free with Offline Mode.
- The pre-run warning about narrow filters now also fires on a location filter used on its own.
Until now it only spoke up when location was combined with keywords, so a run narrowed by
location alone went ahead with no warning at all — and those are the runs most likely to fetch
profiles, charge for them and save none of them.
- The expected-yield figure in that warning is now specific to the contact type you picked.
All four choices used to be quoted the same ~10%. They do not behave the same: asking for
BOTH an email and a phone — the strictest of the four — actually keeps about twice as many
profiles as asking for an email alone, and the warning now says so instead of understating it.
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.10. Saved tasks continue to work identically.
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.9. Saved tasks continue to work identically.
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.8. Saved tasks continue to work identically.
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.7. Saved tasks continue to work identically.
- Runs no longer fail when you start several at the same time. If you launched two or more runs together, one of them could stop with "Could not read this run's progress record in full" — and there was nothing wrong with it. Each run keeps its own list of the accounts it has already looked at, so it can pick up where it left off; a run starting up would clear that list at the very moment another run was reading it. A run that cannot read the list now waits and tries again twice, re-opens the list so anything it saves afterwards is kept, and — if it has not analysed anything yet — carries on with an empty list instead of stopping. That check exists to protect a resumed run from being charged twice for the same account, and a run that has just started has nothing to be charged twice for. Only runs started alongside other runs were ever affected; a single run on its own was not.
- The language filter and the
Detected Language column now cover 44 languages instead of 13. Korean, Polish, Ukrainian, Dutch, Swedish, Serbian, Thai, Vietnamese, Greek, Hebrew, Persian and 23 others were already being recognised from the bio and captions — and then reported as "N/A", because the column only knew how to name 13 of them. They are now named, and each can be picked in Filter by Profile Language. Nothing changed for the 13 languages that already worked.
- The dataset description no longer says the actor has six search modes. It has one — keyword search and hashtag search — and the description was inherited from a larger actor.
- README now lists the Example tasks — ready-to-run searches you can start in one click, no setup. Five more are published in German, Korean and Portuguese and are linked from the Examples tab.
- Runs started from an Example task page no longer open with "Unknown input fields were ignored". The page carries one marker field of ours in its input, and the check that names mistyped fields was counting it as one of the customer's.
- Two runs of the same search are now recognised as the same search whether they were started from an Example page or from the input form.
- Declared the
analytics_failed_* diagnostics records in the key-value-store schema. They were already being written when a background bookkeeping call could not be delivered, and the schema did not mention them.
- Output sample in the README is now a real row from a real run.
- Declared
Posts in Last 30 Days in the dataset schema; the column was already being written but not documented (inherited from the parent).
Initial release.
- Finds Instagram accounts by keyword search and by hashtag search, then enriches each one with contact details, audience size, engagement rate, Reels metrics, business category and detected language.
- Search terms are read in parallel and merged round-robin, so one broad term cannot consume the whole budget while a narrower one returns nothing.
- 20+ post-fetch filters: follower band, engagement floor, Reels view ratio, language, business category, contact-channel presence, posting cadence, verification.
- Single paid event,
PROFILE_ANALYZED at $0.01 per analyzed account. Accounts that could not be read are not charged.
- An empty input runs a small capped demo search instead of failing, and says so in the log, in
USER_MESSAGE, in RUN_SUMMARY and on the status page.
- Free plan: 5 accounts per run, with a row per search term reporting how many candidates it still had.
- Offline Mode re-applies filters to already-fetched accounts without new requests or charges.
- Resume from checkpoint after an interruption; analyzed accounts are never re-billed.