Track Amazon.ca Best Sellers and New Releases (the whole top 100), prices with price history, stock and Best Sellers Rank, search positions, keyword suggestions and reviews, on Canada and 22 more marketplaces. Scheduled runs show what moved, what is new and which prices dropped.
0.1.44 - README: how reliable Amazon.ca's lists were this week
The README no longer calls lists the most reliable mode: it gives the measured share of default runs that got
Amazon.ca's list from Apify's servers on 2026-10-09 and 10-10 (6, 7 and 3 of 10, then 6 of 6), and what a run does
about robot checks. Same code as 0.1.43.
0.1.43 - More patience for a list's first page, less for page 2
A list's first page, a run's way in, is now asked for up to 11 times (about three and a half minutes of waits)
as a new visitor each time, up from 8 (about two minutes). On 2026-10-10 Amazon.ca refused 7 of 10 default runs'
eight tries from Apify's servers, and the runs that got the list did so after 4 and 7 refusals. Page 2 goes back
to 4 tries, so a run that waited out its first page still ends inside the 5 minutes Apify's daily Store test
allows. The Actor still never answers a robot check.
2026-10-09
0.1.40 and 0.1.41 - More patience with robot checks on list pages
A list page, a run's way in, is now asked for up to 8 times over about two minutes (was 4 times over about
17 seconds), each time as a new visitor, after waits of 2, 4, 8, 16 and then 30 seconds. On 2026-10-09 Amazon.ca
answered Apify's servers with robot checks far more often than the day before: 6 of 10 default runs failed with
4 tries, and 3 of the 4 runs of this build that got the list did so on their 5th to 8th try. The Actor still never
answers a robot check; it waits and asks again.
README: keyword suggestions are named with lists as the most reliable mode; the form's change-tracking fields
mention keyword suggestions.
2026-10-08
0.1.37 and 0.1.38 - Keyword suggestions, price history, run summary
(0.1.38 is the same code with the README's measurements from Apify's servers.)
Keyword suggestions mode. The keywords Amazon's search box suggests for each keyword, in its order, on all 23
marketplaces, from Amazon's own suggestion service with each marketplace's id (Amazon.ca's differ from
Amazon.com's). Expand each keyword adds the keyword followed by a to z, or a to z and 0 to 9: "nappies" on
Amazon.co.uk gave 344 keywords, イヤホン on Amazon.co.jp 343. Each suggestion is one row, with what was typed
(prefix) and its place in the box; change tracking marks new, moved and dropped suggestions.
Price history. Lists, searches and products keep their last 30 price readings (Price history: runs to
keep, up to 365), and each row shows lowestPrice, highestPrice, averagePrice, atLowestPrice,
priceReadings and priceHistory, counted in the row's currency only. A product with Only changes on and nothing
to report now has its record updated too (its price and the run's time), so quiet days count in its history.
Run summary. Every run saves RUN_SUMMARY in its key-value store, linked from the Output tab: the outcome
(succeeded, partial, failed, stopped), each list's, search's or keyword's outcome with rows read and delivered,
what failed and why, refusals by kind, and the run's times. A pipeline can check a run without reading its log.
0.1.24 to 0.1.36 - Delivery address
Prices where Amazon withheld them. Where a product page comes without a local delivery address or with its
price withheld ("add this item to your cart to see its details"), the Actor sets the marketplace's main city
through Amazon's own location dialog, as any visitor can without signing in, and reads the page again. On
2026-10-08 the same 12 to 13 products had prices on 48 of 73 rows over six runs with the step, and on 16 of 50
over four runs without it, read at the same moments (Amazon.co.uk, .de, .es, .it, .co.jp, .com.au, .com.tr and .sg
gained them in one run or another). Where Amazon took the postcode and still showed the page without it
(Amazon.co.uk, .com.tr, .it at times), the run says so. Delivery postcode sets
your own postcode on the chosen marketplace; Set a delivery address where Amazon shows none turns the step off.
A step that fails (a robot check, a dialog that only asks to sign in) is named in the status message.
Prices in each marketplace's own currency. Amazon.co.uk showed Apify's servers converted dollars (USD65.99);
the Actor now asks for pounds, euros and so on, as Amazon's currency preference.
Each marketplace has its own visitor (session). A refusal on one Amazon site no longer starts a fresh visit on
the others, which dropped an address just set on another marketplace.
0.1.19 to 0.1.23 - Subcategories, 23 marketplaces, better reviews
Subcategories in one run. Subcategories reads each list's subcategories as Amazon's list page names them
(one level, or two), each a list of its own with subcategoryLevel and parentCategoryName. Amazon.ca's
Electronics has 15. All departments (or a pasted overview link such as https://www.amazon.ca/gp/bestsellers/ )
reads every department of a marketplace. Max results per list sets each list's top N; Max results is still
shared over all the lists, and a run stops looking for more lists at as many as Max results covers, and says so.
Thirteen more marketplaces, 23 in all: Australia, Brazil, the Netherlands, Sweden, Poland, Türkiye, Belgium,
Ireland, Singapore, the United Arab Emirates, Saudi Arabia, Egypt and South Africa. Prices, ratings, Best Sellers
Ranks, review dates and countries are read in each one's own words, from pages captured on Apify's servers, and
the 38 categories are mapped from each marketplace's own department list.
Reviews: a star filter (positive, critical or single stars), verified purchases only, newest or most helpful
first, the reviewer's pictures (reviewImages), a summary row per product (rating, ratings, star breakdown,
Customers say, and how many reviews the page showed and matched), and Also read reviews on other marketplaces:
each shows other reviews of the product, and a review shown on several is returned once.
Pages Amazon serves with parts left out are named, not read as empty. Some visits get a product page without
its lower half (rank, description, full specifications, reviews): 7 of 20 pages from Apify's servers on
2026-10-08, and the Amazon.de, .it and .in pages of 2026-10-06. Such a page is asked for once more as a fresh
visitor (none of 8 retries on the platform brought the whole page, so not more often); a product row that still
lacks it is marked partialPage, and a reviews run says the reviews didn't load instead of "no reviews" (release
1 reported those products as having none).
Withheld prices and the delivery address. Where Amazon picks no delivery address for a visit ("Select delivery
location": Amazon.com, .co.uk, .nl and .com.tr from Apify's servers), product pages show "add this item to your
cart to see its details" instead of a price: such rows say priceHidden. Every product row now has
deliveryLocation, the address Amazon showed the page for ("Deliver to United States" made Amazon.com.au products
"Currently unavailable").
0.1.17 - Only changes, richer product rows, search filters
Only changes: a scheduled run can output, and charge for, only what changed since the last run: new
products, moves, price and stock changes, and products that dropped off a list or search (with their previous
rank). Limits set what counts (1 place, 1% of the price and 10% of a Best Sellers Rank by default); a smaller
move keeps the last reported value as the baseline, so a slow slide is reported once it adds up. Every tracked
row now says its movement and lists its changes, and list and search rows have priceChange too. Max results
is how many ranks are watched; products that dropped off come on top of it.
Product rows: all gallery images, every variant with its ASIN and attributes, the parent ASIN, the
description and "From the manufacturer" text, the star breakdown, Amazon's "Customers say" summary and its
aspects (sentiment, mentions), coupon, discount %, Amazon's Choice, the #1 Best Seller badge, other offers and
their lowest price, and the number of videos. Read from pages of all ten marketplaces.
Search: sort order and price range, and pasted Amazon search links keep their own filters (star rating,
Prime, brand, department) without Amazon's tracking parameters. A filtered search is tracked apart from the
plain keyword (searchFilters). Search rows show coupons and discount %.
Product details for list and search rows: one switch adds each product's page to its row (only for changed
rows with Only changes); a page that didn't load leaves its row as it was, and the status message counts them.
0.1.16 - Pricing
Platform usage is included. Runs no longer charge compute on top of the row price ("Pay per event + usage"
is off). Rows cost $1.00 per 1,000 on the Free and Starter plans, $0.90 on Scale and $0.80 on Business and
above. The README's cost section says so; the code is unchanged.
2026-10-06
0.1.15 - Production pass
A page that can't be read fails the run. A list page whose products can't be read, a results page with
neither results nor Amazon's "No results" message, another page in a product's place, or a pasted link that
isn't a list each failed silently before ("Nothing found", SUCCEEDED, or rows quietly missing). They are now
named, and a run that got nothing that way fails, so a layout change on Amazon can't pass as an empty day. The
message tells such pages apart from robot checks.
A search is empty only when Amazon says so (its "No results for your search query" message, captured from
the platform).
The run stops a minute before its timeout and says what it read, instead of being cut off without a word.
Change tracking: a run that reads fewer ranks than the last one (a quick top-10 test) no longer replaces a
deeper snapshot younger than two days, which left ranks 11-100 "can't tell" on the next daily run. Each product
has its own record: one shared record per marketplace let two schedules erase each other's products. A stored
record holding 52.0 or true no longer makes a row the dataset refuses.
A request in flight stops at once when the run is stopping.
Pages cut short are asked for again. When one of two pages loading at once met a robot check, the fresh
session for its retry closed the shared connection, and the other page arrived cut short as an HTTP 200: a
product without its price or rank, or without its reviews. A session now closes only when no page is loading on
it, and a page that doesn't reach its end is asked for again.
Resumed runs stay within Max results. A run restarted after a kill or a move, whose list or search had
reordered meanwhile, could add its new top rows to those already delivered, and charge them. Each list, search
or product now keeps to its share, earlier attempts included, and the run never passes Max results. A resumed run
also records the products the earlier attempt delivered but didn't get to record.
Reviews are saved as they are read, not after the last product page, so a stop, a move or the spending limit
keeps what was read.
Change tracking: a price is compared only in the same currency (Amazon.com shows prices in the visitor's
currency), a Best Sellers Rank only within the same category, and a price or rank a page didn't show keeps the
last one known instead of erasing it. Product records of 0.1.14 compare as a first run.
Lists: page 2 is asked for whenever page 1 lists 50 products, not only when it links a page 2; Amazon's empty
grid or HTTP 400 there ends the list at 50. A damaged entry list keeps the 30 products shown and names the rest,
and an empty grid without Amazon's own "there are no best sellers" words fails instead of reading as nothing
listed.
Input:smile.amazon.com and m.amazon.de links work; links to other sites (Amazon.com.au, Amazon.nl...) are
skipped and named instead of being read on the chosen marketplace; two links on one line are two products;
{"url": ...} items work in Category links and Products; a History name of spaces means the default; products
past Max results are named.
Robustness: a page the parser chokes on fails its list, search or product, named, instead of crashing the
run, and any unexpected error ends the run FAILED with a message. Another page in a page's place is asked for
again once as a fresh visitor. HTTP 400 for a product counts as not found. Rows read before the timeout stop are
delivered.
Proxies: only the first of several own proxies is used, and the run says so: it never switches addresses to
get past a refusal.
Pay-per-event: a run whose result event can't be charged says so in its log, and the spending limit is still
followed through the per-row price.
0.1.11 to 0.1.14 - Whole lists, ten marketplaces read right, change tracking
Checked against live pages of all ten marketplaces, then rebuilt. Nothing below was guessed: every page layout,
price format and category name was read from Amazon's own pages (tests/fixtures).
What the first version got wrong:
Lists stopped at 30 of 100. Amazon shows ranks 1-30 on the page and loads 31-50 and 81-100 as you scroll.
The Actor now makes the same requests and returns the whole top 100.
Prices were empty outside Canada. "£14.16", "5,89 €", "CAD 17.08" (Amazon.com to a Canadian visitor),
"¥1,599" and "₹299.00" all read as nothing; ratings in German, French, Spanish and Japanese too. Prices,
ratings and counts are now read in each marketplace's own format, with the currency the page shows.
Half the categories had the wrong name. Toys, tools, office, garden and movies were called "not served on
.ca"; Amazon.ca names them toys, hi, office, lawn-garden and dvd. Amazon.de's Electronics is ce-de, so it
returned nothing. 38 categories are now mapped for each marketplace, each checked live (297 checks).
Amazon's refusals passed as results. A robot check counted as "no results", and an error row was output
(and charged) in place of a failure. Refusals are now named (robot check, bot check, HTTP 503), tried again
as a fresh visitor, and a run that got nothing fails with the reason. Nothing is charged for it.
Search titles on Amazon.com were rating counts ("(200536)"). Images were empty for most list rows (a
second image host wasn't read). Review titles were always empty. Product prices could come from another
product's widget ($210 for a $15 subscription).
Best Sellers Rank, seller and review text were said to be unavailable. Product pages do show them for
ordinary products (not for Amazon's own devices): they are now read.
New:
Change tracking: previous rank, rank change, new on the list, previous price; search position changes; product
price and rank changes.
Subcategories by link (any Best Sellers or New Releases page, any marketplace).
Product pages: list price, stock, seller and shipper, all Best Sellers Ranks, breadcrumbs, bullet points,
specifications, "bought in past month". Search: organic positions, badges, several keywords per run.
Max results is shared evenly between lists, keywords and products.
The proxy setting is followed as given (residential proxies refused, passwords masked).
Runs resume after a restart without repeating rows. 256 MB by default (peak use was 54-81 MB).
Removed: the chargeEvent input (the charged event is fixed) and the error row.
Measured on the platform before release (31 runs from Apify's servers):
Lists loaded on all ten marketplaces; one Amazon.co.jp run met a robot check on every try and failed, saying
so; the next one loaded.
Searches met HTTP 503 often: Amazon.fr succeeded on its fourth try, and Amazon.de, .co.uk, .it and .co.jp
refused every try. A search page now gets six tries (after 2, 4, 8, 16 and 30 s), and after two keywords in a
row get nothing on a marketplace, the rest aren't asked, and the run names them.
AWS WAF's challenge (an HTTP 202 of about 2 KB, x-amzn-waf-action: challenge) is named a bot check.
Amazon.com product pages from the platform sometimes show no featured price ("price not available", no
featured offer, or unavailable): the price is then empty, never taken from another part of the page.
Peak memory was 54-109 MB, so runs use 256 MB.
0.1.6 — Stub-response guard
Amazon intermittently answers HTTP 200 with a ~4 KB stub instead of the real
page (a few hundred KB). fetch() treated any 200 as success, so a stub would
have silently produced zero rows for that list. Now responses under
MIN_USABLE_HTML (20 KB) are retried with backoff.
Measured: 10/10 full pages at 1.2 s spacing, so this is a transient blip rather
than systematic throttling — but it must not silently empty a run.
0.1.4 — Multi-angle audit fixes
Five issues found by an adversarial audit (static review, failure injection,
input abuse, docs staleness) and fixed:
inStock false positives (data correctness). Availability was decided by
scanning the whole page for Currently unavailable|out of stock. That phrase
also appears in related-item and other-seller widgets, so genuinely in-stock
products were reported as out of stock (2 of 5 sampled). Now keyed off
Amazon's dedicated <div id="outOfStock"> box — verified 4 True / 1 False on
a mixed sample.
inStock was None for out-of-stock items. The old
(not unavailable) if price else None tied stock state to having a price, so
an unavailable item with no price returned None instead of False.
Unavailable now wins over price.
maxResults crashed the Actor on non-numeric input.int("abc") raised
ValueError and killed the run. Now coerced defensively with a warning.
String inputs for list fields iterated per character. A bare string
asins/urls/listTypes would be walked character by character, silently
producing garbage. Now coerced through an as_list() guard.
Invalid categories passed through unchecked and produced a silent empty
grid. Now validated against the 17 verified categories, with a fallback and a
warning naming the valid options.
Also in this build:
The proxy input was non-functional — it logged a message but never routed
anything. Apify Proxy is now genuinely wired via APIFY_PROXY_PASSWORD /
APIFY_PROXY_HOSTNAME / APIFY_PROXY_PORT, plus support for custom
proxyUrls.
Rows are now only kept when they carry a title (a price with no title is
unreadable to a seller and just inflates the dataset).
README H1 aligned with the Actor title (congruency).
Audit results otherwise clean: no unknown fields emitted, every emitted field
declared in the dataset schema, no dead schema fields, dataset views reference
real fields only, categories consistent across code / input schema / README,
exampleRunInput not the placeholder, parsers survive empty/garbage/truncated
HTML, ranks sequential with no duplicate ASINs, and platform schema validation
correctly rejects bad input with no run created.
0.1.3 — Fix double-counted maxResults guard
Accepted rows were appended to bothrows and batch, and the guard
len(rows) + len(batch) >= max_results counted each row twice — every run
returned exactly half the requested results (60 → 30, 30 → 15). Now guards on
len(rows).
Review counts added for list pages (a-size-small).
Boilerplate search titles ("Check each product page…") filtered out.
0.1.1 — Fix input schema
items.enum is not permitted inside an Apify stringList editor; valid values
moved into the description.
0.1.0 — Initial release
Three modes: trending (ranked lists), products (ASIN/URL lookup), search (keyword).
Verified extraction for Best Sellers and New Releases: rank, ASIN, title, price,
rating, review count, image.
17 category slugs verified to return a ranked grid on amazon.ca. Twelve
obvious candidates (computers, home, toys-and-games, tools, office-products,
shoes, watches, appliances, camera, wireless, movies-tv, lawngarden) return an
empty grid on .ca and are deliberately excluded rather than shipped broken.
Movers & Shakers excluded: Amazon.ca returns an empty grid for every
category tested.
BSR / Sold by / Ships from / FBA / offer counts deliberately NOT reported.
Verified absent from Amazon.ca's HTML both over plain HTTP and through a full
headless-browser render. Documented rather than fabricated.
Batched dataset writes (250 rows per call) so bulk runs do not degrade into
one write per record.
Plain impersonated HTTP only — no detection bypass, no anti-detect browser.