kestrel actors docs

kestrel actors › Ecommerce

Amazon Search Scraper — Best Sellers, Ranks & Prices

An amazon search scraper that turns amazon search results and category charts into structured rows: amazon asin, title, price, rating, rating count, image, sponsored flag, and the exact position on the page.

Run Amazon Search Scraper on Apify →

Amazon search scraper pricing: what one row costs

EventWhat it isPriceCharged for
productProduct row$0.004One product from a search page or a category chart: ASIN, title, price, rating, rating count, image, sponsored flag and its position or chart rank. Searches with no results are free.

Pay per event, one per delivered product row. Free: status rows, every row removed by skipSponsored, minRating or the cap, empty searches, and failed jobs. An ASIN found by two keywords is delivered and billed once per run.

A search page is roughly 20 organic products; a chart page about 30. Three keywords × 2 pages is a little over 100 rows. Verified runs behind this listing cost $0.0002–$0.0052 each in platform compute. Exact per-row pricing is on this page's pricing tab.

Amazon search scraper input reference

Every field of Amazon Search & Best Sellers, straight from the actor's input schema.

FieldTypeDefaultWhat it does
queriesarray[]Keywords to search, exactly as a shopper would type them: "wireless earbuds", "cast iron skillet". Each is searched across the pages set below.
categoriesarray[]Amazon category nodes to pull charts for, e.g. "electronics", "kitchen", "books" — the slug from a Best Sellers URL. Combined with the chart type below.
chartstring (enum)"bestsellers"Which category chart to pull for each category above. Movers & Shakers is rendered client-side by Amazon (its HTML carries no products), so it is not offered. One of: bestsellers, new_releases.
pagesinteger1How many result pages to walk. Search pages carry roughly 20 organic products each; charts carry about 30. Range 1-20.
maxResultsPerQueryinteger00 = everything the pages returned. N = the first N in Amazon's order. The main cost control. Range 0-2000.
skipSponsoredbooleanfalseDrop ad placements and keep only organic results — the honest view of keyword rank. Skipped rows are never charged.
minRatingnumber00 = keep everything. 1-5 = keep only products rated at or above this. Filtered products are never charged. Range 0-5.
domainstring"com"Amazon marketplace: com, co.uk, de, fr, it, es, ca, com.au, co.jp, in, com.mx, com.br, nl, se, pl, sa, ae, sg, com.tr, com.be.
departmentstring""Optional department to search inside, e.g. "electronics", "kitchen". Leave empty to search all of Amazon.
sessionsinteger4How many proxy sessions (egress IPs) run in parallel. More is faster; each is paced separately. Range 1-16.
perIpnumber0.5Pace for each session. Amazon tolerates about 0.5/s per IP; faster causes captchas, not speed. Range 0.1-2.
proxyConfigurationobject{"useApifyProxy": true}Apify Proxy is required: Amazon captchas datacentre traffic that is not rotated. RESIDENTIAL works best.

Example input

{ "queries": ["wireless earbuds", "bone conduction headphones", "sleep earbuds"], "pages": 2, "skipSponsored": true }
{ "categories": ["electronics"], "chart": "new_releases", "pages": 1 }

Amazon search scraper output fields

Two row types share one dataset: product (one search result or chart entry, charged) and status (per keyword or category, free).

Dataset views in the Apify Console: Overview, Keyword rank, Category charts, Run status.

