Skip to content
amz

Search

Stream catalog result cards with refinements for sort, price, rating, Prime, brand, and department.

amz search queries the catalog and streams one record per result card, paging as far as your --limit asks.

A query

amz search "mechanical keyboard"
amz search "mechanical keyboard" -n 20 -o jsonl

Multi-word queries can be quoted or passed as separate arguments; amz joins them.

The card

Each result is a Card: position, rank, asin, title, price, list_price, rating, ratings_count, image, badge, prime, bought_past_month, delivery, sponsored, kind, url, and an envelope naming the response the row was read off. list_price carries the struck through price when the card is discounted, badge holds the "Amazon's Choice" and "Best Seller" style tags, and prime flags Prime eligibility.

Prices are objects: each keeps the string Amazon printed beside the parse of it, so price.value is the number and price.display is what the page said.

Sponsored placements are dropped by default and counted, so a run tells you what it left out:

amz: 3 sponsored placements left out. pass --include-sponsored to keep them

--include-sponsored keeps them, and they arrive flagged rather than mixed in. The sponsored field is never omitted from the JSON, because an advertisement and an organic result are different data and a consumer that cannot tell them apart is holding a corrupted dataset without knowing it.

Refinements

Flag Effect
--sort featured (default), price-asc, price-desc, review, newest, bestselling, or a raw Amazon sort value
--price a band in major units: 50-150, 50-, -150
--stars minimum star rating, resolved against the sidebar
--brand brand name or id
--seller seller name or merchant id
--condition New, Used or Renewed
-d, --department limit to a department, as listed by --list-departments
--refine any group at all, repeatable: --refine p_123=213704,111070
--page, --max-pages where the walk starts and where it stops
amz search "mechanical keyboard" \
  --price 50-150 --stars 4 --sort review -o table

--prime is gone. It is still a registered flag so that passing it says why rather than being an unknown flag, and what it says is an exit 2:

$ amz search "mechanical keyboard" --prime
amz: --prime is gone in v0.3.0. no capture taken on 2026-08-17 offered the p_85 group at all, and the id v0.2.1 sent (2470955011) would have been dropped in silence.
run `amz refine <query>` to see whether this query offers a prime filter, then pass it with --refine

The id v0.2.1 sent is per marketplace, and a query that does not offer the group gets an unfiltered page rather than an error, which is the failure mode the whole refinement layer exists to prevent. amz offers --prime is a different thing and still works, because that one filters records amz already holds.

The vocabulary is read, not compiled in

Only six refinement codes mean the same thing on every search, and amz knows only those six without looking. Everything else is per query: one search for keyboards on 2026-08-17 offered thirty-three groups, and p_n_g-1003532609111 is "Key Count" on that search and does not exist on a search for shoes.

So the sidebar is the source. amz refine prints the whole vocabulary a query offers, with the code, the human label, the scope, and every value with its id:

amz refine "mechanical keyboard"
{"code":"p_123","label":"Brands","scope":"global","values":[{"id":"213704","label":"Logitech"},{"id":"220854","label":"Razer"}]}
{"code":"p_n_condition-type","label":"Condition","scope":"named","values":[{"id":"2224371011","label":"New"}]}

--brand Logitech and --brand 213704 both work, and -v prints the id a name resolved to, so a script can pin the id and skip the lookup next time.

A refinement Amazon dropped is an error

Amazon does not reject an rh group it does not honour. It drops the term and serves the unfiltered result set with a 200 and a full grid. So amz checks the sidebar of the page that came back and fails when what it asked for is not marked as applied:

amazon did not apply the refinement: sent p_n_cpf_labels:121136630011 and the page came back without it applied, so these results are not filtered by it

The alternative is handing back ten thousand unfiltered rows labelled as a filtered search, with nothing downstream able to tell.

Getting past 306

Amazon serves at most 306 results over 20 pages for any query, whatever total it advertises. That is not a pagination problem and no amount of paging opens it. amz search says so when it hits the wall:

amz: amazon serves at most 306 results per search over 20 pages, whatever the corpus says
amz: run `amz why search-depth`, narrow with --refine, or partition with --all to reach the rest

--all is the way through. It partitions the query on a refinement group, runs one search per value, and unions the cells on ASIN, so each cell gets its own 306 and a cell that still hits the ceiling is split again.

Price it before you run it:

amz search "usb-c hub" --all --dry-run

Measured on 2026-08-18, amz search "usb-c hub" --all partitioned on p_123 (Brands) into 68 cells and returned 1,508 unique results, against the 306 a plain search can reach.

A partitioned run is honest about its own holes, and there are always some:

amz: partitioned on p_123 (Brands), 68 cells, 1508 unique results, 298 repeat sightings
amz: 19 cells still hit the ceiling and were not split further, so this union is incomplete: ...
amz: 4 cells were offered in the sidebar and then served unfiltered, so they read nothing: ...

The first list is where the union is known to be short, and --partition-depth raises how many times a capped cell may be split again. The second is Amazon offering a filter in its own sidebar and then ignoring it, which happens on values like "Any Feature" under Sustainability Features. One such cell does not end the run; it is named and the other sixty-seven are still read.

Every card carries the cells it was found in, so a result that turns up under three brands is one record that says so rather than three records that look like three products.

Straight into the queue

--enqueue pushes each result into the crawl queue instead of printing it, so a search becomes the seed for a bulk product crawl:

amz search "mechanical keyboard" --enqueue -n 100
amz crawl              # drain the queue into the local store

See crawling at scale for the queue and store.

Compose

Turn a search into full product records:

amz search "mechanical keyboard" -n 25 --fields asin -o csv --no-header \
  | xargs -I{} amz product {} -o jsonl > keyboards.jsonl

Count the pages and the ceiling without keeping the cards, which is the cheap way to size a query before committing to it:

amz search "mechanical keyboard" --pages -o json