# Changelog of Instagram Related Profiles Scraper — Instagram Competitors (`steadyfetch/instagram-similar-profiles-scraper`) Actor

- **URL**: https://apify.com/steadyfetch/instagram-similar-profiles-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/steadyfetch/instagram-similar-profiles-scraper.md

## Changelog

### 1.0.26 — 2026-10-05

- **A link to an Instagram page that is not an account is now refused with nothing charged, before anything is looked up.** Links such as instagram.com/explore/, /about/, /legal/ or /archive/ were read as accounts with those names, and the run looked each one up. A story highlight link names no account either. Each now gets one uncharged row telling you to type the account name or paste its profile link. A story link (instagram.com/stories/<name>/…) now reads as the account that posted it, where before it was refused. An account name typed on its own is read exactly as before. The input fields and output columns are unchanged, and so is the charge for each profile delivered.

### 1.0.25 — 2026-10-03

- **A run that Apify moves to another server part-way through now picks up where it left off.** The part of the run that continues on the new server counts the profiles already delivered as delivered. It does not look up an account that was already finished again, and it does not write a second copy of a row that is already in your dataset. Before, the restarted part could read an already-finished account a second time, list its delivered profiles as duplicates, add a row saying profiles "were not delivered" when they were in your dataset and charged, and give that account more than its share of "Max profiles", taking it from the next account. Every profile is still delivered once and charged once, as before. The price, the input fields and the output columns are unchanged.

### 1.0.24 — 2026-10-01

- **An account with no share of "Max profiles" is no longer looked up.** "Max profiles" is split evenly between your accounts, so a run with more accounts than profiles gives the last accounts a share of 0. When an earlier account came back short, the run still looked up those last accounts and read their suggestions, two paid reads that could deliver nothing. They are now skipped without a read. Which profiles are delivered, the rows, the charges, the price, the input fields and the output columns are unchanged.

### 1.0.23 — 2026-09-26

- **A run on the Apify free plan now says which price it was charged at.** When a run is billed at the Apify free plan's price, the run page now says so in one sentence — $2.00 per 1,000 profiles — and names what the same run costs on paid plans: $1.17 on Bronze, $0.75 on Silver and $0.50 from Gold. Runs on paid plans read exactly as before. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.22 — 2026-09-26

- **A run cut off before it finishes is now accounted for.** The run now notes its own start in its internal record, so a run that ends without finishing — a hard abort, a crash or a timeout — is still accounted for on our side. Nothing changes about what is delivered, which rows are charged, the price, the input fields or the output columns.

### 1.0.21 — 2026-09-26

- **A long list of accounts on a paid Apify plan is no longer cut short by this actor's own per-run data budget, and a run that does reach it now says so truthfully.** On paid plans that budget now grows with the number of profiles you ask for, so a list of hundreds of accounts is read in one run. When a run does stop at it, the uncharged rows and the run page now say that a new run with those accounts collects the rest, instead of saying the stop lasts until the start of next month. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.20 — 2026-09-24

- **On the Apify free plan, this actor now has a daily allowance.** An account on the Apify free plan can make up to 24 Instagram lookups on this actor in any 24 hours (two per account you name, so 12 accounts), and accounts on the free plan share one daily allowance on this actor. Past either, the run keeps every profile it already delivered, adds one uncharged row saying when the allowance resets (UTC), and says the same on the run page. Paid Apify plans carry no daily allowance, and nothing changes for them: not the price, the input fields or the output columns.

### 1.0.19 — 2026-09-24

- **Settings sent wrapped in an extra "input" object are now read.** A run whose input arrives as `{"input": {…}}` — for example from `run_input={"input": {...}}` in the Python client — now reads those settings as if sent directly and adds one uncharged note row naming them. Before, the run stopped with a guidance row and collected nothing. Nothing changes about the price, the input fields or the output columns.
- **The run page no longer says your account list "was run at this actor's own ceiling" when your accounts arrived under another field name.** That line is now said only of a cap that really ran at this actor's limit; the uncharged note row naming the field to use is unchanged.