FieldTypeWhat it holds
typestringRow type: product or status.
asinstringAmazon's product id — feed these straight into an Amazon reviews run.
titlestringProduct title as shown in the results.
urlstringProduct page URL.
querystringSearch rows: the keyword that returned this product.
chartstringChart rows: bestsellers, new_releases or movers.
categorystringChart rows: the category node.
positionintegerSearch rows: the slot on the results page, ads included — this is keyword rank.
rankintegerChart rows: the position in the chart.
pageintegerWhich result page the row came from.
pricenumberPrice when Amazon shows one in the results.
price_displaystringPrice exactly as printed.
currencystringCurrency of the marketplace.
ratingnumberStar rating out of 5.
ratings_countintegerHow many ratings the product has.
imagestringThumbnail URL.
sponsoredbooleanTrue when the slot is an ad. Charts are never sponsored.
domainstringMarketplace domain suffix.
marketplacestringMarketplace country name.
statusstringStatus rows: ok, no_results or error.
targetstringStatus rows: the keyword or category this job was given.
kindstringStatus rows: search or chart.
productsintegerStatus rows: product rows delivered.
filteredintegerStatus rows: rows dropped by the filters, never charged.
duplicatesintegerStatus rows: ASINs another job already delivered.
pagesintegerStatus rows: how many pages were requested.
errorstringStatus rows: why the job failed, null when it did not.
fetched_atstringUTC timestamp when the row was fetched.

Example row from a real run

Taken from the actor's README — this is the shape your dataset holds.

{
  "type": "product", "asin": "B0H9LRGB3B", "title": "Wireless Earbuds, Bluetooth 5.4 Ear Buds",
  "query": "wireless earbuds", "chart": null, "category": null,
  "page": 1, "position": 2, "rank": null, "sponsored": false,
  "price": 73.42, "price_display": "$73.42", "currency": "USD",
  "rating": 4.7, "ratings_count": 941,
  "image": "https://m.media-amazon.com/images/I/example.jpg",
  "url": "https://www.amazon.com/dp/B0H9LRGB3B", "domain": "com", "marketplace": "US"
}
{
  "type": "product", "asin": "B08JHCVHTY", "title": "Blink Plus Plan",
  "chart": "bestsellers", "category": "electronics", "rank": 1, "page": 1,
  "query": null, "position": null, "sponsored": false,
  "price": 39.99, "currency": "USD", "rating": 4.4, "ratings_count": 12034,
  "url": "https://www.amazon.com/dp/B08JHCVHTY", "domain": "com", "marketplace": "US"
}

Amazon search scraper in Python, JavaScript and curl

Python

from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/amazon-search-scraper").call(run_input={
    "queries": ["wireless earbuds"], "pages": 2, "skipSponsored": True,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "product":
        print(row["position"], row["asin"], row["price"], row["rating"])

JavaScript (Node)

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/amazon-search-scraper').call({
    categories: ['electronics'], chart: 'new_releases', pages: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'product').map((p) => [p.rank, p.asin, p.title]));

curl

curl -X POST "https://api.apify.com/v2/acts/kestrel~amazon-search-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{"queries":["wireless earbuds"],"pages":1,"skipSponsored":true}'

The same three calls are runnable files in the examples repository: examples/amazon-search-scraper.py|.js|.sh.

Limits and honest notes

  • position includes ads. That is intentional — it is the shopper's view. Use sponsored or skipSponsored for organic rank.
  • Price is what the results page shows. Some listings show a range, or nothing until you open the product; price is then null. Chart pages in particular often omit prices for a portion of entries.
  • Chart rank is Amazon's own where it prints one, and otherwise the position in the returned order.
  • Search pages carry about 20 organic products, plus ads. Walking more pages is how you go deeper, and a page that adds nothing new ends the walk automatically.
  • Amazon serves a captcha to repeat callers. The run detects it and rotates to a fresh IP rather than parsing the captcha page as an empty result set.
  • Cheap proxies first, residential only when Amazon pushes back. A run starts on the proxies you chose — datacentre is the cheapest — and rotates to a fresh IP on a captcha or a 503. When the same page is refused twice in a row that is the IP range being blocked, not the page, so the run stops trusting that pool: its sessions re-open on a residential proxy and stay there for the rest of the run. Nothing to configure, no run has to fail to teach it, and a run that is never refused never leaves the cheap pool — so a run costs the least that still succeeds. The run's SUMMARY reports it as http.escalated.
  • Marketplaces differ. The same keyword ranks differently in com and co.uk; run each marketplace as its own job.

FAQ

Does it need an Amazon API key?

No. Amazon's Product Advertising API needs an affiliate account with ongoing sales requirements, and it does not expose search rank the way a shopper sees it. This is an amazon search without api route: it reads the public results page.

