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

Scrape Amazon keyword search results into clean JSON: ASIN, title, price, rating, review count, sponsored flag, badges. Pay per result, $1.50 per 1,000 results.

- **URL**: https://apify.com/jaybird/amazon-search-scraper.md
- **Developed by:** [Jaybird Technologies](https://apify.com/jaybird) (community)
- **Categories:** E-commerce
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 search results

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

### What does Amazon Search Scraper do?

**Amazon Search Scraper** extracts public product cards from [Amazon](https://www.amazon.com/) **keyword search-result pages**. Give it keywords, Amazon search URLs, or both. For each card it can see in the HTML, it saves the ASIN, title, canonical product URL, price, rating, sponsored flag, and badges.

It does not open product detail pages, review pages, or carts. It does not solve CAPTCHAs. Product detail and reviews are separate Actors: [Amazon Product Data Scraper](https://apify.com/jaybird/amazon-product-data-scraper) and [Amazon Reviews Scraper](https://apify.com/jaybird/amazon-reviews-scraper).

### Why scrape Amazon search results?

Search pages show how Amazon ranks products for a keyword on a given request: which ASINs appear, which slots are sponsored, and which price and rating Amazon printed on the card.

Typical uses:

- checking organic rank for a keyword
- comparing prices and ratings across the first pages of a search
- recording Best Seller, Amazon's Choice, and other badges shown on the card
- separating sponsored cards from organic cards when Amazon labels them
- feeding ASINs into a product or reviews Actor

Runs can be started from the Apify Console, on a schedule, or through the Apify API. The default proxy is Apify residential proxy, because Amazon often blocks datacenter addresses.

### What data can Amazon Search Scraper extract?

Each saved item is one product card after duplicate ASINs on that page are removed. Fields that are not visible are `null`. The Actor does not fill them in from the marketplace or from another card.

| Field | Meaning |
| --- | --- |
| `keyword` | Keyword for this search. `null` when the start URL has no `k` parameter. |
| `marketplace` | `amazon.com`, `amazon.co.uk`, `amazon.de`, or `amazon.ca`. |
| `searchUrl` | Search URL requested for this page. |
| `page` | Page number from the URL. Page 1 when the URL has no `page` parameter. |
| `positionOnPage` | 1-based position among deduplicated product cards on the page. |
| `overallPosition` | Same count continued across pages of this search. |
| `organicRank` | Count of organic cards only. `null` for a sponsored card. |
| `isSponsored` | `true` when the card itself carries a sponsored label. |
| `asin` | ASIN from the card. |
| `title` | Title on the card. |
| `url` | Canonical `https://www.{marketplace}/dp/{ASIN}` URL. |
| `price`, `listPrice`, `currency` | Current price and struck-through list price parsed from the card. Currency comes only from that price text. |
| `rating` | Star rating printed on the card, from 0 to 5. |
| `reviewCount` | Ratings count printed on the card. Amazon's search card does not show a separate written-review total. |
| `imageUrl` | Image URL on the card. |
| `isPrime` | `true` when a Prime icon is present on the card, otherwise `null`. Logged-out Amazon pages usually do not show Prime badges on search cards, so expect mostly `null`. |
| `badges` | Badge labels such as Best Seller or Amazon's Choice. Empty when none are shown. |
| `boughtPastMonthText` | Text such as "3K+ bought in past month", kept as shown. |
| `scrapedAt` | ISO time when the card was parsed. |

`positionOnPage` counts product cards. It is not Amazon's internal `data-index`, which also counts non-product widgets.

### How to scrape Amazon search results

1. Open the Actor in Apify Console and sign in.
2. Enter one or more keywords, or paste Amazon search URLs. The form prefills `wireless earbuds`.
3. Choose a marketplace for keyword searches. `amazon.com` is the default. `amazon.co.uk`, `amazon.de`, and `amazon.ca` use the same parser.
4. Set **Max pages per keyword** (default 1, maximum 20) and, if you want a cap, **Max results**.
5. Leave residential proxy enabled unless you have a reason to change it.
6. Run the Actor. Open the dataset to download JSON, CSV, Excel, or HTML. The `OUTPUT` record in the key-value store has page and item counts.

### How much will it cost to scrape Amazon search results?

The Actor uses pay-per-event pricing with one event per saved result:

- event: **Search result** (`result`)
- price: **$0.0015 per result**, which is **$1.50 per 1,000 results**

A blocked page is retried and is not charged, because nothing is saved from it. There is no separate start fee. Residential proxy traffic is included in the Actor's platform costs, so you are not billed for it separately on top of the result price. Sponsored cards are charged like any other card unless you turn off **Include sponsored results**. Set a maximum charge on the run to cap spending.

### Input

See the Input tab for the form. A keyword run looks like this:

```json
{
  "keywords": ["wireless earbuds"],
  "marketplace": "amazon.com",
  "maxPagesPerKeyword": 1,
  "includeSponsored": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

You can pass search URLs instead of, or in addition to, keywords:

```json
{
  "startUrls": [
    { "url": "https://www.amazon.co.uk/s?k=wireless+earbuds" }
  ],
  "maxPagesPerKeyword": 2,
  "maxItems": 40
}
```

`maxPagesPerKeyword` defaults to 1 and cannot be set above 20 in the form. `includeSponsored` defaults to `true`. Keyword searches use `marketplace`. A start URL keeps the marketplace in its host. Supported hosts are `amazon.com`, `amazon.co.uk`, `amazon.de`, and `amazon.ca`.

### Output

You can download the dataset as JSON, CSV, Excel, or HTML. Two items from a US keyword search would look like this when the page shows those values:

```json
[
  {
    "keyword": "wireless earbuds",
    "marketplace": "amazon.com",
    "searchUrl": "https://www.amazon.com/s?k=wireless+earbuds",
    "page": 1,
    "positionOnPage": 1,
    "overallPosition": 1,
    "organicRank": 1,
    "isSponsored": false,
    "asin": "B0EXAMPLE1",
    "title": "Example Wireless Earbuds",
    "url": "https://www.amazon.com/dp/B0EXAMPLE1",
    "price": 29.99,
    "listPrice": 39.99,
    "currency": "USD",
    "rating": 4.5,
    "reviewCount": 1234,
    "imageUrl": "https://m.media-amazon.com/images/I/example.jpg",
    "isPrime": null,
    "badges": ["Amazon's Choice"],
    "boughtPastMonthText": "3K+ bought in past month",
    "scrapedAt": "2026-11-09T17:00:00.000Z"
  }
]
```

The example values above are a shape sample, not a capture from a live run of this Actor.

The key-value record `OUTPUT` is written at the end of every run:

- `pagesRequested`
- `pagesSucceeded`
- `pagesFailed`
- `blockedCount` (blocked, robot-check, and suspicious-empty responses, including retries)
- `itemsPushed`

If every requested page fails, the run exits with a non-zero status instead of ending as an empty success.

### Related Actors

Use this Actor to find ASINs for a keyword, then pass them to these Actors for per-ASIN details:

- [Amazon Product Data Scraper](https://apify.com/jaybird/amazon-product-data-scraper) for product detail pages
- [Amazon Reviews Scraper](https://apify.com/jaybird/amazon-reviews-scraper) for reviews

### Limitations

- Amazon changes search HTML. Selectors that match today's cards can miss fields after a layout change. Missing fields stay `null`.
- Amazon blocks automated requests. The Actor retries a blocked, robot-check, or suspiciously empty page up to three times and asks the proxy layer for a new session each time. That is not a guarantee of access. Live test runs on amazon.com with residential proxy returned results on every page requested, but Amazon can change that at any time.
- Only `amazon.com` has been tested live. `amazon.co.uk`, `amazon.de`, and `amazon.ca` use the same parser and have not been tested against live pages.
- Sponsored labels vary by session and location. A card is marked sponsored only when that card contains a sponsored label. A label elsewhere on the page, such as an influencer carousel, does not mark the main results as sponsored.
- Prices and currency are parsed from the text Amazon printed on the card. A UK or DE host can still display USD. The Actor does not replace that with GBP or EUR.
- `isPrime` is `true` only when a Prime icon appears on the card. Amazon does not show Prime badges to logged-out visitors, so it is usually `null`, which means unknown, not "not Prime".
- The same ASIN later on another page is saved again. Deduplication is per page, and the first block on the page is kept.
- Pagination follows Amazon's next link only. The Actor does not invent page URLs.
- The Actor reads server-rendered HTML. It does not run a browser. Content that exists only after client-side rendering is not scraped.
- Search cards show a ratings count. That number is stored as `reviewCount`.

### FAQ, disclaimers, and support

Our Actors are ethical and do not extract private user data, such as email addresses, gender, or location. They only extract what the page shows publicly on a search result. You should be aware that results could still contain personal data, for example a seller name printed on a card. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you are unsure whether your reason is legitimate, consult your lawyers.

Amazon's terms restrict automated access. You are responsible for how you use this Actor and for complying with the laws and terms that apply to you.

If a run fails immediately, check that each start URL is an `https` search URL on a supported host and that at least one keyword or URL was provided. If `OUTPUT.blockedCount` equals the attempts and `itemsPushed` is 0, Amazon returned a block page or a robot check. Residential proxy is the setting this Actor expects on Apify.

Use the Issues tab for bugs and the API tab to start runs programmatically.

#### Local development

Install dependencies with `npm install` and compile with `npm run build`. A local run without an Apify token cannot use Apify residential proxy, so a real Amazon request from a developer machine is likely to be blocked. `AMAZON_SEARCH_MOCK_HTML` can point a local run at a saved HTML file. It is ignored on the Apify platform.

# Actor input Schema

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

Search keywords. The Actor opens an Amazon search page for each keyword on the selected marketplace.

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

Amazon search-result URLs, for example https://www.amazon.com/s?k=wireless+earbuds. Use keywords, start URLs, or both. Supported hosts: amazon.com, amazon.co.uk, amazon.de, amazon.ca.

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

Amazon site used for keyword searches. Start URLs keep the marketplace in their own host.

## `maxPagesPerKeyword` (type: `integer`):

How many result pages to open for each keyword or start URL. The Actor follows Amazon's next-page link and stops at this limit.

## `maxItems` (type: `integer`):

Stop after this many results have been saved. Leave empty for no Actor-side cap. The run also stops when your pay-per-event spending limit is reached.

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

Save sponsored cards. When off, sponsored cards are skipped and are not charged. Organic rank still reflects their presence on the page.

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

Amazon blocks many datacenter IPs. Residential Apify Proxy is the default.

## Actor input object example

```json
{
  "keywords": [
    "wireless earbuds"
  ],
  "marketplace": "amazon.com",
  "maxPagesPerKeyword": 1,
  "includeSponsored": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `overview` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jaybird/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"] }

# Run the Actor and wait for it to finish
run = client.actor("jaybird/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"
  ]
}' |
apify call jaybird/amazon-search-scraper --silent --output-dataset

```

## MCP server setup

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