### 1.0.18 — 2026-09-24

- **A run that Apify restarts after it has already delivered keeps its own record of that delivery.** If the restarted part of a run delivers nothing new, the run's internal record now keeps what the earlier part delivered and charged, with a note of the restart, instead of being rewritten as if nothing had been delivered; one line in the run log says so. Nothing changes about what is delivered, which rows are charged, the price, the input fields or the output columns.

### 1.0.17 — 2026-09-23

- **The accounts field is no longer marked required in the input form, and its help now opens with what to pass and an example.** An AI agent or an API call that leaves it out gets the built-in sample rows, exactly as a bare Start always did; the help says so plainly instead of calling the field required. It also no longer says a post link is refused with a row naming another actor — the row asks for the account name instead, as it always has.
- **The top of this page now says how to schedule a weekly rerun**, and that each rerun returns a fresh copy of the whole list, charged like any run. Nothing changes about what is delivered, which profiles are charged, the price, the input fields, the output columns or the charged event.

### 1.0.16 — 2026-09-22

- **The run log no longer prints an internal usage summary at the end of a run, and a failed internal bookkeeping write no longer prints where it was being saved.** Nothing changes about what is delivered, which rows are charged, the price, the input fields or the output columns.

### 1.0.15 — 2026-09-22

- **The run log no longer prints internal cost lines, and a row stopped by this actor's own monthly collection allowance no longer quotes a dollar figure.** Those numbers described our own costs with the data source, not anything you pay. The row still says the allowance was reached and that it resets at the start of each month; your rows and charges are unchanged.

### 1.0.14 — 2026-09-22

- **When the data source behind this actor goes down, the run now says so and asks you to try again, instead of reporting the account as permanently unavailable.** A source outage answers with a status code that says nothing about the handle you asked for — the kind a service's front door sends while its own servers are unreachable. The run used to treat any answer it did not have on a short list as a final verdict about your account, so during an outage on 22 September a handle that had been served fifteen minutes earlier came back marked as refused for good, with a row telling you not to bother re-running it. It now works the other way round: only the answers the source actually gives ABOUT what you sent — not found, private, malformed — are treated as final, and everything else is read as temporary, retried a few times inside the run, and reported as an uncharged row worth re-running. Nothing you are charged changes, and an account that really does not exist, or really is private, is still the same definitive answer it has always been.

- **An answer the data source has never sent before now counts as an outage rather than as something we paid for.** The run keeps its own record of which of the source's answers cost us money, and until this build that record was a fixed list — so a response nobody had listed, such as a code the source first sent during an outage, was read as one we had bought. Now only the answers the source actually bills count as bought; everything else is booked at nothing and simply tried again. Nothing changes about what is delivered, what you are charged, the price, the input fields or the output columns.

### 1.0.13 — 2026-09-19

- **The monthly allowance behind this actor's data reads has been raised again — a busy month no longer stops delivery part-way through.** Nothing you are charged changes: the allowance is ours, not yours, and a run that ever meets it still stops honestly and charges nothing for what it did not deliver.

### 1.0.12 — 2026-09-19

- **The whole "Maximum cost per run" you set is now spent on profiles; before this build the run held back about a twelfth of it.** Your cap pays for profiles and nothing else — the compute, the proxy and the data behind the run are ours, not yours — but the run was still reserving roughly 8% of your cap against those costs before it planned a single profile. So a cap worth ten profiles bought nine, and the tenth was money you had authorised and could not spend. That reserve is gone. A run at its cap still ends the same honest way it always did: it stops itself, tells you what it cut and why, and charges you for nothing it did not deliver. No price, input field, output column or charged event changed.

### 1.0.11 — 2026-09-18

- **The monthly allowance behind this actor's data reads has been raised — a busy month no longer stops delivery part-way through.** Nothing you are charged changes: the allowance is ours, not yours, and a run that ever meets it still stops honestly and charges nothing for what it did not deliver.

