# Changelog of Instagram Reels Keyword Search Scraper — Reels Search to Text (`steadyfetch/instagram-keyword-reels-scraper`) Actor

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

## Changelog

### 1.0.49 — 2026-10-12

- **One long reel no longer makes a transcripts run stop early.** A run keeps enough time back for its next reel's transcript, sized from how long reels have taken so far. Until now that was sized from the slowest reel of the run whatever the next reel's length, so one long reel made the run stop taking short reels with up to a minute and a half still on its clock. The time kept back is now sized to each reel's own length at the pace this run has measured, and never more than before, so more of a big ask fits the same run time. A reel that does not say how long it is is sized exactly as before.
- **When a run stops because the next reel is longer than the time it has left, the status line now says so,** and the run time it names fits that reel too. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.48 — 2026-10-11

- **Clearer wording when a run stops at its limit.** Rows for the searches a run could not finish now carry the status "limit_reached" and say "This run reached its limit", with how to fetch the remaining reels in a new run, and the run page counts them as "past this run's limit" instead of printing an internal word. Nothing changes about the price, which rows are charged, the input fields or the other output columns.

### 1.0.47 — 2026-10-10

- **A reel your account received in the last 90 days is no longer charged again once your account memory passes 50,000 entries.** Until now that memory kept only its newest 50,000 entries and quietly dropped the oldest, so a busy account could be charged a second time for a reel it already had well inside the 90 days. The memory now keeps every entry for its full 90 days however many there are, and forgets one only once it is older than that.
- **Large account memories load and save much faster.** A run used to rewrite the whole memory every time it saved; it now saves only the newest part, and older entries are kept in separate records that are written once. Your existing memory is moved to the new layout the first time a run saves to it, and nothing in it is lost.
- A run loads as much of a very large memory as its own memory allows: about 300,000 entries at 256 MB, and more with more memory. If a run cannot hold all of it, its log says how many of the oldest entries it left out. Nothing changes about the price, which reels are charged, the input fields or the output columns.

### 1.0.46 — 2026-10-09

- **A busy speech service no longer costs you transcripts.** When the speech service behind this actor asked a run to slow down, the reel was given up after two short retries and delivered without its transcript, even with plenty of run time left. The run now waits as long as the service asks, holds its next transcript until then, and asks again; while it waits, the progress line says so. Only when the wait cannot fit in the time the run has left does a reel arrive without its transcript, with the words uncharged, on a row that says the speech service was at capacity for this run and where to get the words, and the status line says the same. The reels themselves, and every transcript delivered, are charged exactly as before.

### 1.0.45 — 2026-10-08

- **The monthly data allowance behind this actor was raised, so 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.
- **Reels reach your dataset a page at a time instead of one by one, so a large run spends its time reading reels, not writing them — more of a big ask fits the run.** A reel with a transcript still lands the moment its transcript is done. The rows, their order and what you are charged are unchanged, and nothing is charged until its rows are in your dataset.

### 1.0.44 — 2026-10-03

