Skip to content

Add Amazon shopping and guarded retail cart tools - #56

Merged
yummybomb merged 37 commits into
mainfrom
hypeship/amazon-search-product-bestsellers
Oct 26, 2026
Merged

yummybomb merged 37 commits into
mainfrom
hypeship/amazon-search-product-bestsellers

Conversation

@yummybomb

@yummybomb yummybomb commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds six Amazon US tools in domains/amazon.com/, all kind: "page" on https://www.amazon.com/*. They make same-origin requests only and never navigate the tab.

  • search_products, get_product, get_best_sellers: catalog search, product and variation details, Best Sellers rankings.
  • get_cart: reads the retail cart, plus the session_context and cart_version that writes require.
  • add_to_cart: adds one child ASIN that is not already in the cart. It first checks the product's price and seller against get_product's output.
  • update_cart_item: sets an absolute quantity on one line; 0 removes the line.

No tool opens checkout, uses Buy Now, signs in, or places an order.

How the cart writes work

These request shapes were taken from Amazon's own pages and cart script, then confirmed live.

  • Add: sends the product page's form to the Add to Cart button's own target, /cart/add-to-cart/ref=…. Buy Now is a separate button targeting /checkout/entry/buynow. The tool rejects any other target, and it leaves out the five Buy Now pipeline fields (pipelineType, referrer, isBuyNow, isEligibilityLogicDisabled, ref_). A body with only the ASIN, offer, merchant, token and quantity fields is rejected by Amazon (HTTP 400 or 404).
  • Update/remove: one POST to /cart/ref=ox_sc_cart_actions_1 with the same actionPayload, activeItems and savedItems that Amazon's cart script sends.
  • Every write:
    • Refuses a different session (session_changed) and a stale cart (stale_cart).
    • Refuses carts holding other cart types, delivery groups, or related, subscription or variable-weight lines (unsupported_cart).
    • Refuses sign-in and checkout pages.
    • After sending, it re-reads the cart. It returns success only if exactly the requested change appeared. Otherwise it returns outcome_unknown, and it never retries.
  • Cart reads: each line's title and price come from its data-producttitle and data-price attributes. Each cart row becomes one record, and the reader decides whether the cart can be written.
  • Shared code: tool files can't import, so code is copied, and tests require each copy to stay byte-identical:
    • the page fetch and block detection (sign-in, robot check, throttling, access notice), in all six tools;
    • the text and price helpers, in the four tools that read product markup;
    • the cart reader, in the three cart tools;
    • the checks shared by the two write tools;
    • get_product's price, seller and Add to Cart availability checks, which add_to_cart reuses so it accepts get_product's output exactly;
    • the cart snapshot schema.

Validation

  • node scripts/validate-registry.mjs: 221 tools valid. node --test "tests/*.test.mjs": 2588 pass, 0 fail, including 53 cart tests, 55 shopping-read tests and 6 shared-code tests.
  • Independent live QA on 2026-10-05 and 2026-10-06 (re-run after the restructure), all in fresh signed-out guest carts:
    • Writes: two adds, an update from 1 to 2 and back, and removal of both lines to an empty cart. Each was invoked from the homepage and confirmed by an independent read of the cart.
    • Write refusals: stale version, wrong price or seller, duplicate ASIN, variation parent, wrong line or quantity, and a sign-in page. None of them sent a write.
    • Search: every sort, a price range, sponsored exclusion, a facet filter, page 2, a nonsense query and invalid inputs.
    • Cart reads: identical digests from several pages.
  • No tools were listed on aws.amazon.com.
  • get_product: matched the live product page on price, seller, availability and rating, and returned not_found for an ASIN that 404s.
  • All six tools are draft again. The last commit shares the page fetch and block detection across all six tools and makes add_to_cart_available use add_to_cart's own check. The live QA above was of the previous source, so the current source needs a fresh independent QA pass before it goes back to verified.

Not covered

  • Signed-in carts. Every live write ran in a guest cart.
  • A live outcome_unknown result.
  • Challenge or Conditions of Use pages during a write; these are tested with fixtures only.
  • Wishlists, orders, account pages and checkout are out of scope.

@yummybomb yummybomb changed the title amazon.com: add search_products, get_product and get_best_sellers Add Amazon shopping and guarded retail cart tools Sep 30, 2026
@yummybomb
yummybomb marked this pull request as ready for review September 30, 2026 14:52
…h-product-bestsellers

# Conflicts:
#	registry.json
add_to_cart posted a field subset to the form's handle-buy-box action,
which Amazon rejects; it now sends the form to the Add to Cart button's
/cart/add-to-cart target, minus the Buy Now pipeline fields, and checks
price and seller with get_product's own extraction. Cart lines read title
and price from data-producttitle/data-price (the .sc-product-price node
does not exist), session_context no longer hashes session-token, and add
refuses ASINs saved for later.

Drop the tab ledger and the second preflight read: cart_version and the
exact readback already refuse stale or repeated writes. Fold
remove_cart_item into update_cart_item (quantity 0) and drop
prepare_checkout, whose output was get_cart plus constants. Share one
byte-identical cart reader across the three cart tools, checked by a test.

Bring the README and registry entries to the current spec: two-column
README, url_patterns_reason, and draft status pending QA of the new source.
The cart reader now returns one record per row (public line plus the row
fields requests and the version need) and decides writability itself, so
the separate safety array, raw DOM nodes and supportedCart go away. Write
guards shared by add_to_cart and update_cart_item, and get_product's
price/seller extraction reused by add_to_cart, live in marked blocks that
tests require to stay byte-identical, as does the cart snapshot schema.

Page checks follow the read tools' order (robot check before
throttling; the access notice only counts without the expected content).
Error kinds say what they report: session_changed, unsupported_cart for
whole-cart refusals, quantity_unavailable. add_to_cart accepts any
sold_by get_product returns and the same Add to Cart buttons it detects.

Tests share one schema checker, assert one exact error kind per case and
no longer re-check registry rules the validator owns. Registry entries
from other domains are back to their original characters; the four
changed tools are draft until QA.
The read tools detected blocks with their own, narrower checks: an /ax/
sign-in redirect or a robot-check page without the captcha form came back
as site_changed from get_product, search_products and get_best_sellers
while the cart tools reported login_required or challenge. The page fetch
and block detection now live in one @amazon-page-fetch block used by all
six tools, which also gives the read tools cancellation.

get_product's add_to_cart_available now applies add_to_cart's own check
(an enabled button in the buy box form for this ASIN), shared through the
offer reader. text and cents move into an @amazon-text block covering all
four copies. readAfter returns { error } like the other cart helpers, and
add_to_cart only sends the button's field when the button has a name.

Marker comments name the outer bindings each shared block uses. All six
tools are draft until independent QA of this source.
No test covered the abort signal reaching fetch: dropping it from the
shared page fetch left every test passing, because the stub fetches
ignored init.signal. Both stubs now reject an aborted call the way a
browser does, and tests assert every request carries the caller's signal.
The read tools also refuse an already-canceled call before any request,
like the cart tools.

A 404 was reported as not_found before sign-in and robot-check detection
ran. The page fetch now takes an optional not_found message and checks a
missing page after those.

Rename the buy box helper to buyBoxAddToCart, end error messages the same
way in all six tools, and move the byte-identity tests to
amazon-shared-code.test.mjs.
…e requires

Amazon answers HTTP 406 to a fetch of /gp/cart/view.html whose Accept header is only text/html, while search and product pages accept it. The shared page fetch now sends the Accept value a navigation sends, which the cart page answers with the cart.
@yummybomb
yummybomb merged commit 74bb83f into main Oct 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant