- The whole "Maximum cost per run" you set is now spent on products. Before this build the run held back about a tenth of your cost cap before it started — a cushion for platform running costs which, on this actor's pricing, your cap does not pay for at all: your cap buys products, and the running costs are ours. So the cushion was simply cap you had asked to spend and could not get. On a run capped at $0.10 with products at $0.0015 the plan asked for 60 products where the cap paid for 66 — 6 products of your own cap, unspendable by construction. From this build the plan uses your cap in full, so a run asks for as many products as your cap can really pay for. Nothing you are charged changes, and nothing can be charged above the cap you typed: every charge is still checked against what is left of your cap at the moment it is posted, and a run that reaches your cap still stops cleanly, ships what it had already fetched, and tells you what is left. No price, input field or output column changes.
- The per-product price and a line on how often the data moves now sit in the opening list, three screens earlier than before. A buyer landing here had to read about 7,609 characters before the price appeared at all. It is now a bullet under the input line: both ends of the tier ladder, the one priced event, and the reminder that a row we could not deliver is never charged — with the full ladder, the event name and the honesty contract unchanged below. Beside it is the cadence line that was not on the first screen at all: what actually moves between one run and the next, so a buyer can tell whether this is a one-off or a schedule. No input field, output column, charged event or price changed; only where the page says them.
- The table of sibling Amazon actors now names the Best Sellers listing by its current title. That listing is called Amazon Best Sellers Scraper — Top 60 Ranks, Full Product Row: it returns the top 60 ranks Amazon puts in the page, and its old title said every rank. The link here still points at the same actor; only the words a reader sees changed. Nothing else moved: no input field, output column, charged event or price changed.
- The input form now opens with the call that works, what one product costs and what is never charged — the screen an AI agent reads. An AI agent shopping the store never sees this page: it sees the input form's own description, and that description used to open by telling a human to click Start. It now opens with a ready-to-send input, says which field is required and that every other one can be left out, gives the per-product price on the Apify free plan and on paid plans with the per-1,000 arithmetic, lists what is never charged, names the run option that caps the bill, and points a keyword, a Best Sellers link or a seller id at the right sibling actor. Products leads with the value shape and its example instead of the console instruction, which now comes last. Nothing else moved: no input field, output column, event or price changed, and the console form behaves exactly as before.
- A US product Amazon walled us out of now gets one more route before the run gives up. When amazon.com refused every way this actor knows how to ask for a product page, the run returned an uncharged row telling you to try again. It now takes one more look over a separate, US-pinned route first — the same second route the European stores have had since August — and if that route brings the real page back, you get the product row instead of a re-run. If that route is refused too, or brings back a page we cannot read, the row is exactly the uncharged one you would have had. Prices, events and columns are unchanged, and only delivered products are charged.
- An aborted or migrated run now leaves its receipt from the first moment of the run, instead of only after start-up finishes. The record that says how a run ended was only put in place once the run had finished starting up — reading your input, opening its stores, working out what a previous attempt had already delivered and charged. A run stopped inside that window ended with nothing written about it at all, which mattered most on a re-started run, where the thing not written about was the earlier attempt's work. It is now in place from the run's first moment. Nothing else moved: no input field, output column, event or price changed, and a run that reaches its work behaves exactly as before.
- This actor has a new title on the store: Amazon ASIN Scraper — Full Product Row per ASIN, Flat Fee. 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.
- Asking for a bigger limit than this actor can do no longer stops the run before it starts.
Max products and Max run seconds used to be range-checked by the platform itself, so a run asking for 50,000 products — or for 30 seconds — was refused outright: no run, no rows, no message, nothing on the run page to explain it. The ceilings are unchanged (up to 5,000 products, 60 to 21,600 seconds) but they are now ours to apply: the run starts, continues at the nearest value it can do, and adds one uncharged input_note row naming what you asked for and what bound. Anything you already send inside those ranges behaves exactly as before.
- Nothing else moved: no input field, output column, event or price changed.
- An AI agent can now pin this actor straight from the top of the store page. The one-click MCP link, the actor's id, the single input field it needs with a real example, and the run setting that caps what a run may spend now sit in the opening lines of the page instead of far down it. An agent that reads only the start of a listing could not see any of that before, so it could not work out how to call this actor without being told. Nothing about the actor itself changed — same id, same input, same rows.
- The page also names our other scrapers correctly again. A few links and mentions still used titles those actors no longer have. The links always pointed at the right actors; only the words were out of date.
- One maintenance detail you will not see: the private run-report this actor writes for our own support — numbers only, never anything you typed — now also records the price each charged item carried on that run, so a question about a bill can be answered from the run itself.
- Nothing else moved: no price, event, output column or charge changed, and only delivered products are charged.
- A maintenance build: nothing about your runs changes. The private run-report this actor writes for our own support — counts only, never anything you typed — gained room for four figures it does not fill in yet: how many targets a run was given, how long it waited on a blocked source, how many of those waits recovered, and a reason code for an item our own size limit refused. The build carries the shared contract so a later one can report them; on this actor every one of them is left blank, and nothing a run does or costs is different.
- Nothing else moved: no price, event, output column or charge changed, and only delivered products are charged.
- A run on a short time limit now gets a real second attempt on a blocked product. Patience is sized to the clock a run actually has instead of being refused whenever the full pause would not fit, so a short run — including the eight-minute sample and Apify's own five-minute health check — gets a retry where before it got none. The first pause is a third as long, so a block that lifts quickly is caught far sooner, and a block that answers the same way twice ends the waiting instead of paying for pauses that were never going to help.
- Nothing else moved: no price, event, output column or charge changed, and only delivered products are charged.
- A run that answered every product honestly no longer asks you whether something went wrong. When an id you sent has no product page, belongs to another country's catalogue, or turns out to be a subscription rather than a product, that is a real answer and nothing is charged for it — but the run page still ended with "Something off? Open an issue", which reads as a fault on your own correct input. The run page now asks for an issue only when something a re-run could fix went wrong: a page Amazon blocked, a page we could not read, a setting we could not accept, a run cut short by your cost cap or the clock, or a run that delivered nothing and could not say why. The counts themselves are unchanged and every one of them still appears on the line.
- The receipt row no longer tells you to re-run from a list it left empty. A run that stopped because your Max products cap filled after looking up everything you sent ended its summary row with "re-run with the ids in resumeCursor to continue", while
resumeCursor was empty because there was nothing left to continue with. That sentence now appears only when there really are ids waiting.
- Nothing else moved: no price, event, output column or charge changed, and only delivered products are charged.
- A block of links pasted into one row is now read as the list you meant, whatever separates them. "Products" takes one ASIN or product link per row. A whole block pasted into a single row was read as one very long address, and the product it found was whichever ASIN happened to sit last in it — the wrong product looked up and charged, and every other one dropped without a word. A pasted block is now split back into its individual links whether they are separated by spaces, line breaks, tabs, commas, semicolons, pipes or nothing at all, so a column copied straight out of a spreadsheet works. Each one is then read, deduplicated and charged on its own, exactly as if you had pasted them one per row.
- A link that carries another link inside it is still one link. An address holding a second address in its query or its path is left whole, not broken in two, and a single link pasted on its own is never rewritten.
- Text pasted around a link no longer breaks it. A number, a bullet or a note sitting beside a link is ignored and the link itself is used. A row holding no link at all is still answered as one row, not one row per word.
- Nothing else moved: no price, event, output column or charge changed, and only delivered results are charged.
- The run's own record now counts the products your limits left un-looked-up. When your Max products cap filled, your maximum cost per run was reached, or the run's clock ended the walk, the ids still ahead of it were simply absent from the report this run writes back to us: a run that was sent two ids and delivered one closed its books with one product named by nothing at all. Each of those products is now counted under the limit that stopped it, so a run that stops short of your list is visible to us without you having to report it.
- A run that stopped at your product cap now also records whether that cap really filled. It is one true-or-false fact about the run, never the number you typed, and it lets us see a run that claimed your cap stopped it while it had in fact delivered fewer products than you allowed.
- Nothing you can see changed. Your rows, your columns, your summary row and your bill are exactly as they were — only delivered products are charged, and a product that was not delivered is not charged.
- A product id this actor could not read now counts in the run's own "delivered N of M" line. If your list held five ids and one of them was neither an ASIN nor an Amazon product URL, the summary said "Delivered 4 of 4 products" beside a separate "1 input error" — the id you typed had quietly dropped out of the count of what you asked for. The line now reads "Delivered 4 of 5 products", so the number after "of" is always the number of products you sent. Nothing about your dataset or your bill changed: an id that could not be read is still answered with its own uncharged row, and only delivered products are charged.
- A run whose "Marketplace" could not be read now records every product that setting stopped, not just the setting. The rows you see are unchanged — each product still gets its own uncharged row saying it was not looked up and which setting stopped it — but our own record of the run counted that as one problem rather than as the eight products it cost, so a run of yours that delivered nothing could look smaller to us than it was.
- A delivered row with no price, or a price in another currency, is no longer double-counted against the run's own arithmetic. It was always a delivered, charged row and still is; only our bookkeeping changed.
- A run now pauses only when it can finish a whole second round of attempts afterwards and still have time to write its rows. When Amazon refuses every route, this actor waits a minute and a half to three minutes and asks again. The check that decided whether that pause was affordable set aside half a minute for the round of attempts that follows it, while a real round here takes between two and a half and just over four minutes, depending on how many routes the run is allowed to use. So on a short run — the automatic five-minute check, or a low Max run seconds — the run could take the full pause and then run out of clock part-way through the round it had just waited for. The pause is now measured against a real round on this actor's own connection ladder, so a first run that waits now always keeps room to finish and report: a short run either waits and finishes cleanly or answers straight away, and a run with the time to wait behaves exactly as it did.
- Nothing about your dataset or your bill changed: a pause is never charged, and only delivered products are charged.
- A sentence in the entry below called this actor's sample connection routes "free". A run always spends platform time you pay for, so nothing on this page is described that way: the sentence now says the no-input sample uses only the unpaid connection routes. Nothing about what this actor does, delivers or charges changed.
- A run started with no input at all now has room to wait out a block. Press Start on the untouched form and this actor reads one real product, charged like any run. Amazon sometimes turns every connection away for a few minutes at a time, and one full round of attempts could use up most of the sample's own three-minute limit — so the pause-and-try-again this actor gained in the last build could never happen on the most common first run of all: it reported "blocked, please re-run" while the block was still lifting. The sample's time limit is now eight minutes, sized to hold one full round of attempts, one pause, another full round, and enough time left over to stop cleanly and report. A sample Amazon answers still finishes in seconds; only a blocked one uses the extra time; the no-input sample still uses only the unpaid connection routes, so a wait never buys a paid one; and nothing is charged unless a product row is delivered.
- How much of its remaining time a blocked run may spend waiting now follows the size of what you asked for. A run with more products still to read keeps exactly the limit it had — no more than half the time left — so a wide block still leaves the later products their share of the run. A run with a single product may spend what is left on its one pause, because nothing else is waiting for that time.
- A product Amazon walls now gets another try later in the same run, when the run has the time for it. Every route to a product can be refused for a few minutes at a stretch, and this actor used to report such a product as "please re-run" within about a minute — with most of a long run still unused. Now, when products are left walled after the first pass and the run still holds real time, it waits one to three minutes, comes back on fresh connections and tries the walled products again — more than once on a long run, never on a short one, and never past the point where the summary row and the run's own report must still be written. A product that genuinely is not there — a wrong id, an id from another country's catalogue, one of Amazon's own subscription pages — is still reported at once and never waited on.
- The rows for products that stayed walled land after the delivered ones, in your list order, and each now says how long the run waited and how many passes it made before giving up. They are still uncharged and still safe to re-run.
- The summary row records the wait: how many products were walled, how many passes were made, how many seconds were spent waiting, and how many of the walled products the wait recovered.
- A wait is taken only when it pays for itself. An idle minute costs this actor's own compute, so the run waits only while the walled products still to deliver would cover it at your price — except that a run which has delivered nothing at all always gets one wait. What is charged does not change: only delivered products are charged, exactly as before.
- A price recovery interrupted by a network hiccup now gets a second try before it gives up. When a product page on a European store comes back without a local-currency price, this actor fetches the page a second way to recover it. If that fetch was cut short by a temporary network error or a rate limit — not by the page itself — it used to be abandoned after one attempt. It now takes one more look on a fresh route, so a price reachable a moment later is recovered instead of left blank. A page the store itself walls, or a definitive answer, is unchanged, and nothing is retried past the run's own time limit.
- A run near its time limit stops cleanly instead of being cut off mid-fetch. The page-fetch ladder now checks the run's own clock before every attempt and every pause between attempts, so it never starts a fetch it cannot finish in time. A run that reaches its limit ends with its summary row intact rather than being stopped part-way through a request.
- Settings with no products now run the sample under your settings, instead of returning one guidance row. Picking a different Marketplace, turning off variants or specifications, or setting a limit and clicking Start with Products empty used to end the run with a single uncharged "no products were provided" row — so changing one dropdown was answered worse than changing nothing at all. That run now fetches one real sample product on the store you picked, with your settings applied, charged like any run.
- The sample now has a real product on every store this actor covers, so a sample on
amazon.co.uk, .de, .fr, .it, .es, .nl, .pl, .se or .com.be comes back as a product row rather than "not in that catalogue".
- A limit is a ceiling, never a request. On one of these runs "Max products" and "Max run seconds" are honoured as at most — the sample's own one product and three-minute window are used when they are smaller, so narrowing a setting can never widen the bill.
- One uncharged row explains it, naming every setting you did set, that everything else used the sample's own values, and the field to fill in for your own run. It is never counted as a miss.
- A field this actor does not recognise, or a product list you actually filled in, still gets the guidance row — answering a typo with sample rows would read as if it had worked. A store this actor does not cover is still refused by name.
- A mistyped "Marketplace" no longer swallows your product list. One unreadable value there used to end the run with a single guidance row, whatever you had typed in "Products" — twenty ASINs came back as one row. Every product you sent now gets its own uncharged row saying it was not looked up and which field stopped it, and the run still succeeds. Nothing is fetched and nothing is charged, exactly as before.
- "Marketplace" now says which of three things went wrong. A real Amazon store this actor does not cover (amazon.ca, amazon.co.jp, amazon.in and the rest, plus the country names people type for them) names the nearest store that does work, instead of sending you back to re-check a spelling that was already right. A value naming more than one store — "worldwide", "Europe", or just "amazon" — says this actor reads one store at a time. Only a value nothing can read is now reported as unreadable.
- Every uncharged input row now carries the field it is about, so a run with several settings set says which one to fix without reading the sentence.
- The run status line and the summary row count what you asked for, not what survived the settings. A run stopped by a refused setting said "Delivered 0 of 0 products" when you had asked for twenty; both now say 0 of 20 and name how many were not looked up, so the run page and the dataset never give you two different numbers for the same fact.
- The run's own report to us carries that same number — the ids you typed, counted before any limit applies. It used to report whichever list in your input happened to be longest, so a run that turned every id away could look like it had nothing to do.
- A store written the ordinary way now works in "Marketplace". The field used to take the exact domain and nothing else, so
US, USA, United States, Amazon.com, www.amazon.com and a pasted store link each stopped the run before a single id was looked up — one guidance row, and nothing for anything you sent. The domain, the host, a pasted link, the country code and the country name all resolve now. A store this actor does not cover is still refused rather than answered with a different one.
- A run stopped by an input mistake now tells us which field was wrong — the field's name only, never the value you typed. A check that is too strict now reaches us as one thing to fix instead of looking like many unrelated typos.
- An id that belongs to a different country's catalogue is reported as exactly that in our own run reports, instead of sharing a name with a temporary outage. Nothing about the row you receive changes.
- A product page that comes back unreadable is now retried before it is reported as a miss. A page that arrives complete but with none of the product on it used to end the attempt right there. The run now takes another look — a different page layout, a different network route — and reports a miss only if those come back empty too. Same price either way.
- A European product that every route was walled out of now gets one more route before it is reported as a miss. On amazon.co.uk, .de, .fr, .it, .es, .nl, .pl, .se and .com.be a run that hits a wall on every route now takes the same recovery route it already used to fill in a missing price, so a product that used to come back as "please re-run" comes back as a row. A product that genuinely does not exist is unchanged — still returned uncharged, and with no extra fetch.
- A run that stops before it starts now reports its outcome too — a run refused for its memory setting now reaches us the same way every other run does: counts and reason codes only, never your input or your rows.
- Every run now reports its own outcome to us — counts and reason codes only, never your input or your rows — so a run that goes wrong reaches us even when nobody shares it.
- Run status lines fit the run page again; sample-run wording shortened.
- A run stopped by a pricing fault on our side now asks you to open an issue once, not twice, and names the reply time.
- A run that filled the row cap you set is no longer treated as a run that went wrong. The Issues-tab line now appears only when something actually did.
- The run page points at the Issues tab on every ending that went wrong, including a run refused before it started.
- One support promise on this page — the older three-hours line is gone.
- A run that ends with a problem now says where to reach us. A miss, an input error, an early stop or a failed run closes by pointing at the Issues tab and naming the reply time; a fully delivered run is left alone.
- One support promise across this page — issues are answered in a couple of hours, always within a day.
Documentation build: nothing about what runs, what is delivered or what is charged changed.
- The screenshots on this page now load from Apify storage. The same two images of a real run, served from the platform itself instead of an outside host.
- Every link on this page now stays inside Apify.
A run never spends more on a fetch than it can bill.
- Products that Amazon serves only through a stronger connection are fetched that way only while the run can still pay for it. The first such product in a run always gets the attempt. After that, the run keeps buying the stronger connection only while what it can bill you covers the cost; otherwise the product ships as an uncharged row that says so and tells you which setting to raise. Nothing changed about prices, about what a delivered product row contains, or about what is charged: only delivered products are ever charged, exactly as before.
- Runs that never need the stronger connection — the great majority — behave byte-for-byte as they did.
Documentation build: nothing about what runs, what is delivered or what is charged changed.
- Real console screenshots on this page — the input form exactly as it arrives, and the dataset table a real run delivers.
- One-click MCP link — pin this actor in Claude, Cursor or any MCP client straight from this page.
- Suite links refreshed to the current names of the other steadyfetch actors.
- Input-form copy corrected. The Products field still said a bare Start returns uncharged sample rows. It runs a real one-product sample, charged like any run — the field now says so, as this page already did.
Start with the default form and get a real product instead of a placeholder row.
- A bare Start now runs a one-product sample. Click Start with nothing set (or send an empty input from the API) and the run fetches one real product — ASIN
B0DN4BG1RW on amazon.com — and returns its full row, charged like any other product. The two placeholder "sample rows" are gone; what you see is what a real run returns.
- The sample stays small and quick by design: one product, the no-cost connection lanes only, and a three-minute window. On a bad Amazon minute you get one uncharged row saying the page was not served (re-run in a minute), never an empty dataset.
- The status line says when a run was the sample and how to run your own products.
- Nothing else changed: any input with products in it behaves exactly as before, and a mistyped field still gets a row naming the field instead of a sample.
The Marketplace dropdown accepts null as well, so an all-fields-null template runs.
- An input that fills every optional field with
null now starts. That is the shape n8n, Make and most agent frameworks actually send, and one field was still refusing it: the Marketplace dropdown. {"products": ["B0DN4BG1RW"], "marketplace": null, "maxItems": null, "includeVariants": null, "includeSpecs": null} used to be rejected before the run began, with an error about allowed values. It now runs on the defaults, exactly as if those fields had been left out.
- A store we do not cover is answered by name, and nothing is looked up.
"marketplace": "amazon.ca" returns one uncharged row naming the ten stores that do work. It is never quietly swapped for amazon.com: US rows under a Canadian question look exactly like the answer you asked for, which is the one outcome worth failing a run over. Nothing is charged, and the run still succeeds.
- Every value the dropdown lists behaves exactly as before, and the console picker is unchanged.
- Nothing about what is delivered or charged changed. One flat fee per delivered product, misses never charged.
Optional settings now accept null, and null means "use the default".
- An explicit
null on an optional setting starts the run instead of refusing it. Agents and integrations routinely fill in the fields they are not using with null; until now {"products": ["B0DN4BG1RW"], "maxItems": null} was rejected before the run began, with an error saying the field had to be an integer. It now runs exactly as if the field had been left out.
null never changes what a run does. Max products, Max run seconds, Include variants and Include specifications each fall back to the same default they would have used anyway. This is a second way to say "leave it alone", not new behaviour.
Products still cannot be null, and neither can the Marketplace dropdown — a dropdown only accepts one of the values it lists. Send a real value or leave the field out entirely. Products staying strict is deliberate: it is what catches a mistyped field name before the run starts rather than after.
- Nothing about what is delivered or charged changed. One flat fee per delivered product, misses never charged.
Rows come back in the order you listed your products.
- The dataset now follows your list. Every row carries the line it came from (
input, shown as "You asked for"), but the two fetch lanes each wrote their row the moment that product finished loading, so a pasted list came back out of order and could not be read straight back alongside the sheet it came from. Rows are now written in list order.
- An uncharged miss keeps its own line. An ASIN Amazon would not serve still ships as a
charged: false row, and it now sits on its own line in the list instead of at the end.
- A list that mixes Amazon stores keeps its own rhythm. Such a list is worked through store by store in rotation, to keep the pace off any one site — the rows now arrive in exactly that sequence, which is also the sequence the summary's
resumeCursor counts in, so the two can no longer disagree.
- Nothing else moved. Rows still stream in as the run goes (a run the platform moves to another server keeps everything already written), the two lanes still fetch in parallel, and what is charged is unchanged: one flat fee per delivered product, misses uncharged.
The linked example dataset is re-shot from the code this release ships, and it now has a permanent address.
- The "real dataset, not a mock-up" link points at a fresh run of exactly this code — three products across amazon.com, amazon.co.uk and amazon.de, the Sold-by cluster populated on every charged row, and the self-reconciling summary row last.
- That sample now lives at a permanent address. It used to be one run's own output, which is cleared when that run ages out — the link would eventually have gone dead on its own. It cannot now.
- The page says "one verified run of the current code", not "of the current build", because a release that changes only this page must not make that sentence false. Nothing about what this actor delivers or charges changed in this release.
The linked example dataset is re-shot from a verified run of the current build.
- The "real dataset, not a mock-up" link now points at a run of this build — three products across amazon.com, amazon.co.uk and amazon.de, the Sold-by cluster populated on every charged row, and the self-reconciling summary row last. Nothing about what this actor delivers or charges changed in this release.
The Sold-by seller is populated again on delivered rows, and absences explain themselves.
buyBoxSeller, buyBoxSellerId, fulfilledByAmazon and soldByAmazon are filled in again. Amazon serves the Sold-by block in several different layouts, and rows had been shipping the whole cluster as null. The parser now reads every layout we have captured — the classic Sold-by block, the newer offer-display widget, the mobile "Sold by:" rows and the Add-to-Cart form's own merchant id — verified against freshly captured amazon.com and amazon.co.uk pages.
- New column:
buyBoxNote. When a served page genuinely names no seller (some renders ship the buy box empty), the four Sold-by fields stay null and this column says so on that exact row. A null is never a silent gap.
- Amazon's own device pages now deliver their specs. Fire-TV-class pages keep their spec sheet in a different layout and previously shipped
specs: {}. categoryPath and bestSellersRank stay empty on those pages because Amazon renders neither there — the README now discloses that.
- Invisible direction marks are stripped from every text field. Some pages prefix values with right-to-left/left-to-right marks that render as
‎ garbage in exports; they are gone.
- amazon.co.uk delivers again. The .co.uk site had begun refusing every desktop browser fingerprint on every route we use, which could zero a run. The fetch ladder gained one final mobile-fingerprint step on the same residential exits, verified end-to-end on .co.uk pages the same day. Blocked or missing items are still never charged.
This page's wording refreshed — the European price re-check is described more plainly. Nothing about what this actor delivers or charges changed.
Clearer release notes — this page's notes now read more plainly. Nothing about what this actor delivers or charges changed.
Suite links now point at the full live shelf — every actor named in this README is a live
store link. Nothing about what this actor delivers or charges changed.
Restarts, resurrections and billing bookkeeping hardened end to end.
- A restarted run no longer trusts a stale answer about what it already delivered. Right after a restart, the platform's view of the run's own output can lag a few seconds behind. A run that believed that lagging answer could have delivered — and charged — products a second time, or lost count of rows past the lagging total. It now double-checks an "empty" answer and reads its own output through to the true end before doing anything, so nothing already delivered is ever fetched, delivered or billed again.
- Finishing an interrupted charge can never bill twice — and can never sink the run. When a restart finds a charge from the previous attempt half-finished, the amount still owed is reckoned against the highest count of what already landed, so a lagging counter cannot cause a repeat charge. And if that settlement cannot be completed at that moment, the run carries on and settles it on a later resume instead of failing — nothing extra is charged either way.
- A run being moved to another server hands over cleanly. The departing side no longer declares the run finished on its way out — the run continues where it left off.
- A resurrected run gets a real working window. "Max run seconds" counts the run's life, not each restart's — but a run resurrected after that window had already passed used to stop on its first step, blaming your own limits, with nothing new delivered. It now gets a fresh, bounded window to finish the remaining work.
- If this actor's own price configuration is ever broken, a run stops before spending anything. Both broken shapes — one that would bill for rows we promise carry no result fee, and one that could not bill at all — halt immediately, fetch nothing, charge nothing, and say plainly that the fault is ours.
- A charge is counted only when it actually landed. The
charged flag and the run's own charge totals now reflect the platform's answer, never an assumption.
The extra price retry's spending allowance now counts correctly.
- The per-run allowance on the extra price retry is now measured exactly. Some retries could previously be under-counted, so a retry-heavy run could spend past the allowance before its clean stop engaged. That allowance is ours and was never billed to you — nothing changes about what a run delivers or charges.
Numbers printed in the "wrong" language now always read as the numbers they are.
- Counts survive a page served in another language's number format. Amazon renders a page in the formatting of the route that fetched it, not the store's own, so amazon.de sometimes arrives with English-style numbers — a review count of "4,305". Read with German number rules that used to collapse into a decimal: a charged
reviewCount of 4, a thousand times under. Grouped whole numbers now read as grouped whole numbers in every language — on review counts, bestseller ranks and prices alike.
- "Bought in past month" badges phrased without a "+" right after the digits parse correctly. In phrasings like the German "Mehr als 1.000 Mal … gekauft" the word after the number could be mistaken for a millions mark — 1,000,000 instead of 1,000. A magnitude mark now counts only when it is attached to the digits, and the localized German thousand/million marks ("Tsd.", "Mio.") are understood.
- A Nordic "kr" price on a non-Nordic marketplace is never labelled with that marketplace's own currency. Such a page used to ship first try with the amount labelled e.g. EUR. It now counts as a foreign-currency render — the standard routes are tried again and the extra price retry can fix it, and if the kr amount still ships, its
currency is left honestly empty instead of guessed.
- The extra price retry is spent only on pages it can actually fix. A page that itself says "Currently unavailable" has no price to recover in any country, so it no longer consumes the per-run retry budget — that now goes entirely to pages where Amazon withheld the buy box. And if the retry stops being available to the run, it stands down for the rest of the run instead of delaying every remaining product with doomed attempts; rows keep shipping either way.
- The Amazon suite links in the README now point at the published actors.
Guidance rows say "Nothing was charged" exactly once.
- A row answering an unusable input no longer repeats itself. The row for a misspelled input field name, and the row for a link that points at an Amazon marketplace this actor does not cover, both used to end by saying "Nothing was charged" twice in a row. Each now says it once. What is delivered, what is charged and every other row are unchanged.
A typo in an input field name now gets a helpful pointer instead of sample rows.
- A run that sets a field this actor does not have is answered, not demoed. Sending something like
asns instead of products used to look exactly like an empty run, so it came back with the uncharged sample rows — and nothing said the field had been ignored. Such a run now returns one uncharged row that names the field it did not recognise, names Products (input key products) and shows the shape to send. A run that really is empty still returns the sample rows, and a run with real products is unchanged.
- Review counts on amazon.fr, amazon.se and amazon.pl arrive as numbers. Those storefronts print the review total with a non-breaking space between the digit groups ("4 298"), which earlier builds could not read — the row shipped an honest
reviewCount: null. The count is now read in the store's own formatting, like every other marketplace. Prices, charging and all other fields are unchanged.
Nine European marketplaces, with real local prices.
- New marketplaces: amazon.fr, amazon.it, amazon.es, amazon.nl, amazon.pl, amazon.se and amazon.com.be join amazon.com, amazon.co.uk and amazon.de — paste a product URL from any of them, or pick one in the
Marketplace setting for bare ASINs.
- European rows now carry the real local price. Amazon withholds the buy box from cheap routes far more often in Europe; a European product that comes back price-less now gets one extra, more thorough retry, so
49,00 €, 475,00 kr and 139,00 zł arrive as numbers in the store's own currency instead of price: null. When every route fails the row still ships honestly price-null with a priceNote, and misses are never charged. The flat fee is unchanged.
- Two price-parsing fixes. The Swedish
kr and Polish zł currency marks are now read off the page instead of being dropped, and promotional wording printed next to a price ("avec 18 % d'économies") can no longer bleed its digits into the parsed amount — a percentage is never read as part of a price, in any language.
- Runs near their timeout always end cleanly. When too little time remains for the extra price retry it is skipped and the row ships promptly with its honest
price: null, and a retry that does start is given only the time actually left — a run can no longer be cut off by the platform timeout mid-retry and lose its end-of-run summary row.
- An outage on the extra price retry stops it at once. If those retries start being declined, the run stops sending them for the rest of the run instead of spending up to 90 seconds per price-less product on attempts that cannot succeed. The affected rows keep their honest
price: null either way, and misses are still never charged.
- The extra retry's internal spending cap is now exact under parallel fetches. It could previously be overshot by one attempt when two products were in flight at once. This cap is our own budget — it never was, and never is, on your bill.
Initial release.
- Paste ASINs or Amazon product URLs and get one complete product row each: price, currency, list price, stock, buy-box seller, rating, review count, bought-in-past-month, variants, bestseller ranks, category path, images, bullet points and the specifications table.
- Accepts ASINs,
/dp/ and /gp/product/ links, short links and links copied out of search results, in any casing.
- Marketplaces: amazon.com, amazon.co.uk and amazon.de.
- One priced event per product and nothing else — no start fee, no per-field fee, no delivery-location fee.
- Blocked, missing, absent-from-that-marketplace and unreadable products are returned with an honest status and are never charged, and every run ends with a summary row that reconciles against the invoice.
- Amazon's own subscription plans (some of them rank in Best Sellers) come back as
not_a_product and say so plainly, instead of being reported as a page we could not read.
- One product is one row and one charge, however you reached it — the same listing sent as an ASIN, as a URL, as a short link, or reached by two redirects that only converge on the page itself, is never delivered or billed twice.
- Your limits are exact: the run stops cleanly, names the setting that stopped it, and hands back a resume cursor.
- Limits and billing survive a restart. If the platform migrates the run to another server, or you resurrect it, the run reads back what it already delivered and continues: already-delivered products are never sent twice and never billed twice, a cap of 10 stays a cap of 10, and "Max run seconds" counts seconds of the run rather than of each restart.