# Amazon Search Scraper (`steadyscrape/amazon-search-scraper`) Actor

Amazon search results for any keyword or search link on 20+ marketplaces: organic and sponsored position, ASIN, title, price, list price, rating, reviews, badges (Best Seller, Amazon's Choice), bought in past month, Prime and delivery, coupons, deals. No login, pay per product.

- **URL**: https://apify.com/steadyscrape/amazon-search-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** E-commerce, SEO tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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.

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 Search Scraper

Amazon **search results** for any keyword or Amazon search link, on amazon.com and 20+ other marketplaces, as a shopper sees them: **position on the page and across pages, organic position, sponsored or not**, ASIN, title, brand, price, struck-through list price, rating, review count, badges (**Best Seller** with its category, **Amazon's Choice / Overall Pick**, "Top Reviewed for…"), "**10K+ bought in past month**", Prime and delivery lines, coupons, deals, color and size options, image and link. **Every search you ask for comes back**: when Amazon has nothing the row says why (`no_results`, `invalid`, `blocked`) instead of an empty dataset. You pay only for products read.

No browser, no login, no API key: it reads the results pages Amazon serves to a desktop browser, page after page, and moves to another IP (datacenter, then residential in the marketplace's country) when Amazon's bot check shows up. It never solves a CAPTCHA or a challenge.

### What you get

One row per product card per results page:

- **Where it ranks**: `position` (1, 2, 3… across pages, sponsored cards included, as a shopper scrolls), `organicPosition` (the same count without ads; `null` for an ad), `sponsored`, `page`, `positionOnPage`.
- **The product**: `asin`, `title`, `subtitle` (the author line of a book, or the grey second half of a long title), `brand` (printed above the title in fashion and some other departments), `format` ("Paperback", "Kindle", "Audiobook"), `url` (`https://www.amazon.com/dp/<ASIN>`), `image` (the original picture, not the thumbnail).
- **The price**: `price`, `currency`, `priceText` as written ("$19.97", "R$ 109,90", "₹866"), `listPrice` with `listPriceLabel` as the site labels the struck-through price ("List", "Typical price", "Was", "RRP", "M.R.P"), `unitPrice` ("($0.50/count)"), `priceNote` ("Exclusive Prime price", "Click to see price", "Free with Audible trial"), `coupon` ("You pay $34.99 with coupon"), `deal` ("Limited time deal").
- **Reviews and demand**: `rating` (4.8), `reviewCount` (16708, the exact count, not "16.7K"), `boughtPastMonthText` ("10K+ bought in past month") and `boughtPastMonth` (10000, the floor Amazon states).
- **Badges**: `badges` as printed (`["Best Seller"]`, `["Overall Pick"]`, `["Amazon's Choice"]`, `["Top Reviewed for Battery life"]`), `bestSeller` with `bestSellerCategory` ("Earbud & In-Ear Headphones"), `amazonsChoice`.
- **Delivery**: `prime` (the card offers Prime delivery), `delivery` ("Join Prime to get FREE delivery Tomorrow, Oct 20") and `deliveryAlternative` ("Or fastest delivery…", "Or Non-members get FREE delivery…").
- **Options**: `colorOptions` (swatches plus their "+5"), `variations` ("Options: 3 sizes"), `otherOffers` ("More Buying Choices $183.44 (7+ used & new offers)").
- **The search**: `input` (the line as you gave it), `keyword`, `marketplace`, `department`, `sort`, `searchUrl`, `totalResultsText` ("over 20,000") and `totalResults` (20000), `scrapedAt`.
- **`status` and `reason`**: `ok`; `no_results` (Amazon shows nothing for the keyword, or only ads); `invalid` (the line is neither a keyword nor an Amazon search link); `blocked` (every IP route was refused; unpaid).

### Input

| field | what it does |
|---|---|
| `keywords` | One search per line: a keyword (`wireless earbuds`) or a link to any Amazon search results page, taken as it is with its own marketplace, department, sort and filters. **Any filter Amazon offers works**: set a price range, brand, rating or Prime on Amazon and paste the link. |
| `marketplace` | Where keywords are searched: `com` (default), `ca`, `com.mx`, `com.br`, `co.uk`, `de`, `fr`, `it`, `es`, `nl`, `se`, `pl`, `com.tr`, `co.jp`, `in`, `com.au`, `sg`, `ae`, `sa`, `eg`, `com.be`, `ie`. |
| `department` | Optional: the alias Amazon puts after `i=` in a search link (`electronics`, `stripbooks` for Books, `digital-text` for Kindle, `fashion`, `beauty`, `garden` for Home & Kitchen, `sporting`, `toys-and-games`…). Empty: all departments. |
| `sort` | `relevance` (default), `price-asc`, `price-desc`, `rating`, `newest`, `best-sellers`: Amazon's own "Sort by" menu. |
| `maxResultsPerSearch` | Stop each search after this many product rows. Default 100. |
| `maxPagesPerSearch` | The most results pages per search. Default 5, up to 50. Amazon shows 16 to 60 cards a page and usually ends a search at 7 pages of 48 or 20 of 16. |
| `includeSponsored` | Default on: ads come back flagged `sponsored: true`. Off: they are left out and not charged, while `position` still counts them, so it matches what a shopper sees. |
| `residentialFallback` | Retry through residential proxies of the marketplace's country when Amazon refuses the datacenter IPs. Default on, included in the price. |

```json
{
    "keywords": ["wireless earbuds", "yoga mat", "https://www.amazon.co.uk/s?k=desk+lamp&s=review-rank"],
    "marketplace": "com",
    "sort": "relevance",
    "maxResultsPerSearch": 100,
    "includeSponsored": true
}
```

### Output example

```json
{
    "status": "ok",
    "reason": null,
    "input": "wireless earbuds",
    "keyword": "wireless earbuds",
    "marketplace": "com",
    "department": null,
    "sort": "relevance",
    "searchUrl": "https://www.amazon.com/s?k=wireless+earbuds",
    "totalResultsText": "over 20,000",
    "totalResults": 20000,
    "page": 1,
    "positionOnPage": 2,
    "position": 2,
    "organicPosition": 2,
    "sponsored": false,
    "asin": "B0FQFB8FMG",
    "title": "Apple AirPods Pro 3 Wireless Earbuds with Active Noise Cancellation",
    "subtitle": "Live Translation, Heart Rate Sensing, Hearing Aid Feature, Bluetooth Headphones, Spatial Audio, USB-C Charging",
    "brand": null,
    "url": "https://www.amazon.com/dp/B0FQFB8FMG",
    "image": "https://m.media-amazon.com/images/I/61solmQSSlL.jpg",
    "format": null,
    "price": 199,
    "priceText": "$199.00",
    "currency": "USD",
    "listPrice": 249,
    "listPriceLabel": "List",
    "unitPrice": null,
    "priceNote": null,
    "coupon": null,
    "deal": null,
    "rating": 4.4,
    "reviewCount": 16708,
    "boughtPastMonthText": "10K+ bought in past month",
    "boughtPastMonth": 10000,
    "badges": ["Best Seller"],
    "bestSeller": true,
    "bestSellerCategory": "Earbud & In-Ear Headphones",
    "amazonsChoice": false,
    "prime": true,
    "delivery": "Join Prime to get FREE delivery Tomorrow, Oct 20",
    "deliveryAlternative": "Or Non-members get FREE delivery Sat, Oct 24",
    "colorOptions": null,
    "variations": null,
    "otherOffers": "More Buying Choices $183.44 (7+ used & new offers)",
    "scrapedAt": "2026-10-19T18:00:00.000Z"
}
```

A keyword Amazon finds nothing for:

```json
{ "status": "no_results", "reason": "amazon.com shows no products for \"qwxzvbnmplkasdfghjzz\"", "input": "qwxzvbnmplkasdfghjzz", "keyword": "qwxzvbnmplkasdfghjzz", "asin": null, "…": "…" }
```

### Use cases

- **Keyword rank tracking**: schedule a daily run over your keywords and follow where your ASIN, or a competitor's, sits in `position` and `organicPosition`.
- **Share of search and ad saturation**: how many of the first 50 cards for a keyword are ads, and which brands buy them.
- **Product and niche research**: what sells for a keyword, at what price, how many reviews, how many bought it last month, who holds the Best Seller and Amazon's Choice badges.
- **Price monitoring**: prices, list prices, coupons and deals across a whole search, on several marketplaces.
- **More detail on a product**: feed the ASINs to our [Amazon Product Details Scraper](https://apify.com/steadyscrape/amazon-product-scraper) for the buy box, seller, stock, specs and variations, or check their category ranks with the [Amazon Best Sellers Scraper](https://apify.com/steadyscrape/amazon-bestsellers-scraper).

### Limits and honesty

- **Marketplaces**: measured from Apify's cloud on 2026-10-19, amazon.com, .ca, .com.mx, .com.br, .co.jp and .com.au answered through datacenter proxies; amazon.co.uk, .de, .it, .es and .in answered Amazon's bot check to cloud IPs and were read through residential proxies of their own country (included in the price). **amazon.fr answered a JavaScript challenge on every route**, residential included: it comes back as a free `blocked` row, because this Actor never solves challenges. Amazon changes its mind about IPs from one hour to the next; a search every route refuses is a free `blocked` row and the run still finishes.
- **What Amazon shows depends on the IP**: Amazon localizes prices, delivery and even the results to the visitor's location. Residential IPs are taken in the marketplace's country, but datacenter IPs are in the US, so amazon.co.jp read from Apify's datacenter showed prices in US dollars ("USD 23.53"); `currency` always says which. A visitor who is not logged in sees "Join Prime to get FREE delivery…" on amazon.com; most other marketplaces show visitors no Prime marker, so `prime` reads `false` there.
- **Positions are the cards a shopper sees**: product cards, sponsored ones included. Video ads, brand banners and carousels between the results are not product cards and are not counted. Amazon reshuffles and personalizes results, so two runs minutes apart can differ by a few places.
- **Ads alone are not results**: when Amazon finds nothing for a keyword it sometimes fills the page with sponsored products. Such a search is a free `no_results` row that says how many ads were shown.
- **Books list several formats per result**; the row carries the first one Amazon shows, with its price (an audiobook's "$0.00 Free with Audible trial" is what the card says; `priceNote` tells you).
- The same ASIN can appear twice in a search (as an ad and as an organic result): both rows are what the page shows, and both are charged.
- Product pages are not opened: no description, specs, seller or stock beyond what the card shows.

### Pricing

Pay per event: one `product` event per row with status `ok`, **US$0.001** (US$1 per 1,000 results, no start fee). Rows with any other status are free, and sponsored cards you turn off are not charged. Set a spending limit on the run and the Actor stops at it.

### Legal

The Actor reads publicly available search pages that Amazon shows to anyone, without logging in, and stores no personal data. It does not solve CAPTCHAs or bypass challenges. Use the data in line with Amazon's terms and your local law.

# Actor input Schema

## `keywords` (type: `array`):

One search per line: a keyword (<code>wireless earbuds</code>) searched on the marketplace below, or a link to any Amazon search results page (<code>https://www.amazon.co.uk/s?k=desk+lamp\&rh=p_72%3A419153031</code>) taken as it is, with its own marketplace, department, sort and filters. Any filter Amazon offers (price range, brand, rating, Prime) works: apply it on Amazon and paste the link.

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

Where keywords are searched (links carry their own). Measured from Apify's cloud on 2026-10-19: amazon.com, .ca, .com.mx, .com.br, .co.jp and .com.au answered through datacenter proxies; .co.uk, .de, .it, .es and .in through residential proxies of their own country; amazon.fr answered a challenge on every route (a free <code>blocked</code> row).

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

Search one department only, by the alias Amazon puts after <code>i=</code> in a search link: on amazon.com <code>electronics</code>, <code>stripbooks</code> (Books), <code>digital-text</code> (Kindle Store), <code>fashion</code>, <code>beauty</code>, <code>garden</code> (Home & Kitchen), <code>hpc</code> (Health & Household), <code>sporting</code>, <code>toys-and-games</code>, <code>tools</code>, <code>pets</code>, <code>automotive</code>, <code>office-products</code>. Empty: all departments. Applies to keywords only.

## `sort` (type: `string`):

The order of Amazon's own "Sort by" menu. Applies to keywords; a link keeps its own.

## `maxResultsPerSearch` (type: `integer`):

Stop each search after this many product rows (sponsored ones included unless they are turned off below). Amazon shows 16 to 60 cards a page.

## `maxPagesPerSearch` (type: `integer`):

The most results pages read per search. Amazon usually ends a search at 7 pages of 48 or 20 of 16; within a department it can go further.

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

Sponsored product cards come back flagged <code>sponsored: true</code>. Off: they are left out (and not charged), while <code>position</code> still counts them so it matches what a shopper sees.

## `residentialFallback` (type: `boolean`):

When Amazon refuses the run's own IP and the datacenter proxies, retry through residential proxies of the marketplace's country (included in the price: you pay per product, not per proxy byte). Off: those searches come back with status <code>blocked</code>, unpaid.

## Actor input object example

```json
{
  "keywords": [
    "wireless earbuds"
  ],
  "marketplace": "com",
  "sort": "relevance",
  "maxResultsPerSearch": 30,
  "maxPagesPerSearch": 5,
  "includeSponsored": true,
  "residentialFallback": true
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# 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 = {
    "keywords": [
        "wireless earbuds"
    ],
    "maxResultsPerSearch": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/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 = {
    "keywords": ["wireless earbuds"],
    "maxResultsPerSearch": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/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 '{
  "keywords": [
    "wireless earbuds"
  ],
  "maxResultsPerSearch": 30
}' |
apify call steadyscrape/amazon-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/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/PgAc6FcaKQbeIZ32J/builds/megmEcG0dl1TPsovt/openapi.json
