# Amazon Products Scraper & Price Tracker (`myth84/amazon-search-scraper`) Actor

Amazon products scraper and Amazon price tracker: scrape Amazon search results on 9 marketplaces for any keywords or search URL — price, list price, discount, coupon, rating, review count, bought in past month, badges. Track price drops between runs. One flat row per product, no personal data.

- **URL**: https://apify.com/myth84/amazon-search-scraper.md
- **Developed by:** [Flatrow Data Studio](https://apify.com/myth84) (community)
- **Categories:** E-commerce, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Amazon Products Scraper & Price Tracker – prices, ratings and price drops, no personal data

Amazon products scraper and Amazon price tracker: get Amazon prices, list prices, discounts, coupons, ratings and "bought in past month" for any keywords or search URL on 9 Amazon marketplaces, as a clean table or through an API — no login. Use it as an Amazon scraper and Amazon price monitor with price drop alerts, for competitor price monitoring, deal hunting and market research.

**No login, no cookies, no personal data:** nothing to sign in to, no cookies to paste, nothing about buyers, reviewers or third-party sellers in the output.

- **What you get:** one flat row per Amazon product for any keywords or search URL on 9 marketplaces (amazon.com, .co.uk, .de, .fr, .it, .es, .com.mx, .co.jp, .ca): price and currency, list price and discount, coupon, rating and exact number of ratings, "bought in past month", Amazon's Choice and Best Seller badges, sponsored flag, delivery, image and link; a price-tracking mode that returns only the price drops, price rises and new products since your previous run. No personal data.
- **For whom:** e-commerce brands and Amazon sellers, price-tracking and competitive-intelligence teams, deal hunters, market analysts, AI agents through MCP.
- **How much:** from $1.50 per 1,000 products on the Free plan, lower on paid plans; Apify's free monthly credit of $5 covers about 3,333 products. A fixed price per product saved and nothing else (compute and proxy traffic included, see the Pricing tab); `maxResults` caps every run.

**Sample output**: one real row from a "wireless earbuds" search on amazon.com, key columns only (the full row is under *Output example*):

```json
{
  "platformProductId": "B0HDB173YV",
  "title": "Wireless Earbuds, Bluetooth 6.0 Headphones HiFi Stereo 50H Playback LED Digital Display Ear Buds with ENC Noise Canceling Headset, IPX7 Waterproof Earphones for Gym/Running/Work（White）",
  "currency": "USD",
  "price": 19.97,
  "originalPrice": 249.99,
  "discountPercent": 92,
  "rating": 4.8,
  "reviewCount": 183,
  "isChoice": true,
  "searchRank": 1
}
```

Scrape Amazon search results for any keywords, or paste your own Amazon search URLs with their filters, and get **one flat row per product**: ASIN, title, current price, struck-through list price, typical price or former price with the discount, coupon, average rating and exact number of ratings, Amazon's "bought in past month" signal, Amazon's Choice, Best Seller and deal badges, sponsored flag, delivery wording and cost, stock warnings, number of colours, main image, whether the offer is sold by Amazon itself, and the position in the results. Sort by price or by customer review, filter by price range or department, on **amazon.com, amazon.co.uk, amazon.de, amazon.fr, amazon.it, amazon.es, amazon.com.mx, amazon.co.jp and amazon.ca**, and **track prices**: in price-monitoring mode a scheduled run returns only the new products and the price changes since your previous run, with the previous price and the difference. This Amazon scraper reads the public result pages without logging in, keeps one browsing session per search, retries the pages Amazon fails to serve, removes duplicates and stops exactly at the number of products you ask for.

**No personal data, by design.** Amazon search results carry no information about buyers; review texts and their authors are never collected, only the average rating and the number of ratings. A seller is named only when it is Amazon itself; third-party sellers, who may be private persons, are never named nor identified. Every row goes through a privacy filter before it is saved. The dataset is safe to store, share and feed to AI agents.

### What can you do with Amazon data?

- **Track Amazon prices and get price drop alerts**: price, list price, typical price, former price and coupon of a product family on one or several marketplaces. With `monitorPrices` and `onlyChanges` on, a daily schedule gives you only the price drops, price rises and new products, and you pay only for those rows.
- **Watch the competition and your own products**: rank of each ASIN for a keyword, sponsored placements, Amazon's Choice and Best Seller badges, ratings, number of ratings and monthly purchases.
- **Size a market or a niche**: price distribution, share of sponsored results, products bought more than 1,000 times last month, share of offers sold by Amazon itself.
- **Compare marketplaces and platforms** with a stable, documented schema shared by the other scrapers of this e-commerce studio (the eBay, AliExpress and Etsy scrapers use the same columns), dollars, pounds, euros and yen side by side.

### What data does Amazon Scraper extract?

Every row has every column: a value Amazon does not show in the results is `null` (or `[]` / `{}` for lists and objects), so CSV and Excel exports keep the same columns from run to run.

| Group | Columns |
|---|---|
| Identity | `schemaVersion`, `platform`, `platformProductId` (ASIN), `variantId`, `url`, `title`, `brand`, `category`, `categoryPath` |
| Prices | `currency`, `price`, `originalPrice`, `discountPercent`, `inStock`, `stockQuantity` |
| Popularity | `rating`, `ratingMax`, `reviewCount`, `soldCount`, `isBestSeller`, `isChoice`, `listedAt` |
| Seller | `storeType`, `storeName`, `storeId`, `storeUrl`, `storeRating` |
| Shipping | `shippingFree`, `shippingCost`, `deliveryEstimate`, `shipsFrom` |
| Media and attributes | `imageUrl`, `imageCount`, `attributes` |
| Search context | `isSponsored`, `searchQuery`, `searchRank`, `searchPage`, `viewCountryCode`, `scrapedAt` |
| Price monitoring | `changeType`, `previousPrice`, `priceDelta`, `priceDeltaPercent` (`null` unless `monitorPrices` is on, see *Price monitoring* below) |

Result pages show a subset of what a product page holds. For this Actor, `variantId` (every colour or size has its own ASIN), `category`, `soldCount`, `shipsFrom`, `imageCount`, `listedAt`, `storeId`, `storeUrl` and `storeRating` are always empty and `categoryPath` is `[]`; `brand` is filled only when the card shows the brand on a line of its own (some grid layouts), never guessed from the title. `reviewCount` is the exact number of ratings (46784 where the page displays "46.7K"). `originalPrice` is the struck-through price, kept only when it is above the price in the same currency; `attributes.originalPriceType` tells which one it is: `list` (list price, "List:", "RRP:", "UVP:", "Prix conseillé :", "参考:"), `typical` (Amazon's typical price, "Typical price:") or `was` (former price, "Was:", "Statt:", "Ancien :"). `storeType` is `platform` when the featured offer is sold by Amazon itself (`storeName` "Amazon") and `unknown` otherwise. `inStock` is `true` when a price is shown, `false` when the card says the product is currently unavailable, `null` otherwise; `stockQuantity` is filled from "Only 3 left in stock". `shippingFree` is `true` when the delivery line starts with free delivery (sometimes above a minimum order, as worded in `deliveryEstimate`), `false` when a delivery cost is shown (`shippingCost`). `isChoice` is `true` for an Amazon's Choice / "Overall Pick" badge, `false` when the card carries another badge, `null` without badge.

`attributes` holds the other facts of the card as flat strings, only the keys it shows: `boughtPastMonth` (lower bound of Amazon's monthly signal, "4000") and `boughtPastMonthLabel` (as displayed: "4K+ bought in past month", "300+ Mal im letzten Monat gekauft"), `badge` ("Overall Pick", "Best Seller in Yoga Mats") and `badgeType` (`amazons-choice`, `best-seller`…), `bestSellerRank` (category rank shown on amazon.co.jp, "4"), `deal` ("Limited time deal"), `coupon` ("You pay $29.99 with coupon"), `originalPriceType`, `otherOffers` ("More Buying Choices $40.76 (3 used & new offers)"), `colorOptions` (number of colours offered), `subtitle` (selling points under the title), `reviewHighlight` ("Top Reviewed for Comfort"), `prime` ("true" when the Prime logo is shown) and `searchAlias` (department of the search).

### How to scrape Amazon products

1. **Enter search keywords**, one per line ("wireless earbuds", "yoga mat"), or paste **Amazon search URLs** copied from your browser, with their filters (the URL decides the marketplace).
2. **Choose the marketplace** for the keywords: amazon.com (default), amazon.co.uk, amazon.de, amazon.fr, amazon.it, amazon.es, amazon.com.mx, amazon.co.jp or amazon.ca.
3. **Set the maximum number of products per search**, the sort order and, if needed, a price range or a department.
4. **Run** and open the **Output** tab: the *Overview*, *Prices*, *Ranking* and *Badges* views show the main columns; export everything as JSON, CSV, Excel or through the API.
5. **To track prices**, schedule the run and turn on `monitorPrices` with `onlyChanges`: every run after the first returns only what changed (see *Price monitoring* below).

### Marketplaces and local prices

The marketplace (its domain) decides the catalogue, the language of the titles and the currency. amazon.com, amazon.co.uk, amazon.de, amazon.fr, amazon.it, amazon.es, amazon.com.mx and amazon.co.jp were all served at build time; amazon.ca is supported but not verified yet (check the first rows of a run and tell us if something looks wrong).

What Amazon shows depends on the country it is seen from. amazon.com results are read from the United States. For every other marketplace, the option `localPrices` (on by default, included in the price) reads the results from the marketplace's own country, as a local visitor sees them: prices in the local currency for every product, local delivery wording and the sponsored products of that country. `viewCountryCode` says from which country each row was seen.

With `localPrices: false`, or when you set your own proxy group, country or proxy URLs, the results of a marketplace outside the US are seen from the US (or from your proxy's country): Amazon may convert prices to US dollars ("USD 12.41" on amazon.co.uk, "25,47 USD" on amazon.de, "USD 10.76" on amazon.co.jp) and hides the price of products it would not ship to that country (10 of 16 products of an amazon.de page at build time). The scraper always keeps the currency it reads in the price, never assumes one, and asks Amazon for the marketplace currency, which brings it back on most pages.

### Input

Give at least one keyword in `searchQueries` or one URL in `startUrls` (with nothing at all, "wireless earbuds" is searched). Field names and defaults are those of the input form.

The input of our validation run: the first 60 products for "wireless earbuds" on amazon.com in Amazon's featured order (every other field keeps its default):

```json
{
  "searchQueries": [
    "wireless earbuds"
  ],
  "marketplace": "US",
  "sortBy": "relevance",
  "maxResults": 60
}
```

Every field, with its type and default:

| Field | Type | Default | Description |
|---|---|---|---|
| `searchQueries` | string\[] | `["wireless earbuds"]` | Search keywords, one search per entry, as typed in the Amazon search box. |
| `startUrls` | string\[] | `[]` | Amazon search URLs (`/s?k=...`, with your filters) copied from your browser, on any supported marketplace; the URL decides the marketplace, its filters are kept, the sort order, price range and department below are applied on top only when set. |
| `marketplace` | string | `"US"` | `US` (amazon.com), `UK` (amazon.co.uk), `DE`, `FR`, `IT`, `ES`, `MX` (amazon.com.mx), `JP` (amazon.co.jp) or `CA` (amazon.ca, not verified yet). Used for keyword searches; a URL keeps its own marketplace. |
| `maxResults` | integer | `100` | Stop each search after this many unique products (1 to 2,000). You are never charged for more. The form is prefilled with 20 for a quick first run. |
| `sortBy` | string | `"relevance"` | `relevance` (Amazon's featured order), `price_low`, `price_high` or `avg_review` (average customer review), all validated; `newest` (newest arrivals) and `popularity` (best sellers) use Amazon's URL parameters and are not verified yet. |
| `priceMin` | number | — | Minimum price in the marketplace currency, e.g. `20` (Amazon's own filter, which lets a few products outside the range through). |
| `priceMax` | number | — | Maximum price in the marketplace currency, e.g. `50`, at least `priceMin` (same filter as `priceMin`). |
| `department` | string | — | Amazon department alias, as in the `i=` parameter of its search URLs: `electronics`, `office-products`, `kitchen`… Empty: all departments. |
| `includeSponsored` | boolean | `true` | Keep the sponsored products mixed into the results (flagged in `isSponsored`) or skip them; skipped products are not counted in `searchRank`. |
| `localPrices` | boolean | `true` | For a marketplace other than amazon.com, read the results from that country: local currency and every price (see *Marketplaces and local prices*). Applies with the default proxy configuration; no effect on amazon.com. |
| `maxPages` | integer | `20` | Safety cap on result pages read per search (Amazon shows 20 at most). |
| `monitorPrices` | boolean | `false` | Track prices: compare every product with the previous run of the same search (by ASIN and marketplace) and fill `changeType`, `previousPrice`, `priceDelta`, `priceDeltaPercent`. `maxResults` then counts the products compared per search. |
| `onlyChanges` | boolean | `false` | With `monitorPrices`: return and charge only the new products and the price changes; a run without any change succeeds with an empty dataset. Off: every compared product with its `changeType`. |
| `monitorStoreName` | string | `"amazon-price-monitor"` | Key-value store of your account that keeps the previous prices (one record per search). One name per schedule when two schedules run the same search with different settings; letters, digits and dashes. |
| `proxyConfiguration` | object | `{"useApifyProxy":true}` | The default (Apify Proxy, automatic group, no country) is the configuration validated for Amazon and its traffic is included in the price: keep it. Your own proxy group, country or URLs are accepted and turn `localPrices` off. |
| `maxRequests` | integer | `600` | Safety cap on page requests in one run, all searches and attempts included. |
| `maxAttemptsPerPage` | integer | `5` | Amazon answers some requests with a temporary error page: the page is retried at once, each time as a new visitor, up to this many attempts (1 to 10), plus one last attempt per search. |
| `delayMs` | integer | `1000` | Pause between two page requests of the same search, in milliseconds. |
| `debugStoreHtml` | boolean | `false` | Debugging only: store every fetched result page in the key-value store (0.5 to 2 MB each). |

### Output example

One real row, produced by the Actor from a "wireless earbuds" search on amazon.com (the first product of the results page). All columns are present, in this order, for every product:

```json
{
  "schemaVersion": "ecommerce-product/1.1",
  "platform": "amazon",
  "platformProductId": "B0HDB173YV",
  "variantId": null,
  "url": "https://www.amazon.com/dp/B0HDB173YV",
  "title": "Wireless Earbuds, Bluetooth 6.0 Headphones HiFi Stereo 50H Playback LED Digital Display Ear Buds with ENC Noise Canceling Headset, IPX7 Waterproof Earphones for Gym/Running/Work（White）",
  "brand": null,
  "category": null,
  "categoryPath": [],
  "currency": "USD",
  "price": 19.97,
  "originalPrice": 249.99,
  "discountPercent": 92,
  "inStock": true,
  "stockQuantity": null,
  "rating": 4.8,
  "ratingMax": 5,
  "reviewCount": 183,
  "soldCount": null,
  "storeType": "unknown",
  "storeName": null,
  "storeId": null,
  "storeUrl": null,
  "storeRating": null,
  "shippingFree": true,
  "shippingCost": null,
  "deliveryEstimate": "FREE delivery Mon, Oct 26 on $35 of items shipped by Amazon",
  "shipsFrom": null,
  "imageUrl": "https://m.media-amazon.com/images/I/61lW-nQhWIL.jpg",
  "imageCount": null,
  "attributes": {
    "boughtPastMonth": "4000",
    "boughtPastMonthLabel": "4K+ bought in past month",
    "badge": "Overall Pick",
    "badgeType": "amazons-choice",
    "originalPriceType": "typical",
    "colorOptions": "4"
  },
  "isSponsored": false,
  "isBestSeller": false,
  "isChoice": true,
  "listedAt": null,
  "searchQuery": "wireless earbuds",
  "searchRank": 1,
  "searchPage": 1,
  "viewCountryCode": "US",
  "scrapedAt": "2026-10-20T00:00:00.000Z",
  "changeType": null,
  "previousPrice": null,
  "priceDelta": null,
  "priceDeltaPercent": null
}
```

`price` is the price of the featured offer displayed in the results, delivery not included; `originalPrice` is the struck-through price ($249.99 here, Amazon's "Typical price"), `discountPercent` the percentage off computed from it (one decimal). "4K+ bought in past month" is a monthly lower bound, kept in `attributes.boughtPastMonth`, not a sales total: `soldCount` stays `null`. The last four columns are filled in price-monitoring runs only (see *Price monitoring* below).

The **Output** tab offers five views of the same rows: **Overview** (title, price, currency, struck price, discount, rating, ratings, Amazon's Choice, best seller, sponsored, link, image), **Prices** (ASIN, price, struck price, discount, currency, in stock, delivery, seller kind, attributes, country seen from, link), **Ranking** (query, page, rank, sponsored flag, rating, ratings, price) **Badges** (Amazon's Choice, best seller and sponsored flags, attributes with the badge text, deals and monthly purchases) and **Changes** (price-monitoring runs: change type, price, previous price, difference in money and in percent, struck price, discount, ASIN, query, link).

### Price monitoring

Turn on `monitorPrices` and `onlyChanges`, then **schedule the run** (daily is typical): the Actor becomes an Amazon price tracker that sends you the price drops. It keeps the last displayed price of every product it compared in a key-value store of your account (`monitorStoreName`, `amazon-price-monitor` by default), with one record per search (same keywords or URL, marketplace, sort order, price range and department, and the country the prices are seen from); a product is identified by its ASIN and its marketplace. The first run of a search is the reference: every product comes back with `changeType` = `"new"` (and `RUN_STATS.monitorBaseline` is true). From the second run on, with `onlyChanges` the dataset holds **only the new products and the products whose price changed**, with the previous price and the difference, and **only those rows are charged**; a run where nothing changed succeeds with an empty dataset. Without `onlyChanges`, every compared product is returned with its `changeType` (`new`, `price_changed` or `unchanged`). In both cases `maxResults` is the number of products compared per search.

A scheduled input that watches the 100 first "wireless earbuds" results of amazon.com, cheapest first:

```json
{
  "searchQueries": ["wireless earbuds"],
  "marketplace": "US",
  "sortBy": "price_low",
  "maxResults": 100,
  "monitorPrices": true,
  "onlyChanges": true,
  "monitorStoreName": "earbuds-daily"
}
```

A `price_changed` row, as the Actor produces it from the row of the output example when the previous run had recorded 21.99 USD (the other columns are the same as above):

```json
{
  "platformProductId": "B0HDB173YV",
  "title": "Wireless Earbuds, Bluetooth 6.0 Headphones HiFi Stereo 50H Playback LED Digital Display Ear Buds with ENC Noise Canceling Headset, IPX7 Waterproof Earphones for Gym/Running/Work（White）",
  "currency": "USD",
  "price": 19.97,
  "changeType": "price_changed",
  "previousPrice": 21.99,
  "priceDelta": -2.02,
  "priceDeltaPercent": -9.2
}
```

What to know before relying on it:

- **The record is written only after a search that ended cleanly.** A failed or empty search, a page given up after Amazon's temporary errors, a run stopped by its budget or an interrupted run never overwrites the reference, so a bad day cannot erase your prices; the log says when a record was kept unchanged (`RUN_STATS.monitor` counts the records written and skipped).
- **Prices are compared as displayed, in the same currency.** The price of the featured offer is what gets compared, delivery and coupon excluded (a new coupon shows in `attributes.coupon`, not as a price change). A product shown without a price (no featured offer, or not delivered to that country) is reported `unchanged` and keeps its last known price, so that a price that comes back lower is reported as a drop. A product seen in another currency is reported `unchanged` and the new currency becomes the reference. Searches read with and without `localPrices` have separate records, because Amazon shows different prices to visitors of different countries.
- **Rankings move.** Amazon reorders its results between sessions, so the set of compared products (the first `maxResults` of each search) drifts a little from run to run; a product that drops out of the results and comes back later is not reported as new (its last price is kept for 90 days). Sort by price or use a narrow search or a price range to get a stable set.
- **Several searches in one run.** Each search compares its own products, so a product found by two searches of the run is recorded in both; it is written to the dataset (and charged) only once per marketplace (`RUN_STATS.extra.monitorDuplicatesNotWritten`).
- **One store per schedule when searches collide.** Runs sharing a `monitorStoreName` share the records: two schedules with the same keywords, marketplace, sort and filters would overwrite each other's reference, so give them different store names. Changing the keywords, marketplace, sort or filters of a search starts a new reference for it. Delete the key-value store in Apify Console to start over.

### How much does it cost to scrape Amazon?

This Actor uses **pay-per-event pricing: you pay a fixed price per product** saved to your dataset, and nothing else. On the Free plan, products cost $1.50 per 1,000, so Apify's free monthly credit of $5 covers about 3,333 products; paid plans pay less per product, and the price of every plan tier is on the **Pricing tab** of this page.

| What you pay for | How it is counted | Price |
|---|---|---|
| `result` event: one product saved to your dataset | once per unique product of the run, capped by `maxResults` | Pricing tab, per plan tier |
| Run start | a symbolic amount, once per run | Pricing tab |
| Compute, proxies (local prices included), retries, storage and data transfer | included: no platform usage is passed on to you | — |

The cost of a run is known before you start: 1,000 products cost 1,000 times the `result` price of your tier, whatever the number of pages fetched or retried. In price-monitoring runs with `onlyChanges`, only the new products and the price changes are charged. A page of 16 products (48 to 60 in grid layout) takes 2 to 4 seconds plus the pause between pages: 100 products in about half a minute, a full search of about 320 products in one to two minutes.

### Limits and behaviour worth knowing

- **Search results only.** The Actor reads result pages, not product pages: bullet points, specifications, best-seller rank of the product page, buy-box seller, every variant's price and customer reviews are not available (see the column notes above). Product pages, reviews (behind Amazon's login), seller profiles and best-seller lists are out of scope.
- **At most 20 result pages per search.** Amazon shows 20 result pages for a search at most: about 320 products in list layout (16 per page), 336 to 420 in grid layout (7 pages of 48 to 60 products), fewer for a narrow search. The scraper stops at Amazon's last page, when two consecutive pages bring nothing new, or at `maxResults` / `maxPages`, and removes duplicates by ASIN across the whole run (`RUN_STATS.extra.duplicatesSkipped`). Run several related keywords or search URLs to go further.
- **No postal code.** Delivery dates, delivery costs and, for some products, availability depend on the delivery address; the scraper reads the results without an address or a postal code (Amazon then uses a default location of the country the results are seen from).
- **Sponsored products.** Amazon mixes sponsored products into the results; they are flagged in `isSponsored`, counted in `RUN_STATS.extra.sponsoredSeen` and can be skipped with `includeSponsored`.
- **Temporary error pages.** Amazon answers part of the requests with a temporary error page (HTTP 503, more often on page 1): the scraper retries such a page at once as a new visitor, up to `maxAttemptsPerPage` attempts, then gives that search up and reports it in the log. `RUN_STATS.extra.attemptsTotal`, `http503`, `pagesNeedingRetry` and `maxAttemptsUsed` show how often it happened; you never pay for the retries.
- **Prices that are not shown.** Products without a featured offer, or not delivered to the country the results are seen from, have no price on the result page: `price` and `currency` are `null` (`RUN_STATS.extra.cardsWithoutPrice`). See *Why are some prices missing?* below.
- **Not verified yet.** amazon.ca was not served at build time, and the `newest` and `popularity` sort orders use Amazon's public URL parameters without having been exercised: they are marked as such in the input form and confirmed at the first runs. Check the first rows if you rely on them.
- **No empty successes.** A run that finds no product ends as failed with an explicit message (keywords misspelt, price range too strict, Amazon's error page to every attempt, or a proxy configuration error), so that your schedules and integrations notice. The one exception is a price-monitoring run that compared products and found no change: it succeeds with an empty dataset.

### Integrations and API

Start the Actor from Apify Console, schedule it, or call it from the [Apify API](https://docs.apify.com/api/v2) with any language (the **API** tab shows ready-made code for Node.js, Python and curl). Webhooks notify your systems when a run finishes; the dataset can be pulled as JSON, CSV, Excel, XML or RSS, or pushed to Google Sheets, Make, Zapier, n8n, Slack, Airtable, Google Drive and more through the Apify integrations.

### Use it from your AI assistant

Add this Actor as a tool to Claude, ChatGPT, Cursor, VS Code or any MCP client with the Apify MCP server URL below (sign in with your Apify account when asked):

`https://mcp.apify.com?tools=myth84/amazon-search-scraper`

Then ask in plain words. Copy this prompt and change the details:

```text
Use myth84/amazon-search-scraper to track the prices of the 30 cheapest wireless earbuds on amazon.com and tell me which ones dropped since my last check. Input: {"searchQueries": ["wireless earbuds"], "marketplace": "US", "sortBy": "price_low", "maxResults": 30, "monitorPrices": true, "onlyChanges": true, "monitorStoreName": "earbuds-watch"}. The first run records the prices; from the second run on, show the title, price, previous price, change and link of each product.
```

### For AI agents (MCP)

Through the [Apify MCP server](https://docs.apify.com/mcp) this Actor is a tool that answers questions such as *"what do the best-rated air fryers under 100 dollars cost on Amazon right now?"*, *"which wireless earbuds carry Amazon's Choice on amazon.de, and at what price in euros?"* or *"which of these products got cheaper on Amazon since yesterday?"*.

**Minimal input** (every other field keeps its default; raise `maxResults` only when the question needs more rows):

```json
{
  "searchQueries": [
    "air fryer"
  ],
  "marketplace": "US",
  "priceMax": 100,
  "sortBy": "avg_review",
  "maxResults": 20
}
```

- **Key output fields**: `platformProductId` (ASIN), `title`, `url`, `price`, `currency`, `originalPrice`, `discountPercent`, `rating`, `reviewCount`, `isChoice`, `isBestSeller`, `isSponsored`, `storeType`, `attributes.boughtPastMonth`, `attributes.coupon`, `searchRank`, `viewCountryCode`; in price-monitoring runs `changeType`, `previousPrice`, `priceDelta`, `priceDeltaPercent`. Every column is always present, in a fixed order; `null` means Amazon did not show the value. The full list is in *What data does Amazon Scraper extract?* above.
- **Use it when** you need current Amazon search results for keywords on one of the 9 marketplaces: prices, struck prices, discounts, coupons, ratings, numbers of ratings, monthly purchases, badges, sponsored flags, images. Pass `searchQueries` (or `startUrls`), `marketplace`, optionally `sortBy`, `priceMin` / `priceMax`, `department`, and a small `maxResults` (16 to 60 is enough for an answer and fits in one to four pages). To report price changes between two calls, pass `monitorPrices: true`, `onlyChanges: true` and a stable `monitorStoreName`.
- **Do not use it for** product details (bullet points, specifications, buy box), customer reviews, seller information, best-seller lists, prices for a given postal code or anything behind a login: it only reads public search results and collects no personal data.
- **Cost per 1,000 results**: 1,000 `result` events, $1.50 per 1,000 on the Free plan and less on paid plans (Pricing tab); nothing else is charged (in price-monitoring runs with `onlyChanges`, unchanged prices are free).
- **Typical time**: 2 to 4 seconds per page of 16 products, pause and retries included: 20 products in a few seconds, a few hundred in one to two minutes.

### Alternatives and switching

- **Official APIs.** Amazon's own product APIs are reserved to registered affiliates or sellers and need an account and access keys. This Actor reads what any visitor sees in Amazon search results (public prices, struck prices, coupons, ratings, badges, sponsored flags) with no account, no keys and no approval.
- **Your own scraper.** Nothing to build or maintain: sessions, retries of Amazon's temporary error pages, pagination, deduplication, local currencies and Amazon page changes are handled for you. The columns stay the same from run to run, a run that finds nothing fails with an explicit message instead of succeeding empty, and a scheduled test run catches Amazon changes early.
- **Another scraper from the Store.** The input names differ from one Actor to the next; the usual ones map to this Actor as follows:

| Usual input | Here | Note |
|---|---|---|
| `search`, `query`, `keyword` | `searchQueries` | Several keywords per run |
| `startUrls`, `searchUrls` | `startUrls` | Amazon search URLs, filters included |
| `maxItems`, `limit` | `maxResults` | Unique products per search, never charged beyond |
| `country`, `domain` | `marketplace` | `US`, `UK`, `DE`, `FR`, `IT`, `ES`, `MX`, `JP`, `CA` |
| `sort` | `sortBy` | `relevance`, `price_low`, `price_high`, `avg_review`, `newest`, `popularity` |
| `minPrice`, `maxPrice` | `priceMin`, `priceMax` | In the marketplace currency |
| `category` | `department` | Amazon department alias such as `electronics` |
| `proxy` | `proxyConfiguration` | Keep the default: proxies are included in the price |

### FAQ

#### Does Amazon Scraper collect personal data?

No. Amazon search results carry no buyer information, and the scraper never collects review texts or their authors (only the average rating and the number of ratings). A seller is named only when it is Amazon itself; third-party sellers are never named nor identified, because a seller may be a private person. Every row goes through a privacy filter before it is saved.

#### Is it legal to scrape Amazon?

The Actor only reads search results that Amazon serves to any visitor without an account, and it stores no personal data. Scraping public data is generally lawful, but Amazon's conditions of use restrict automated access, and you are responsible for how you use the results and for complying with the laws that apply to you (including copyright on product texts and images). Use the data for analysis, not to republish Amazon's catalogue.

#### Which Amazon marketplaces are supported?

Nine: amazon.com (USD), amazon.co.uk (GBP), amazon.de, amazon.fr, amazon.it and amazon.es (EUR), amazon.com.mx (MXN), amazon.co.jp (JPY) and amazon.ca (CAD). All were served at build time except amazon.ca, which is supported but not verified yet. Choose one with `marketplace` for keyword searches, or paste search URLs of any of them in `startUrls`.

#### Why are some prices missing?

Amazon shows no price on the result page for a product without a featured offer (only "See options" or "No featured offers available": the other offers are summarised in `attributes.otherOffers`), and it hides the price of products it would not deliver to the country the results are seen from. Keep `localPrices` on (the default) for the marketplaces outside the US so that the results are seen from the marketplace's own country; on amazon.com a few products of each page have no featured offer. `RUN_STATS.extra.cardsWithoutPrice` counts them.

#### What do `price`, `originalPrice` and `attributes.originalPriceType` mean?

`price` is the current price of the featured offer, delivery excluded, in `currency`. `originalPrice` is the struck-through price next to it, kept when it is higher, and `discountPercent` the percentage off. `attributes.originalPriceType` says which reference Amazon used: `list` (the list or recommended price), `typical` (Amazon's "Typical price", the usual price of recent months) or `was` (the former price). A coupon on top of the price is in `attributes.coupon` ("You pay $29.99 with coupon").

#### Is "bought in past month" the number of sales?

It is Amazon's own rounded monthly signal ("4K+ bought in past month", "300+ Mal im letzten Monat gekauft"): `attributes.boughtPastMonth` keeps its lower bound (4000, 300) and `attributes.boughtPastMonthLabel` the wording. It is not a sales total, so `soldCount` stays `null`. Amazon shows it only for products bought often enough.

#### Can I use my own search URL with filters?

Yes. Run a search on Amazon, apply the filters you need (brand, rating, Prime, department…), copy the URL from your browser and paste it into `startUrls`: its filters are kept, the URL decides the marketplace, and the scraper pages through the results. The sort order, price range and department of the input are added on top only when you set them.

#### Why do I get fewer products than Amazon announces?

Amazon announces thousands of results but shows at most 20 result pages per search, about 320 products in list layout or 336 to 420 in grid layout. Products repeated across pages are removed. Run several related keywords, sort orders or price ranges to collect more products of a category.

#### How often should I run it, and how do I get only price changes?

Every run fetches live result pages. Prices, coupons and rankings change by the hour, so schedule the Actor as often as your use case needs (daily is typical for price tracking) and compare runs by `platformProductId`, `viewCountryCode` and `currency`, or let the Actor compare them for you: turn on `monitorPrices` and `onlyChanges`, keep the default `monitorStoreName` (or one per schedule) and schedule the run. The first run records every product of the search and returns it as `new`; each later run returns only the products that appeared since and the products whose displayed price changed, with `previousPrice`, `priceDelta` and `priceDeltaPercent`, and charges only those rows. A run without any change succeeds with an empty dataset. Keep the same keywords, marketplace, sort, price range and department from run to run. Turn `onlyChanges` off to get every product with its `changeType`.

#### How do I export or integrate the results, and where do I get support?

From the run's Output tab (JSON, CSV, Excel, XML, RSS) or automatically: Apify API, webhooks, scheduled runs and integrations with Google Sheets, Make, Zapier, n8n, Slack and others; AI agents can call the Actor through the Apify MCP server. For bugs or questions, open an issue in the **Issues** tab of this Actor with your run id and input: page-layout changes are fixed as a priority, and feature requests (product pages, other marketplaces, postal codes) are welcome.

### More scrapers by Flatrow Data Studio

The e-commerce scrapers of the studio share the same columns, so products from several marketplaces land in one comparable table:

- [eBay Listings Scraper & Price Tracker](https://apify.com/myth84/ebay-search-scraper): eBay prices, condition, shipping and units sold on 9 marketplaces, with price monitoring.
- [AliExpress Products Scraper & Price Tracker](https://apify.com/myth84/aliexpress-search-scraper): AliExpress prices, discounts, units sold and shipping for any keywords and delivery country, with price-drop alerts.
- [Etsy Listings Scraper & Price Tracker](https://apify.com/myth84/etsy-search-scraper): Etsy prices, sale prices, ratings and review counts for any common search term, with price monitoring.

Did this scraper give you the data you needed? A rating on its Store page helps other people find it. For a bug or a missing field, open an issue in the **Issues** tab.

### Legal note

This Actor reads publicly available Amazon search results without logging in and collects no personal data. You are responsible for your use of the data and for complying with Amazon's conditions of use and the laws that apply to you.

Not affiliated with, endorsed or sponsored by Amazon. Amazon is a trademark of Amazon.com, Inc. or its affiliates.

# Changelog

This Actor's version history is a separate document: https://apify.com/myth84/amazon-search-scraper/changelog.md

# Actor input Schema

## `searchQueries` (type: `array`):

Enter one search per line, as you would type it in the Amazon search box, e.g. <code>wireless earbuds</code> or <code>yoga mat</code>. Each search gets its own results, up to the maximum number of products below. Default <code>wireless earbuds</code>: only for runs started without any keyword or URL (the form is prefilled with it); a run with URLs only searches just those URLs.

## `startUrls` (type: `array`):

Paste one or more Amazon search result URLs copied from your browser, e.g. <code>https://www.amazon.com/s?k=yoga+mat</code>, with any filters you applied on the page, on any marketplace below. Their filters are kept and the URL decides the marketplace; the sort order, price range and department below are applied on top only when you set them. Product pages (<code>/dp/...</code>) are not search URLs. Default empty: keywords are enough.

## `marketplace` (type: `string`):

Amazon marketplace to search for keywords: it decides the catalogue, the language of the titles and the currency. All of them were served at build time except amazon.ca, which is not verified yet. A URL in the field above always uses its own marketplace. Default US: amazon.com in USD, the marketplace of our daily check.

## `maxResults` (type: `integer`):

Stop each search (keywords or URL) after this many unique products; you are never charged for more. Amazon shows at most 20 result pages per search: about 320 products in list layout (16 per page) and 336 to 420 in grid layout (7 pages of 48 to 60). Default 100: the top of a search in about 2 to 7 pages; the form is prefilled with 20 for a quick first run.

## `sortBy` (type: `string`):

Order of the results. Featured (Amazon's default), price low to high, price high to low and average customer review were validated at build time; newest arrivals and best sellers use Amazon's public URL parameters and are not verified yet. Default relevance: Amazon's featured order, the one a shopper sees first.

## `priceMin` (type: `number`):

Keep only products priced at least this amount, in the marketplace currency, e.g. <code>20</code> for 20 USD on amazon.com (Amazon's own filter, which lets a few products outside the range through). Leave empty for no minimum.

## `priceMax` (type: `number`):

Keep only products priced at most this amount, in the marketplace currency, e.g. <code>50</code> for 50 USD on amazon.com (Amazon's own filter); it must be at least the min price. Leave empty for no maximum.

## `department` (type: `string`):

Optional Amazon department alias to search in, as in the <code>i=</code> parameter of Amazon's search URLs: <code>electronics</code>, <code>office-products</code>, <code>kitchen</code>, <code>beauty</code>, <code>toys-and-games</code>… (letters, digits, dashes and underscores). Leave empty to search all departments.

## `includeSponsored` (type: `boolean`):

Amazon mixes sponsored products into the results (several per page). Keep them (they are flagged in the isSponsored column) or skip them; skipped products are not counted in searchRank. Default on: they are real offers, and searchRank then counts every product shown.

## `localPrices` (type: `boolean`):

For a marketplace other than amazon.com, read the results as a visitor of that country sees them: local currency and the prices of every product. Seen from another country, Amazon converts prices and hides those of products it would not deliver there. Applies only with the default proxy configuration; no effect on amazon.com. Default on: the prices a local shopper sees, proxy traffic included in the price.

## `maxPages` (type: `integer`):

Safety cap on the number of result pages read for one search (Amazon shows 20 at most). The scraper also stops at Amazon's last page, at maxResults, or when two consecutive pages bring no new product. Default 20: Amazon's own limit, so the cap never cuts a search short.

## `monitorPrices` (type: `boolean`):

On: every product is compared with the previous run of the same search, by ASIN and marketplace, and maxResults becomes the number of products compared per search. Default off: a plain search, every product is returned and the four monitoring columns stay null.

## `onlyChanges` (type: `boolean`):

With price monitoring on: return and charge only the new products and the products whose price changed since the previous run; a run without any change succeeds with an empty dataset. Recommended for scheduled runs. Default off: every compared product is returned with its changeType (new, price_changed, unchanged).

## `monitorStoreName` (type: `string`):

Name of the key-value store, in your account, that keeps the previous prices when price monitoring is on (one record per search), e.g. <code>earbuds-daily</code>. Runs sharing a name share the records; use one name per schedule when two schedules run the same search with different settings. Letters, digits and dashes only, at most 63 characters; upper case is lowered. Default amazon-price-monitor: one store holds every search.

## `proxyConfiguration` (type: `object`):

Proxy used for the requests to Amazon. Do not set a proxy country: the marketplace is chosen by its domain and Local prices picks the country. You can also provide your own proxy group, country or URLs; they turn Local prices off. Default: Apify proxy, automatic datacenter group, the configuration validated for Amazon, its traffic included in the price.

## `maxRequests` (type: `integer`):

Safety cap on the number of page requests in one run, all searches and attempts included. Default 600: 30 searches of 20 pages without retries, far above a usual run; raise it for a long list of searches.

## `maxAttemptsPerPage` (type: `integer`):

Amazon answers some requests with a temporary error page: the scraper then retries the page at once, each time as a new visitor, up to this many attempts (plus one last attempt per search) before giving the search up. Default 5: about one attempt in four got that page at build time, and five attempts make an unread page rare.

## `delayMs` (type: `integer`):

Pause between two page requests of the same search, in milliseconds; 0 disables the pause. Default 1000: a polite pace of at most one page per second for each search.

## `debugStoreHtml` (type: `boolean`):

Debugging only: save every fetched result page in the run's key-value store. Answers weigh 0.5 to 2 MB: slows the run down and uses storage. Default off: not needed to get the rows.

## Actor input object example

```json
{
  "searchQueries": [
    "wireless earbuds"
  ],
  "startUrls": [],
  "marketplace": "US",
  "maxResults": 20,
  "sortBy": "relevance",
  "includeSponsored": true,
  "localPrices": true,
  "maxPages": 20,
  "monitorPrices": false,
  "onlyChanges": false,
  "monitorStoreName": "amazon-price-monitor",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxRequests": 600,
  "maxAttemptsPerPage": 5,
  "delayMs": 1000,
  "debugStoreHtml": false
}
```

# Actor output Schema

## `products` (type: `string`):

All extracted products as dataset items, one flat row per product. Append ?format=csv or ?format=xlsx for spreadsheets. The Overview view is selected by default; Prices, Ranking and Badges views are also available.

## `runStats` (type: `string`):

Requests and attempts per page, HTTP 503 answers, bytes transferred, products seen (sponsored, repeated and price-less ones counted), products pushed and the estimated platform cost of the run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "wireless earbuds"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("myth84/amazon-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["wireless earbuds"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("myth84/amazon-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "wireless earbuds"
  ],
  "maxResults": 20
}' |
apify call myth84/amazon-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,myth84/amazon-search-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/4Ka5PtdhE9wnWVkPj/builds/fxlPUxjolVEiCcnWS/openapi.json