- **A short transcripts run now collects what its time allows, instead of buying a page and stopping.** When a transcripts run had less than 80 seconds — from "Max run seconds" or from the run timeout (the Timeout setting in the run's options) — it kept back a fixed 20 seconds for its closing report, so asking for more than one reel could read a page of search results and then stop before the first reel. The time kept back is now sized to the time the run actually has, and it counts the run timeout when that is shorter than "Max run seconds": a 58-second timeout with the default 30 reels now delivers reels with their transcripts instead of none. A speech call that stalls near the end now gives up in time for the run to write its summary, and that reel's transcript is not charged. Runs of 80 seconds or more behave exactly as before.
- **The note about short windows now names the clock that limits the run.** It now also appears when the run timeout, rather than "Max run seconds", is what makes a transcripts run short, and it names the run timeout as the setting to raise. Its sentence about whether the run will read anything now counts the time the run has already used to start. The note about a "Max run seconds" below 30 or above 3,600 no longer says the run went on at that number when the run timeout gave it less. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.43 — 2026-10-03

- **The README links a real sample dataset:** twenty reels for "pasta recipes" from one verified run with transcripts on, unedited, with the run's own summary row last. Twelve reels carry their spoken words; the other eight had no speech and say so on their row, with no transcript charge. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.42 — 2026-10-03

- **A search whose next page comes back empty is no longer cut short with a "temporary, please re-run" row.** When a later page of Instagram's search results came back holding no reels, the run used to stop that search at once and tell you to re-run for the rest. It now asks for that page once more, ranked afresh: if reels come back, the run simply keeps collecting; if it is empty again, or Instagram's search says the list has ended, the row says the search had nothing more to give this run and does not send you to re-run it. Reels already delivered stay delivered and charged as before, and the rest carry no result fee. If the run's time limit or its own data budget is what stops that second look, the row says so and names that limit.
- **The run summary row now says what happened to the transcripts.** A new `transcriptLeg` field on the summary row (and in the run's OUTPUT) says whether transcripts were requested, how many were delivered, and for every other reel why it has no transcript — not requested, a reel you already had, no speech, the run's time limit, and so on. The run page now says "without a transcript" for those reels instead of "without speech or audio", which was not true of all of them. Nothing changes about the price, which rows are charged, the input fields or the existing output columns.
- **A run whose maximum cost per run was too small for even one reel no longer says that maximum was reached.** When your maximum cost per run could not cover a single reel (or a single reel with its transcript, with transcripts on), the run stopped before anything was charged, yet the run page, the summary row and the skipped rows all said the run had reached your maximum. They now say the run stopped before any charge because the maximum leaves no room for one reel (or one reel with its transcript), and to raise it to collect more. A run that did charge reels before its maximum ran out reads exactly as before.
- **A run that stops because the rest of a small ask is not worth reading another page of search results now says this limit is the actor's own.** It used to say "your maximum cost per run was reached", even with your maximum nowhere near spent. The skipped row now says it is a limit of this actor's own and not your maximum cost per run, the run page and the summary row name it as this actor's own limit for a small ask, and all three say that asking for more reels in one run lets it read further. The reels it did not reach are still uncharged. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.41 — 2026-09-30

- **The README no longer links out to Instagram.** The sentence about Instagram's keyword search serving a ranked slice now names that page instead of linking to it; nothing else on this page changed. Apify Store copy carries no outside links.

### 1.0.40 — 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.40 per 1,000 reels — and names what the same run costs on paid plans: $1.40 on Bronze, $0.90 on Silver and $0.60 from Gold. Runs on paid plans read exactly as before. A run stopped at the free plan's daily limit whose token could not update the repeat memory now fits its whole summary on the run page instead of being cut off at the end. Nothing changes about the price, which rows are charged, the input fields or the output columns.

### 1.0.39 — 2026-09-26

- **A transcript this run's own spending limit stopped now says so plainly.** A reel whose transcript was not attempted because this run reached its own budget for this run on reels with nothing chargeable in their audio now says exactly that. The run also now notes its own start in its internal record, so a run cut off before it finishes (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.

All notable changes to this actor are documented here. Each entry matches one build on the Builds tab.

### 1.0.38 — 2026-09-26

- **A wide search run 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 reels you ask for, so a long list of phrases is searched in one run. When a run does stop at it, the uncharged rows and the run page now say that a new run on the same searches continues, skipping reels you already have, instead of saying the stop lasts until the start of next month. Nothing changes about the price, which reels are charged, the input fields or the output columns.

### 1.0.37 — 2026-09-24

- **A short run with transcripts on now uses its whole clock.** Until this build a run asking for two reels or more with "Include transcripts" on stopped taking new reels once 90 seconds were left, however quickly its reels were actually being transcribed — so a run with a 3-minute time limit stopped at about its halfway mark, and a run of 90 seconds or less read nothing. The run now keeps back what its own reels have actually been taking (with a safe minimum, more for a long reel, and never more than before), so it keeps collecting while another reel and its transcript still fit; a reel longer than the 180-second transcript ceiling, which is never transcribed, no longer counts against the clock. When the time left truly cannot fit another reel, the rows it could not reach and the run's status line now name the run time that would have fit the whole ask, for example "set the run timeout and "Max run seconds" to at least 3 minutes (180 seconds)". Reels that were not reached are still uncharged, and a transcript the clock can no longer finish is not attempted, is not charged and says so on its row. The note a short transcripts run gets up front now names the time this run actually holds back. A run with plenty of time behaves exactly as before, and no price, charged event, input field or output column changed.
- **A search cut short part-way down its last page now names the limit that cut it.** If the run's time limit or your maximum cost per run stopped a search part-way through a page that was also its last, the row for the reels left could read as the search having run out. It now says the run stopped at that limit, and those reels are counted as skipped at it, uncharged as before.

### 1.0.36 — 2026-09-24

- **On the Apify free plan, this actor now reads at most 60 pages of Instagram search results per account in any 24 hours, and all accounts on the free plan share one daily allowance on this actor.** Past either, the run keeps every reel it already delivered, stops reading, and ships one uncharged row naming the allowance and the time it resets (UTC); the run page says the same in one sentence and the run still succeeds. Nothing past the allowance is charged. Transcripts of reels already collected are unaffected. Paid Apify plans carry no daily allowance and are not affected at all: no price, input field, output column or charged event changed.

### 1.0.35 — 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.

### 1.0.34 — 2026-09-24

- **A short run clock can now produce a transcript.** With transcripts on and about a minute on the clock, the step that pulls the audio out of a reel was given only a second and failed, so the reel was delivered with no transcript. It is now given a share of the time actually left, which is several times what a typical reel needs. Runs with two minutes or more to spare are unchanged.
- **Runs that deliver many reels finish sooner.** Your account's record of delivered reels is now saved once per search page instead of once per reel; which reels are skipped next time is unchanged.
- The note shown for a very short run clock with transcripts on now says the window may not leave room to transcribe every reel, rather than that it rarely does.
- **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.33 — 2026-09-23

- **This actor's own record of the search pages it has read can no longer keep a run open past its time limit.** Each update of that record used to wait on its own timer; it now also stops when the run's time is up. And an update that could not first read the stored record no longer writes over it, so the record never goes backwards. This is our own bookkeeping: nothing about what is collected, delivered or charged changed.

### 1.0.32 — 2026-09-23

- **"Keywords" is no longer marked as a required field.** It never had to be filled in — an untouched Start already ran the built-in sample — and some AI-agent tools read "required" literally and refused to call the actor without it. Leaving it out, or sending it empty, still runs the sample exactly as before; a run with your phrases is unchanged.
- **The top of this page now says how to come back for fresh reels:** how often Instagram's ranking changes, how to put the same input on a schedule, and that reels already delivered to your account are skipped and not charged again. Nothing about what is collected, delivered or charged changed, and no price changed.

### 1.0.31 — 2026-09-23

- **A transcript call that hangs no longer holds your whole run for minutes.** With **Include transcripts** on, this actor transcribes one reel at a time, and a speech call that never answered used to hold the run for three minutes — and was then tried twice more, so one stuck reel could cost a run about nine minutes of doing nothing. Each call now gets a limit sized to that reel's own length — at least 20 seconds, about four seconds for every second of audio, never more than three minutes and never more than your run has left — is tried once more on a fresh call, and then the reel is delivered with its transcript left empty, a row saying the transcript did not complete and asking you to re-run, and no transcript charge. Nothing else about what is delivered or charged changed.
- **A run that is stopped part-way is now counted in full in this actor's own record of the data it reads.** That record used to be written only when a run finished, so a run you aborted or that reached its time limit left out every search page it had already read. It is now kept up to date page by page. This is our own bookkeeping: nothing about what is delivered, which rows are charged or the price changed.
- **The run's default settings are now part of the actor itself, and this page says how to get a faster run.** The defaults are unchanged — 512 MB of memory, a one-hour time limit, the latest build — and the Price section now says that with transcripts on a run gets faster with more memory, at the same price per reel.
- **Two older entries on this page no longer quote a dollar figure for our own monthly allowance.** They now say only that it was raised, on the same dates; nothing you pay was ever tied to it.

### 1.0.30 — 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.29 — 2026-09-22

- **A run no longer goes quiet while it works.** Reading search pages and downloading, extracting and transcribing reels used to happen without a single line in the log — a run could sit silent for over a minute, which reads exactly like a run that has hung. A run now opens with what it is about to do and promises a line at least every 30 seconds, and keeps that promise on the run page and in the log: which step is in flight ("search 1: reading results page 3", "reel 4: downloading the video", "reel 4: transcribing 1 min of audio", "pausing 14 s before asking again") and how long it has been on it, how many reels are delivered so far, the time left on your run's limit, and the sentence "Nothing has stopped; the run continues until it finishes or your time limit ends it." The progress lines name steps and counts only — never your keywords, a handle or a caption — and they push no row and charge nothing. No price, charged event, input field or output column changed.

### 1.0.28 — 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. A transcript that fails no longer passes on the speech service's own error message and links either; the row says so in plain words.

### 1.0.27 — 2026-09-22

- **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.26 — 2026-09-22

- **When Instagram's search cannot be reached at all, this actor now says the read did not come through and asks you to run it again, instead of telling you the phrase cannot be searched.** A search that failed because the source itself was unreachable was reported as a phrase Instagram "refuses to search at all — the refusal is the same every time and running it again cannot change it": a permanent verdict about your words, written on a run where the only thing wrong was a passing outage upstream. It hit during one such outage on 2026-09-22, on phrases that had been served fifteen minutes earlier. Those rows now say what is true — the read did not come through, this is temporary, nothing was charged for it, please re-run — and the run itself now waits and tries a couple more times before giving the search up at all, which is often enough to ride the outage out. Only the answers that really are about what you sent — a phrase the source rejects outright, or something it cannot find — still read as permanent and still stop the search at once. Nothing about what is collected or charged changed, and no input field, output column, charged event or price changed.

### 1.0.25 — 2026-09-21

- **A re-run now walks past the reels your account already has to reach the new ones behind them, instead of giving up two pages in.** Instagram ranks a keyword search afresh on every read, and on a phrase you have collected before the top of that ranking is largely reels you already hold. This actor skips those — no row, no charge — and it used to count a page of them as a page that "added nothing", so two such pages in a row closed the search and the rest of your ask came back as an uncharged row. On a real schedule that was costing about one reel in every eleven asked for. A page holding reels *your account* already has is now treated as ground your ask sits behind and is paid past, for a bounded number of pages, out of this actor's own collection allowance rather than your bill; a page that merely re-serves reels the same run has already met is still a repeat and still closes the search just as fast. Nothing about what is charged changed, and no input field, output column, charged event or price changed.
- **When that walk still runs out, the row says how many pages of your own reels it paid past.** The uncharged row for a search this actor's backstop closed used to name the bound as two pages — the number the backstop stops on — which stopped being the whole story the moment the walk started paying its way past pages of reels you already have first. It now names both: how many pages of your own reels it walked through, and how many pages after those added nothing. It is still stated as this actor's own limit and never as Instagram's answer about your phrase.
- **The run page now says how many reels came back from your account's memory without a result fee.** With **Include reels you already have** on, those rows were delivered and not charged — and the run page, the one surface a scheduled run leaves you, said nothing about them at all. It now names them, and that sentence is among the last to give way when the platform's 500-character cut bites. The receipt row at the end of the run also splits the two halves outright: how many reels were new and charged, and how many came back for nothing.
- **A repeat row no longer claims your transcript was already bought.** With **Include transcripts** on, a reel your account already had came back saying it had been handed back "without transcribing it again" — a claim about an earlier run this actor cannot actually check, because what it remembers is the reel, not whether its words were ever collected. The row now says exactly that, and still says plainly that nothing was charged for it.
- **The store page and the input fields say what a second run really costs, with the numbers measured.** "How often this data changes" carried an unmeasured "mostly new reels" and a promise that a skipped reel always leaves the number you asked for intact. Both are now the measured shape — about a third of what each read met was new to a returning account on a three-minute schedule — plus a new **What a second run costs** section, and the **Include reels you already have** field names this actor's own bound instead of promising a depth it does not have.

### 1.0.24 — 2026-09-21

- **A run with transcripts on now attempts a transcript for every reel it delivers; before this build it stopped transcribing after about seventy, whatever it had charged.** This actor carries a small per-run allowance for speech work that comes back with nothing to sell — reels whose audio is music only, or silent, or has no sound track at all — so one run cannot spend its way through a long list of them. That allowance was meant to grow as the run charged, and it never did: it stayed at its opening figure for the whole run, so a run asking for more than about seventy reels with transcripts on delivered the rest of them with an empty transcript and a row saying the allowance was spent — on a run where every transcript before it had been produced and charged for. The allowance now grows with what the run has actually charged, so a run that is paying for its transcripts keeps transcribing to the end of your ask; a run whose reels genuinely have nothing to transcribe still stops at the same opening figure, exactly as before, and is charged for none of it. The row you get when it does stop now says what a later run really does with those reels — this actor remembers the reels it has delivered to your account, so a later run will not transcribe them again — instead of asking you to re-run for them. Nothing about what is charged changed, and no input field, output column, charged event or price changed.

### 1.0.23 — 2026-09-21

- **A run that asks for a single reel with transcripts on no longer refuses itself inside a short time window.** With **Include transcripts** on, this actor holds part of "Max run seconds" back so the last reel never loses its transcript to the clock — and it used to hold back the same 90 seconds whether you asked for one reel or two thousand. A run that could only ever transcribe one reel was therefore stopped before it read anything from Instagram on any window under about two minutes: no reels, no transcripts, nothing charged, and a row saying the run clock had run out. The hold-back is now sized to what the run can still transcribe — 45 seconds for a one-reel ask, the same 90 seconds as before for anything larger — so a small ask inside a short window collects its reels instead of refusing itself. It is never longer than it was, so no run holds back more of your window than it did before. The uncharged note about short transcript windows is still there, still names the two ways out, and now says which of the two is actually happening on your run. Nothing about what is charged changed, and no input field, output column, charged event or price changed.

### 1.0.22 — 2026-09-20

- **A run that set field names this actor does not have now names three of them on the run page and counts the rest, instead of listing every one of them and having the end of the line thrown away.** The run page is cut at 500 characters by the platform, and it throws away the END — where the sentence about what you were charged sits. That sentence was safe as long as the line was built from our words. It was not: the sentence naming the fields a run had set echoed every one of them back, so its length was set by whatever was sent rather than by us. A run from a template or an agent that sends a whole form of unrecognised names — twelve of them, or forty — pushed the line to two and a half times the cut, and what the platform then cut off the end was the count of what was not delivered and the statement that none of it was charged. The run page now names the first three, cuts any single name that is longer than forty characters, and says how many more there were; where even that will not fit beside the money on a heavy run, it gives way to one short sentence that still says the fields are not this actor's and names the one it reads. **The uncharged row in your dataset is unchanged and still names every field you set, in full** — nothing truncates a row, and that is where the whole list lives. Nothing about what is collected or charged changed, and no input field, output column, charged event or price changed.

### 1.0.21 — 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.20 — 2026-09-19

- **The whole "Maximum cost per run" you set is now spent on reels; before this build the run held back about a twelfth of it.** Your cap pays for reels 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 reel. So a cap worth ten reels 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.19 — 2026-09-19

- **When this actor stops a search because the last pages only repeated reels you already have, the row now tells you what running the same phrase again actually does.** It used to give one reason to run it again — for reels posted since — which is how a feed that pages forward works: read the next slice, and only new arrivals lie beyond it. Instagram's reel search does not page forward. It ranks the phrase afresh on every read, so two reads minutes apart return an overlapping but different slice of the same results, and a later run is a new ranking rather than a continuation of this one: it can surface reels this run's reads never showed, as well as anything posted since. A buyer told the paging story reads that row as "there is nothing here for me until somebody posts", and stops asking on exactly the phrase where asking again is what gets them more. The row now names the mechanic and says what a later run may do, without promising it. Nothing about what is collected or charged changed, and no input field, output column, charged event or price changed.

### 1.0.18 — 2026-09-19

- **A run that Apify moves to another server part-way through now finishes the search it was in the middle of, and counts the reels it had already delivered.** Apify sometimes moves a long run to a different server and the new server picks it up. The reels already in your dataset were never at risk — each one was collected once and carried one result fee, and that has always been true. What was wrong was everything the run then said about itself. The restarted half counted from zero, so a search whose reels were already in your dataset got a row of its own saying they had not been delivered, the run summary read 0 delivered beside a result-fee count that was not zero, and the run's own record of how much it had read from Instagram covered only the second half. Worse, the restarted half had to work its way back through the reels it had already collected, and the check that stops this actor paying to re-read reels you already have counted those pages as "nothing new here" and closed the search early — a page short of where the run had really got to. A moved run now reads its own delivered reels back out of your dataset, carries on from the place it had reached, asks only for what is still owed, and reports the whole run's numbers. A run that is never moved behaves exactly as it did, and nothing about what is collected or charged changed.

### 1.0.17 — 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.16 — 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: "the reels you already had were skipped, not charged", "none of the undelivered rows was charged" and the note about a repeat check that could not run were being thrown away to make room for a settings note and a request to open a support issue. Measured across 1,440 shapes a real run can end in, 735 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 transcript count (each row already says why it carries no speech), 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.

- **And the line naming a field this actor does not have now reads as one sentence.** It used to be joined with a semicolon, which reads as two — cosmetic on the page, but the run page's own tooling splits a summary on semicolons, so the second half could be read as a separate clause. Same words, a full stop instead. No input field, output column, charged event or price changed.

### 1.0.15 — 2026-09-16

- **Transcripts with a short run window now say so before the run starts, instead of after it has
  ended with nothing.** A transcripts run holds 90 seconds back so the last reel never loses its
  transcript to the clock, which means a "Max run seconds" of 90 or less stops the run before it
  reads anything from Instagram at all. That was true and invisible: the form accepted the pair, and
  the only thing that said so was a row written after the run was over. Setting both now puts one
  uncharged note row at the top of the dataset naming the setting, and both settings say the same
  thing on the form — give a transcripts run over about 2 minutes, or switch transcripts off to
  collect reels alone. Nothing about what is collected or charged changes.
- **A run stopped by a time limit always tells you which setting raises it.** On one path — a read
  cut short by the run's own clock a moment before the limit itself was reached — the receipt said
  only "stopped by deadline" and the run page said nothing about the stop at all. Both now carry the
  same sentence the ordinary time-limit stop has always carried, naming "Max run seconds" as the
  lever. A run that finished cleanly or filled your result limit reads exactly as it did before.

### 1.0.14 — 2026-09-16

- **A search that comes back holding no reels is now asked a second time before the run gives up
  on it.** Instagram's reel search always answers — even a phrase nobody has ever posted comes back
  with a full page — so a first page carrying no reels at all has never been a verdict about your
  phrase. Until now the run stopped there and the row asked you to run it again, which is a run you
  pay platform time for. The run now asks the same phrase once more, ranking the search itself the
  second time so the two reads are genuinely independent, and if that answer carries reels they are
  simply delivered: most runs that used to end empty will now end with your reels and you will never
  see a row about any of it.
- **And when both reads hold nothing, the row says so instead of sending you back for the same
  answer.** It names the phrase, says the run asked twice, and tells you that starting it again in
  the next minute buys the identical answer — so the lever is a different or broader phrase, or the
  same one later. Nothing about it is charged. A single empty answer that was never confirmed is
  unchanged: it is still reported as a read that did not come through, and a re-run is still the fix.
- **A run that is nearly out of time now still buys the short retry that fits.** When the feed
  answered with something worth retrying, the retry was priced at a full-length read plus its
  cooldown and refused whenever the whole thing would not fit — so a run with twenty seconds left
  bought nothing at all, rather than the cooldown and a shorter read it could afford. The retry is
  now sized to the time actually left.
- **A read cut short by your own "Max run seconds" is now reported as the run clock, not as
  Instagram being unavailable.** It used to land on the temporary-problem row and ask for a re-run
  with the same limit, which would have been cut in the same place; it now lands on the row that
  names the setting to raise. No price, input field, output column or charged event changed, and
  nothing a run cuts short is ever charged.

### 1.0.13 — 2026-09-15

- **"Max run seconds" now really stops the run.** It always decided when this actor would stop
  *starting* work, and it said so honestly in the summary — but nothing stopped a single search
  page, video download or speech call that was already in flight, and each of those carried its
  own separate timer of up to 25, 45 and 180 seconds. A search that kept answering nothing could
  retry three times with cooldowns between and run for 80 seconds on a run you had limited to 30,
  and one long speech call could outlast a short run several times over. Every one of them is now
  given the smaller of its own limit and the time your run actually has left, and the run ends
  inside the number you typed. A run with time to spare is unchanged: every request still gets its
  full allowance, and nothing that used to be delivered stops being delivered. The other half is
  migrations — when Apify moves a run to a new machine mid-flight, the run used to start your whole
  time limit again from zero; it now continues with what is left of the one you asked for. No
  price, input field, output column or charged event changed, and nothing that a run cuts short is
  ever charged.

### 1.0.12 — 2026-09-14

- **A video link that does not come from Instagram's own servers is now refused before it is
  fetched, instead of being downloaded, transcribed and charged.** The link this actor downloads for
  a transcript is written by the search feed it buys from, not by you. Nothing checked where it
  pointed, so a wrong or tampered answer would have been downloaded from whatever host it named,
  sent to the speech service and billed to you as a transcript. Every rendition is now checked
  against Instagram's own media servers first, and a link that is not one is never opened: the reel
  itself is still delivered, the transcript is uncharged, and the row says the link was refused and
  names the host — it does not say the reel has no video, because those are two different things. A
  reel is only refused when EVERY rendition it offers fails that check, so nothing that used to
  produce a transcript stops producing one. No price, input field, output column or charged event
  changed.

### 1.0.11 — 2026-09-14

- **A run that brings back no reels 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 reels of 1 asked for across 1 search. Not delivered: 1 source unavailable" — 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 temporary read says to start the run again and that it says nothing about your phrases, a phrase Instagram is publishing no reels for says a re-run answers the same and suggests a broader one, a phrase Instagram refused outright says to try it as plain words without hashes or punctuation, and an answer this actor could not map says it is ours rather than yours and asks you to open an issue. **And a phrase 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 phrases were all unreadable said "Delivered 0 reels of 1 asked for across 1 search." and nothing else. It now names the count and tells you which field to put phrases into. A field name this actor does not have keeps the sentence it already had rather than being explained twice, the monthly collection allowance is said once rather than in two places, a run that did deliver reels is unchanged and says nothing extra, and nothing about what is collected or charged changed.

### 1.0.10 — 2026-09-14

- **What a run costs, and whether tomorrow is worth running, are now on the first screen.** You had to scroll past the column table and the sample row to learn that a reel is **$0.60 per 1,000** on Gold and above ($2.40 per 1,000 on the Apify free plan), that a transcript is a flat $0.006 and only when one was actually produced, and that Instagram re-ranks a keyword continuously — so the same phrase tomorrow is mostly reels you have not seen, and the ones you already have are skipped rather than charged again. All of it now sits 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.9 — 2026-09-14

- **A run that can read your repeat memory but not write to it now says so, instead of letting your next run pay for everything twice.** The previous entry covered a token that cannot OPEN that memory. This is the other half: an API token can be allowed to read key-value stores and not to write them — or to write them and not to create one you do not have yet — and such a run opens your memory, recognises every reel you already had correctly, and then remembers nothing it delivered. The run looks perfect and your NEXT run is charged for the whole delivery all over again — here the reel **and** the transcript you already paid for. The run page now names it the moment the first write is refused, an uncharged row at the top of the dataset carries the cause and the fix in full, the receipt carries `repeatWrite: "denied_scope"`, and the run log keeps Apify's own message and adds the permission to grant: key-value store **Write** (and **Create**), or Actor runs set to **Full access**, under Settings → API & Integrations. A write that fails for an ordinary reason is still just retried bookkeeping and says nothing. Both run-page sentences are also shorter and now read the same on every actor in the portfolio, with the whole fix on the row. No price, no input field, no delivered column and no charged event changed.

- **The run page no longer says "50 searchs".** A run across more than one search phrase printed a plural that does not exist in English, while the receipt on the same run said "50 searches". One spelling now, on both. Nothing about what is collected or charged changed.

- **A run that cannot open your account's repeat memory now says so instead of quietly charging you twice.** This actor promises you never pay for the same reel twice, and never pay twice for a transcript you already bought: it remembers what it delivered to your account in a key-value store there, and skips those next time. A run started from the API with a **scoped token** in restricted-access mode cannot open that store unless the token is allowed to — so the check never ran, every reel you already had was collected and charged again (and re-transcribed), and nothing on the run page, the rows or the receipt said a word about it. The run page now names the cause and the fix, an uncharged row at the top of the dataset says the same thing for anything reading rows rather than the page, the receipt carries `repeatCheck: "unavailable_scope"`, and the run log keeps Apify's own message and adds the permission to grant: key-value store **Read, Write and Create**, or Actor runs set to **Full access**, under Settings → API & Integrations. Every other reason the memory can be unreadable reads exactly as it did before. No price, no input field, no delivered column and no charged event changed.

### 1.0.8 — 2026-09-13

- **A search phrase sent under a slightly different field name is now collected instead of ignored.** A run that put its phrases in `keyword`, `query`, `queries`, `searchQuery`, `searchQueries`, `search`, `term` or `terms` used to collect nothing: Apify passes a field this actor does not declare straight through, so the run looked like a Start with no phrase set and came back with one uncharged row naming a field you had never filled in. Those names are now read as the field they plainly mean, a phrase sent under both names is searched once and charged once, and one uncharged row tells you which field to use next time so it stops appearing. A field name that matches nothing still gets an uncharged row, and that row now names the field you set as well as the field this actor reads. No price, no input field, no output column and no charged event changed.

### 1.0.7 — 2026-09-13

- **Your result limit now holds even when Apify moves the run to another server part-way through.** This actor already picks up exactly where it left off after such a move, and it works out how much of your limit is left from the reels it has already delivered — but it was counting only the reels that carried a fee. A reel your account already has comes back delivered and uncharged, and so does every row on a run that cannot be billed at all, so those were invisible to the count: the run believed more of your limit was unspent than really was, and could hand you more reels than you asked for. It now counts every one already delivered to you, whether or not it carried a fee. Nothing about what you are charged moves — a repeat is still delivered without a result fee, and only delivered reels and produced transcripts are charged.

### 1.0.6 — 2026-09-13

- **The page now shows you a row before you spend anything, and it is called what the store calls it.** A new **What a row looks like** section carries one real delivered row from a live run of the phrase `latte art` — every field, including the transcript fields and the charge record — and the first line of the page is now the listing's own 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 reel costs (and what a transcript adds), the never-charged list and the cap — the screen an AI agent reads; `keywords` leads with the value shape and says a phrase that matches nothing is never charged.** Nothing else moved: no price, no charged event, no input field, no output column changed.

- **An answer that can never work no longer asks you to run it again.** Two things used to be reported the same way as a temporary outage — "this is temporary, please re-run": a phrase Instagram refuses to search at all, and an answer that came back in a shape this actor cannot read yet. Neither changes on a re-run, so that row was asking you to spend a second run for the identical answer. Each now has its own uncharged row that says what is actually true — `source_refused` for the phrase Instagram would not search, `unsupported_shape` for the answer that is on us — and neither is marked retryable. Real outages are untouched: a read that failed is still temporary, still says so, and a re-run is still the fix. Where a search had already delivered reels before it stopped, the row still opens with how many you were handed and charged for, and denies a fee only for the rest. Nothing about what you are charged 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 reels 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.5 — 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 fourteen seconds for every run.** Since the last build a search that hit a quiet stretch was waited out twice — a short wait, then a longer one — and then given up on, whether you had asked for three reels on a two-minute run or five hundred on an hour-long one. A big ask on a long run now keeps waiting and reading the same page again, each wait longer than the last, for as long as the reels it is still owed are worth the run time it costs. 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. Where the source comes back, the reels behind the pause are delivered and charged exactly as they always were. Where it does not, nothing changes: the reels in hand are yours, the rest carries no result fee, and the row still says a re-run is the fix.

- **An answer this run already paid for is never bought twice.** When the source replies in a shape this build cannot read, waiting and asking again cannot change one byte of it — the run did it anyway, up to twice per search. From this build only the refusals that cost nothing are waited out: a rate limit, a server error, a dropped connection. This matters more than it used to precisely because runs now wait longer, and it can only ever reduce what a run spends on your behalf. Nothing about what you are charged moves.

### 1.0.4 — 2026-09-12

- **A search that comes back holding nothing is no longer reported as a final answer about your phrase.**
  Instagram's keyword search always has something to show — even a phrase nobody has ever posted comes back
  with a full page of reels — so a search that returns no reels at all means the read did not come through,
  not that your phrase has none. The run used to call that a definitive answer and tell you there was nothing
  more to find, which is the one moment a re-run is exactly what would get you your reels. It now says what
  actually happened, marks the row as worth re-running, and still charges nothing for it. Reels already
  delivered from that search stay yours and stay charged exactly as their own rows say. No input field,
  output column, price or charged event changed.

### 1.0.3 — 2026-09-12

- **A search no longer ends because Instagram could not be reached for a moment.** When the source went
  quiet part-way through a phrase, the run used to stop collecting for it on the spot — about five seconds
  after the first sign of trouble — and report every reel it still owed as not delivered. It now waits and
  reads the same page again: a short wait, then a longer one, spent once per phrase rather than on every
  page, and only while the run still has the clock for it and none of your own limits have been reached.
  Where the source comes back, the reels behind the pause are delivered exactly as they always were. Where
  it does not, nothing changes at all: the reels already collected are yours and charged as marked, the
  rest carries no result fee, and the row still says a re-run is the fix. A search with nothing to show and
  a run that has reached a limit are answers, not pauses, and are never waited on.

### 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.
- **An uncharged row no longer blames Instagram for a limit of this actor's, and a search that stopped part-way
  no longer denies the reels it already charged you for.** Three different endings used to share one sentence —
  "Instagram's search returned no more reels for this phrase; that is a definitive answer" — even when what actually
  closed the search was this actor's own ceiling on how deep one phrase is read, or its own backstop on pages that
  only re-served reels you already have. Each ending now says which one it was, names the bound as this actor's own
  where it is ours, and points at what you can change: a re-run, a narrower phrase, or "Include reels you already
  have". And when the search stops answering after it has already delivered reels, the row now opens with how many
  were handed over and charged for, and asks for the re-run only on the rest, instead of saying there was no result
  fee for a run that had one. No input field, output column, price or charged event changed.
- **The run page now names this actor's own read limits in its own words, instead of listing them as
  "no data".** When a search stops because this actor reached its own ceiling on how deep one phrase is
  read, or its own backstop on pages that only re-serve reels you already have, the summary line on the
  run page now says so — "past this actor's read depth", "only repeats on later pages" — where it used to
  fold both into the same "no data" count as a search Instagram had genuinely run out of. The uncharged
  rows already said which of the three it was; the run-page count now agrees with them. No input field,
  output column, row status, price or charged event changed.
- **This actor has a new title on the store: Instagram Reels Search Scraper — Keyword Search, Transcripts.** 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.
- **The price table in this README now matches the actor's pricing record exactly.** One reel costs $0.0024 on the Apify
  free plan, $0.0014 on Bronze, $0.0009 on Silver and $0.0006 on Gold and above — from $0.60 per 1,000 reels. The README
  table and the store description had been quoting a higher draft ladder, $0.70 per 1,000, that was never filed as this
  actor's price (the 1.0.0 note below still carries that draft number). Nobody was ever charged it: the price itself did
  not move, only the sentences that quote it.
- The transcript price is unchanged — a flat $0.006 per transcript actually produced, the same on every Apify plan — and
  so is everything else: no input field, output column or charged event changed.
- **A limit typed above what this actor can do no longer refuses the run.** "Max reels" 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 20,000 reels and the run collects 2,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.
- **A run that has reached your maximum cost per run no longer fetches a page of results it cannot deliver.** The limit
  was already exact on what you are charged; now the run also stops reading as soon as your ceiling can no longer cover
  a single further reel, instead of collecting one more page first. Nothing about your rows, your bill or your limits
  changes — the run just stops a moment earlier and says so on the same uncharged row it always did.

### 1.0.0 — 2026-09-11

First public release.

- Instagram reels by search phrase: type the words, get the reels Instagram ranks top for them, with caption, hashtags, mentions, engagement, media links, owner and the permalink.
- **Transcripts bundled.** Switch on **Include transcripts** and every delivered reel also carries `transcript`, `transcriptLanguage` and timestamped `transcriptSegments`, taken from the reel's own audio.
- **The result limit is exact.** Set 30 and the run delivers 30, or the last row says why it could not. With several phrases the limit is split evenly between them, and a phrase that runs short leaves an uncharged row saying so rather than borrowing another phrase's share.
- Two charged events. `reel`, from $0.70 per 1,000 reels, platform usage included; `reel-transcript`, a flat $0.006 on every plan and only on a reel whose spoken words were actually produced. No start fee, and no second charge for "details".
- A reel whose audio could not be transcribed — no speech, no audio track, an expired media link, or longer than the 180-second ceiling — is delivered as a normal reel row with an explicit null transcript and a reason, and the transcript event is not charged.
- Honest uncharged rows: a search with nothing more to give, a search whose later pages only repeated reels already delivered, a read that did not go through, this actor's own monthly collection allowance, and any of the limits that can stop a run each say so in their own words, and none of them is billed.
- Repeat memory: reels already delivered to your account are skipped on a later run, not charged again, never re-transcribed, and their slot goes to the next new reel — so a daily schedule on the same phrases costs only what is new.
- Signed media links are delivered with the requesting network address stripped out, and with `videoUrlExpiresAt` so you know how long each link lasts.
- **`maxTotalChargeUsd` is a hard ceiling on delivery, not only on billing.** With transcripts on, a reel and its transcript are reserved together at take-off, so a run reaching your maximum stops collecting there and the last row names the reels it did not deliver — rather than continuing to hand reels over past the limit you set.
