# Changelog of Instagram User Search (`opspilot.cc/instagram-user-search`) Actor

- **URL**: https://apify.com/opspilot.cc/instagram-user-search/changelog.md
- **Full Actor documentation**: https://apify.com/opspilot.cc/instagram-user-search.md

## Changelog

### \[0.3] - 2026-10-12

- The run can no longer be killed by the key-value store. Under
  `LIMITED_PERMISSIONS` — how Apify's automated QA and every API-triggered run
  starts an Actor — opening the store is refused with HTTP 403
  (`KeyValueStoreCollectionClient.getOrCreate`, path `/v2/key-value-stores`).
  That call sat in a `||` fallback chain and was never inside a `try/catch` of
  ours, so the throw ended the run with exit code 91 and a reported FAILED run
  with zero items. Every store open now goes through a wrapper that returns a
  no-op store instead of throwing, so the free-run counter and the run SUMMARY
  degrade and the actual work proceeds.
- The gate store's name-to-id lookup no longer depends on the store still being
  on the first page. There is no GET-by-name endpoint, so the lookup pages
  through `/v2/key-value-stores`; it used a fixed `limit=50`, which silently
  stopped containing gate stores once the account passed 50 of them — and the
  account creates a new default store on every run, so that list grows on its
  own. The lookup now pages (100 per page, up to 20 pages).
- Medians on an even-sized sample returned the upper-middle element, not the
  median. `arr[Math.floor(arr.length / 2)]` yields the larger of the two middle
  values, which biases the number upward — the exact bias a median exists to
  remove. It now averages the two middle values.

### \[0.2] - 2026-10-09

#### Changed

- README: added three sections before Quick start - what you can use it for, who it fits, and who it does **not** fit. The last section now names the Actor's real limits (what it cannot reach, which field is unavailable, which reading of a metric is wrong), so a buyer can tell whether it is the wrong tool before paying.

### 0.1 (2026-10-04)

- Initial release. One dataset row per account Instagram returns for a keyword, carrying Instagram's own `searchPosition` for that keyword — the signal that shows who owns a keyword rather than who merely exists.
- Uses the v1 search leg (`fetch_search` with `select=users`): half the cost of the v2 leg and it includes the ranking position. The v2 flat shape is also understood by the normaliser so a leg switch needs no rewrite.
- Optional enrichment (`enrichTop`, default 20 per keyword, capped at 60 per run) adds followers, following, posts, bio and external link through the profile leg; unenriched rows keep `null` counts and are flagged via `enriched`.
- Run summary per keyword: result count, enriched count, verified/private counts, median followers of enriched rows, and the top 5 hits in Instagram's order.
- Free tier: 5 runs/day (counter persisted in a cross-run named KV store).