### 1.0.10 — 2026-09-18

- **When the run page's one-line summary is too long to fit, the sentences about what you were charged are now the last to go, not the first.** Apify cuts that line at 500 characters, so a long run drops clauses until it fits — and the order it dropped them in was wrong: "N accounts suggested for more than one of your accounts were delivered once" (one read, one charge) and "none of the undelivered rows was charged" were being thrown away to make room for a settings note and a request to open a support issue. Measured across 120 shapes a real run can end in, 24 of them lost a sentence about money or lost the one sentence telling you what to do next, while the line still read as a tidy 500 characters. Everything that costs you nothing to lose now gives way first — the census of undelivered rows folds to a pointer, then the settings note and the support ask, then the stop's own guidance, which the receipt row carries in full — and only under all of that do the money sentences shorten to their plainest form. They never disappear. Nothing about what is collected or charged changed.

### 1.0.9 — 2026-09-16

- **"Instagram lists no accounts similar to this one" is now asked twice before it is said.** That sentence is definitive — it tells you there is nothing there and not to run again — and it was written off a single read that came back holding nothing. A source answering nothing is not the same as Instagram having nothing: a one-off blank read was published as a fact about your account. When the read comes back empty it is now asked once more, and only a second empty answer earns the definitive row. If the second read brings accounts, you simply get them. If the second read fails for any other reason, the empty stands unproven and the row says the read was temporary and worth running again, rather than telling you to stop. A refusal that names its own reason — Instagram declining to suggest anything from this account at all — already carries its proof and buys no second read. An account that served fewer accounts than you asked for is unchanged. Nothing is charged for any of it.

### 1.0.8 — 2026-09-16

- **The row that says your own time limit stopped an account now fires in every case it should, not just the last seconds of a run.** The last release added that row — but it worked out which case it was by asking whether the run had already reached its own stopping point, and a read is cut off by your limit well before that. In the gap between the two the row still read as the data source being unavailable and still pointed you at a re-run that would stop in exactly the same place. Both paid reads — the handle lookup and the suggestions themselves — now know, at the read itself, whether your own limit is what ended them, and say so every time; the run also no longer asks again for a read it has no time left to use. A read the source really did refuse still reads exactly as before, and nothing about what is collected or charged changes.

### 1.0.7 — 2026-09-15

- **"Max run seconds" now really ends the run — before, a slow read could carry it past the number you typed.** Your time limit decided when the next read was allowed to *start*; once one was sent, only the reader's own 25-second timer could end it, so a stalled read ran on past your limit and a run could close after the time you set. It now ends at your limit: a read is given the shorter of its own timer and the time your run has left, so nothing outlives the clock. Two smaller things come with it. Your limit is now counted from when the **run** started rather than from when it finished starting up, so the seconds spent booting are yours and not extra — and a run the platform moves to another machine part-way through keeps what is left of your window instead of starting a fresh full one. And an account that was cut by your own time limit is reported as exactly that — the stop row saying the run clock ran out, counted with the rest of the time-limited residue — instead of the "temporarily unavailable, please re-run" row, which was asking you to pay for a second run to work around a limit you set yourself. Nothing about what is collected or charged changed: a profile that is not delivered still carries no result fee, and no price, no input field, no output column and no charged event changed.

### 1.0.6 — 2026-09-14

- **A run that brings back no suggestions now tells you what to do about it — and counts the mistake it never showed.** A run that delivered nothing used to name only the count and a reason code — "Delivered 0 profiles of 1 asked for across 1 account. Not delivered: 1 not found" — and stop there, with no next step, because the run had ended cleanly and only a run stopped by a limit ever said anything further. Each reason now carries its own plain sentence: a handle Instagram has nothing at tells you to open it in a browser and says a re-run answers the same, a private account says this actor reads public accounts only, an account Instagram is offering no suggestions for says the list is built from that account's own audience and a re-run answers the same until that changes, a temporary read says to start the run again, and an answer this actor could not map says it is ours rather than yours and asks you to open an issue. **And a value this actor could not read is now counted on that line at all**: it was named on its own uncharged row but was missing from the run page's summary entirely, so a run whose accounts were all unreadable said "Delivered 0 profiles of 1 asked for across 1 account." and nothing else. It now names the count and tells you which field to put accounts into and what one looks like. The monthly collection allowance is said once rather than in two places, a run that did deliver profiles is unchanged and says nothing extra, and nothing about what is collected or charged changed.