Can I track Amazon keyword rank over time?

Yes — that is the main use. Schedule the run, keep the dataset, and position plus fetched_at give you rank history per ASIN per keyword. Use skipSponsored if you want organic rank only.

How do I separate sponsored from organic results?

Every row has a sponsored boolean. Leave it in to see the page as a shopper does, filter it out for organic analysis, or set skipSponsored: true so ads are dropped before billing and you never pay for them.

Can I scrape Amazon Best Sellers and New Releases?

Yes. Put the category slug in categories and choose chart: bestsellers or new_releases. Each row carries rank, so the chart arrives ready to sort. The slug is the part of a Best Sellers URL after /gp/bestsellers/.

How many products does one search return?

About 20 organic results per page plus ads, so a 2-page run is roughly 40 organic products. Charts return about 30 per page. Set pages for depth and maxResultsPerQuery to cap cost.

Can I get results for a specific category or department?

Two ways: department narrows a keyword search to a department, and categories pulls the chart for a category node. They answer different questions — the first is "who ranks for this phrase in kitchen", the second is "what sells best in kitchen".

Does it return the ASIN so I can scrape reviews next?

Yes, every product row carries asin. Feed those into an Amazon reviews run and you have the full picture: rank and price from here, customer opinion from there.

Which marketplaces are supported?

Twenty, listed in the input table. Set domain per run; the same keyword in two marketplaces should be two runs, because ranks are not comparable across them.

Can I export to CSV or Excel?

Yes. Every run writes an Apify dataset, exportable to CSV, Excel, JSON or XML from the Console, or over the API with ?format=csv.

Is there a free tier?

Empty searches, filtered rows, status rows and failed jobs are always free, so a run that finds nothing costs nothing beyond a fraction of a cent of platform compute. Apify's free plan includes monthly credit you can spend here.

How to use Amazon Search Scraper

Ready-made runs you can open and start

Each one is a saved input on the Apify Store — open it, press Start, and it runs with the fields already filled in. All 163 across the suite.

Ready-made runWhat it does
Amazon Keyword Rank Tracking for ASINsThree earbud keywords, two pages each, ads removed: the organic position of every ASIN, which is the number a listing is actually judged on.
Amazon Sponsored Products Share of PageKeep the ads in and every row is flagged sponsored or organic, so you can measure how much of a keyword page is paid before you bid on it.
Scrape Amazon Search Results to CSVTwo cookware keywords exported as a flat table: ASIN, title, page, position, price, rating and rating count, ready for CSV or a spreadsheet.
Amazon Category Bestsellers in One RunThree Amazon category charts - electronics, kitchen and beauty - pulled as ranked rows with price, rating and rating count in a single run.
Product Research Tool: Top 100 by KeywordFive pages deep on one keyword, ads removed and anything under four stars filtered out: the hundred products worth studying before you source.
Amazon Keyword Tracking on amazon.co.ukUK search results are a different ranking from the US ones: three kitchen keywords tracked on amazon.co.uk with prices in pounds.
Amazon Search Results on amazon.deGerman shoppers type German keywords: two of them run against amazon.de, returning German titles and euro prices with position on the page.
Amazon Product Data Inside a DepartmentSearching "knife" across all of Amazon returns pocket knives and toys. Scoped to the kitchen department it returns the products you meant.
Bulk Amazon Product Data, 10 KeywordsTen keywords, fifty products each: five hundred rows of ASIN, title, price and rating in one run - a category dataset rather than a rank check.
Amazon Search Without API Access, No KeyAmazon's Product Advertising API needs affiliate approval. This is the twenty-row replacement: one keyword, one page, no key, JSON out.
Amazon Bestsellers Scraper for JapanCategory charts on amazon.co.jp: the Japanese best sellers for electronics and kitchen, with yen prices and Japanese titles, fifty ranks each.

Run Amazon Search Scraper

The actor lives on the Apify Store, where the pricing tab carries the live per-row price and the input form has every field above: apify.com/kestrel/amazon-search-scraper