- **What a run costs, and how often the list is worth re-reading, are now on the first screen.** The price was three screens down: **$0.50 per 1,000 profiles** on Gold and above, $2.00 per 1,000 on the Apify free plan, with no start fee and no per-account fee. So was the honest cadence — Instagram rebuilds the suggestion list as the account’s audience changes rather than hour to hour, so weekly or monthly is the useful re-run, `rank` makes each move visible when you diff it, and running it daily would mostly hand you the same list back and charge you for it. Both now sit in the opening block beside the actor id and the input. No price, no input field, no output column and no charged event changed.

### 1.0.5 — 2026-09-13

- **If you send your accounts under a different field name, this actor now reads them instead of telling you it found nothing.** `username`, `handle`, `handles`, `account`, `accounts`, `profile`, `profiles`, `profileUrl`, `profileUrls`, `url`, `urls`, `startUrl` and `startUrls` are all read as "Instagram accounts", as a single value or as a list, and each takes the same path a value in the declared field already took — a handle, an `@handle` or a profile link all work, and a Start-URLs entry written as `{"url": "…"}` is opened out to the link inside it. The same account sent in both fields is still one unit. The run gets one uncharged note row saying which field the accounts arrived in and which field to use next time, your run log says the same, and if a value cannot be read the row now names the field you actually set as well as the one this actor reads. `usernames` is still the declared field and nothing about it changed. No price, no charged event, no input field and no output column changes.

### 1.0.4 — 2026-09-13

- **The page now shows you a row before you spend anything, and its first line is the listing's own name.** A new **What a row looks like** section carries one real delivered row from a live run on `nasa` — every field, Instagram's own ranking included — and the heading at the top of the page is now the store title instead of a different name for the same product. No price, no input, no output column and no charged event changed.

- **Input schema: the description now opens with the call that works, what one suggested profile costs, the never-charged list and the cap — the screen an AI agent reads; `usernames` leads with the value shape and says an account with nothing to give is never charged.** Nothing else moved: no price, no charged event, no input field, no output column changed.

- **A read that will never work is no longer reported as one that might.** Two different answers used to arrive as `vendor_unavailable`, the row that says "this is temporary — please re-run": an account Instagram refuses to answer for at all, and an answer that arrives in a shape this actor cannot read yet. Neither changes on a re-run, so that row was selling you a second run for exactly the same answer. Each now has its own uncharged row — `source_refused` and `unsupported_shape` — saying what is actually true, what to check, and that a re-run will not change it. And an answer this actor cannot read is no longer reported as "Instagram has no such account" or "Instagram lists nothing similar" — it was never proof of either. A genuine outage still ships as `vendor_unavailable`, still asks for a re-run, and still carries no result fee. No price, no input and no delivered column changes.

- **A run may now wait longer for a slow source before it gives up.** How long a run can keep waiting is sized against what the accounts it is still owed are worth, and this build lets that sizing draw on half of the run's own margin instead of a quarter — so a page that is answering slowly gets about twice as long to come back, and a delivery cut short on a slow page is rarer. Everything that bounds the waiting is unchanged: your run-time limit, your result limit and your cost cap still end it on the spot, no run ever waits less than it did before, and a small ask waits exactly as long as it always has. No input, no output column, no charged event and no price changes.

### 1.0.3 — 2026-09-12

- **The time a run waits out a quiet source is now sized to what you asked for, instead of being the same five and a half seconds for every run.** A account that hit a quiet stretch was retried twice — a short wait, then a longer one — and then reported as unreadable, whether you had asked for three accounts on a two-minute run or five hundred on an hour-long one. A big ask on a long run now keeps waiting and asking again, each wait longer than the last, for as long as the accounts it is still owed are worth the run time it costs, and that extra patience is a pool the whole run shares so one difficult account cannot use it all. A small ask waits exactly as long as it did before, so nothing gets slower or dearer; no run ever waits less than it used to; and no run waits past your own run-time limit, your result limit or your cost cap, all of which still end the waiting on the spot. An account whose suggestions still cannot be read carries no result fee and the row still says a re-run is the fix.

All notable changes to this actor. Dates are UTC.

### 1.0.2 — 2026-09-12

- **A link in your rows can never carry a network address, whatever form it arrives in.** Every link
  this actor delivers already went through our own URL hygiene before reaching your dataset, and that
  pass had a gap: where an upstream body writes its links with HTML-escaped separators (`&amp;` in
  place of `&`), the address parameter was not recognised by name and could survive into a row. It is
  now removed however the link is written — escaped, plain or legacy separators, upper or lower case,
  and inside a link that wraps another link. Nothing else in a link moves: the expiry, the signature
  and every routing parameter are delivered exactly as they were served, so the links keep working
  exactly as before. No column, no input, no price and no charge changes.
- **This actor has a new title on the store: Instagram Related Profiles Scraper — Similar Profiles Finder.** Same actor, same id, same URL, same input, same output, same price — only the words on the listing changed, so nothing you have saved, scheduled or wired into an integration needs touching. The title now carries the phrase buyers actually search for, which is the only reason it moved.
- **A run that has reached your maximum cost per run no longer looks up an account it cannot deliver.** Each account
  costs two reads, and the run used to open the next one before its first row could stop it. Now it checks your ceiling
  first and stops there. Nothing about your rows, your bill or your limits changes — the run just stops a moment
  earlier, and the row naming the accounts it did not reach no longer describes them as partly collected.
- **A limit typed above what this actor can do no longer refuses the run.** "Max profiles" and "Max run seconds" carried
  hard ceilings in the input form itself, which meant the platform rejected the whole run before it started — no rows, no
  run page, nothing to act on — and an automation or an AI agent guessing a round number got an error instead of your
  data. Both ceilings are now the actor's own: ask for 50,000 profiles and the run collects 5,000, ask for a day and it
  runs for an hour, ask for 5 seconds and it takes 30, and one uncharged row says what was asked and what was used. The
  ceilings themselves are unchanged, and so is every price.
- Nothing else moved: no output column, event or price changed.

### 1.0.0 — 2026-09-11

First public build.

- The accounts Instagram itself suggests as similar to any handle: `username`, `fullName`,
  `profileUrl`, `isVerified`, `isPrivate`, `socialContext`, `userId`, `profilePicUrl`, plus
  `similarTo` and `rank` so a suggestion can always be traced back to the account it came from
  and to its place in Instagram's own ordering.
- Input takes account names, `@handles` or profile links, one per line. A pasted block opens
  out into one account per entry. A hashtag, a post link or a reel link is refused on an
  uncharged row that names the actor which does take it.
- One charged event, `similar-profile`, on delivered rows only. No start fee, no per-account
  fee, no search fee. The result limit is exact and is split evenly across the accounts asked
  about.
- Every profile that could not be delivered leaves an uncharged row naming its own cause:
  `account_not_found`, `private_account`, `no_suggestions`, `stopped_at_limit`,
  `vendor_unavailable` or `vendor_budget`. The run still finishes successfully.
- `maxTotalChargeUsd` is a hard ceiling: the run stops at it, ships one uncharged row per
  account naming what it cut, and buys nothing further.
- A time limit ends the collecting, never the delivering — rows already in hand are written out.
- Pressing Start with nothing set returns built-in sample rows, so the output shape is visible
  before anything is collected and before anything is charged.
