# Amazon Keyword Rank Tracker: Organic & Sponsored (`cleanpull/amazon-keyword-rank-tracker`) Actor

Track where your products rank on Amazon search for your keywords: organic and sponsored place, page, who outranks you, and changes since the last run, in 22 marketplaces. Plus each keyword's top results and competition. From $2 per 1,000 pages; compact JSON for AI agents.

- **URL**: https://apify.com/cleanpull/amazon-keyword-rank-tracker.md
- **Developed by:** [CleanPull](https://apify.com/cleanpull) (community)
- **Categories:** E-commerce, SEO tools
- **Stats:** 1 total users, 1 monthly users, 94.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 search pages

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 Keyword Rank Tracker: Organic & Sponsored

Give it **keywords** and **your products (ASINs)** and get, for every pair, the product's **organic rank**, its **sponsored (ad) place**, the **page** it shows on, **who ranks above it**, and **what changed since your last run**. Every keyword also gets a row describing its results: the top 10, the ads, and the **competition** (price spread, review depth, Best Seller badges, units bought in the past month). It works in **22 Amazon marketplaces**, with each country read from that country. From **$2 per 1,000 search pages** plus $1 per 1,000 product ranks.

### What you can do with it

- **"Where does my product rank for my keywords?"** Track every keyword and product pair daily, with organic and sponsored places kept apart.
- **"Who outranks me?"** Each rank row lists the five results directly above your product, with their price, rating and reviews.
- **"Tell me when my rank moves."** With Changes only, you get only real moves; small reshuffles between reads are filtered out (see below).
- **"Is this niche worth entering?"** Each keyword row gives the price range of the top 20, their median reviews, how many have under 100 reviews, Best Seller badges and units bought in the past month.
- **"Export a search results page."** Turn on One row per search result to get every card with its position, ad or organic place, price, rating, reviews and badges.

### What makes the ranks right

- **Organic and sponsored are counted separately.** A product's organic rank counts organic results only, across pages, so ads never push it down. Its sponsored place counts ads only. `position` (every card) and `slot` (Amazon's own slot, with widgets) are given too.
- **Ads are read from home-network addresses.** In tests, Amazon showed no ads at all to datacenter addresses and stopped showing them to a session after a few searches. So each keyword starts on a fresh session through US residential addresses, and a first page without ads is read once more at our cost (first reading only). A keyword that showed no ads on 2 runs in a row is not re-read again for a week; at most 3 re-reads a run that find no ads. If a keyword still shows no ads (some categories rarely do), the row says `adsShown: false` rather than reporting "no ad place".
- **Rank noise is filtered.** Deeper results reshuffle by 1 to 3 places between two reads of the same search, up to 8. An organic move counts from 1 place in the top 3 and 2 places in the top 10. Below that it needs 3 places and 25% of the earlier rank (rank 21 needs 6); both are adjustable.
- **Milestones need to be clear.** Entering or leaving the top 3, the top 10 and page 1 (the organic results on that run's first page) counts when the rank is clearly past the line, comes with a reported move, or is seen two runs in a row. So a product sitting at the line does not flap.
- **Ad places are noisier.** A sponsored move needs 3 places and half the place, and an ad starting or stopping is reported once two runs in a row agree.
- **Baselines move only when a change is reported.** Organic and sponsored places keep separate baselines, so a slow drift still shows once it adds up. A baseline is saved only once its row is delivered, so a stop at a limit never loses a change. For steadier numbers, Readings per keyword (up to 3) reports the median rank and its range.
- **Short results pages are handled.** Some categories show 16 results a page and others 48. Depth is set in organic results, not pages, and pages are followed (up to 7) until it is reached, or until all your products are found.
- **Each country is read from that country.** Outside the US, pages come through addresses in that country, and every row gives `localView`. A page shown as for a visitor abroad is not compared for changes.
- **Only delivered work is billed.** A keyword that could not be read is listed in the run summary with the reason, never charged.

### Input

| Field                                                              | What it does                                                                                                                              |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `keywords`                                                         | Search terms, one per line                                                                                                                |
| `asins`                                                            | Your products: ASINs or product URLs. Optional; without them you get keyword rows only                                                    |
| `marketplace`                                                      | US, GB (or UK), DE, FR, IT, ES, CA, MX, BR, JP, IN, AU, NL, SE, PL, BE, TR, AE, SA, SG, EG, IE, or a domain                               |
| `maxResults`, `stopWhenFound`                                      | Organic depth to scan per keyword (default 48), and whether to stop once all products are found                                           |
| `sponsored`                                                        | Record ad places (US: read through residential addresses). Off: organic only, cheaper                                                     |
| `samples`                                                          | Read each search 1 to 3 times and report the median rank                                                                                  |
| `resultRows`                                                       | Also one row per result card                                                                                                              |
| `changesOnly`, `monitorName`, `rankChangeMin`, `rankChangePercent` | Only ranks that moved since the last run with this monitor name, and how big a move counts                                                |
| `providerFallback`                                                 | Provider fallback: when Amazon refuses a keyword on every proxy, read it through the marketplace data service (off by default; see below) |
| `maxRunCostUsd`                                                    | Max cost per run: a keyword is read only when its worst case fits what is left. For schedules and tasks                                   |
| `maxItems`, `fields`, `proxyConfiguration`                         | Limits, field selection and proxy                                                                                                         |

#### Example inputs

Three products on five keywords, checked daily for rank moves:

```json
{
  "keywords": [
    "stainless steel water bottle",
    "insulated water bottle",
    "water bottle with straw",
    "kids water bottle",
    "gym water bottle"
  ],
  "asins": ["B0BZYCJK89", "B07N2F3JXP", "B0BZYBSRNF"],
  "changesOnly": true,
  "monitorName": "bottles"
}
```

The first 100 organic results for a keyword in Germany, one row each:

```json
{
  "keywords": ["yogamatte"],
  "marketplace": "DE",
  "maxResults": 100,
  "resultRows": true,
  "sponsored": false
}
```

### Output

A rank row (real, from a test run):

```json
{
  "recordType": "rank",
  "keyword": "stainless steel water bottle",
  "marketplace": "US",
  "asin": "B0BZYCJK89",
  "found": true,
  "organicRank": 1,
  "organicPage": 1,
  "position": 5,
  "slot": 7,
  "sponsoredRank": null,
  "title": "Owala FreeSip Stainless Steel Water Bottle 24 oz Denim",
  "price": 29.99,
  "currency": "USD",
  "rating": 4.6,
  "reviewCount": 141437,
  "badges": ["Overall Pick", "Amazon's Choice"],
  "boughtPastMonth": "20K+ bought in past month",
  "outrankedBy": [],
  "organicSeen": 45,
  "adsShown": true,
  "localView": true,
  "changes": [],
  "previousOrganicRank": 1,
  "firstSeen": false,
  "url": "https://www.amazon.com/dp/B0BZYCJK89"
}
```

A change looks like `{ "type": "organic-rank", "from": 9, "to": 4, "delta": 5 }`. A milestone looks like `{ "type": "milestone", "milestone": "entered-top-3", "from": 4, "to": 3 }` (also `left-top-3`, `entered-top-10`, `left-top-10`, `entered-page-1` and `left-page-1`). The other types are `organic-entered`, `organic-lost` (counted only when the run read as deep as the old rank), `sponsored-rank`, `sponsored-started` and `sponsored-stopped` (compared only when both runs were shown ads). Rank rows also carry `sponsoredPage`, `adPlacements` (sponsored video, carousels), `rankRange` (with several readings) and `previousSponsoredRank`. With several readings, `outrankedBy` comes from the reading whose rank is the median, and keyword rows from the first reading.

A keyword row's competition block (real):

```json
{
  "keyword": "stainless steel water bottle",
  "resultsText": "1-48 of over 30,000 results",
  "organicSeen": 45,
  "sponsoredSeen": 12,
  "adsShown": true,
  "competition": {
    "topCount": 20,
    "priceMin": 11.99,
    "priceMedian": 26.99,
    "priceMax": 34.99,
    "reviewsMedian": 12924,
    "resultsUnder100Reviews": 1,
    "bestSellerBadges": 7,
    "boughtPastMonthTotalMin": 138800
  }
}
```

Keyword rows also hold `topResults` (the first 10 organic), `sponsoredResults` (the first 10 ads), `adPlacements`, `pagesRead`, `resultsPerPage` and `deliveryLocation`. Result rows hold each card's `position`, `organicRank`, `sponsoredRank`, `page`, `slot`, `price`, `listPrice`, `rating`, `reviewCount`, `badges`, `boughtPastMonth`, `promotion`, `image` and `tracked`.

Every row has a `source`: `amazon` (read from Amazon's pages) or `provider` (read through the marketplace data service, below).

Dataset views: **Ranks**, **Keywords** and **Search results**. `RUN_SUMMARY` gives the outcome, pages read, residential pages, keywords and records read through the marketplace data service, extra reads for ads, keywords without ads, charges, what Amazon answered on each proxy tier (`fetching.answers`), and every keyword that could not be read, with the reason.

### When Amazon refuses a keyword

Some marketplaces (amazon.fr in particular) sometimes answer every address with a bot check. The actor never tries to solve or get around it: it tries fresh sessions and then higher proxy tiers. When a keyword is refused on all of them, the run says so and suggests the **Provider fallback**. With it on (`providerFallback: true`, off by default; available from 31 October 2026), it reads that keyword's search results through **CleanPull's marketplace data service**, a third-party web data provider. CleanPull holds the account and its key, which never appears in your input, logs or results.

- **Cost:** $0.015 for the keyword plus about $0.003 per result record (see Pricing), at most Max results records, instead of the page charges. Nothing is charged for a keyword the service cannot read either, and a job is never started when the run's maximum cost cannot cover it.
- **Time:** 1 to 5 minutes per job. When the first 2 keywords of a run are both refused, the rest go straight to the service, up to 25 keywords a job (only as many as Max rows and the cost limits allow). A run moved to another server downloads the jobs it already started instead of paying for new ones.
- **Ranks over time:** each source keeps its own baseline. A rank read through the service is never compared with one read from Amazon: the first reading from a new source has `changes: []` and `sourceChanged: true` (with Changes only, it delivers nothing), and a return to Amazon compares with the last Amazon reading.
- **What it gives:** organic places, page, price, rating, reviews, badges and "bought in past month" from its records, compared with your earlier runs like any reading. Not available from it: sponsored places (its records hold organic results only, so `sponsoredRank` is empty and `adsShown` is null), ad placements, the results text and the delivery location; `localView` is null on these rows.
- **Off** (the default): a refused keyword fails, costs nothing, and the run stops after the first 2 keywords are refused.

### Pricing

| Event                                                                                                        | Free and Bronze | Silver | Gold and above |
| ------------------------------------------------------------------------------------------------------------ | --------------- | ------ | -------------- |
| Search page read                                                                                             | $2.00           | $1.80  | $1.60          |
| Search page from home-network addresses (add-on: US with sponsored places, every marketplace outside the US) | $6.00           | $6.00  | $6.00          |
| Product rank (a delivered rank row)                                                                          | $1.00           | $0.90  | $0.80          |
| Search result row (with One row per search result)                                                           | $0.50           | $0.45  | $0.40          |
| Provider search (a keyword Amazon refused, read through the marketplace data service)                        | $15.00          | $15.00 | $15.00         |
| Provider record (a search result record from the marketplace data service)                                   | $3.00           | $2.70  | $2.40          |

Per 1,000. Each run also has a $0.00005 start fee.

- **Not charged:** extra reads to find a page with ads.
- **Max cost per run** (`maxRunCostUsd`) counts each keyword's worst case: every page through home-network addresses; with Provider fallback on, a refused keyword's fallback starts only when its provider search and Max results records fit too.
- **Readings per keyword** multiply the page charges: 3 readings bill 3 times the pages.
- **Your own residential proxy** (in the Proxy field) is not charged the add-on.

Example: 10 keywords and 3 products checked daily in the US, with sponsored places and one page each, is 10 pages at $8 per 1,000 plus 30 ranks at $1 per 1,000. That is about $0.11 a day, or $3.30 a month. Without sponsored places, the same check costs about $0.05 a day. With Changes only, the pages are still billed, but unchanged ranks are free.

### Limits

- **Ranks are for a signed-out shopper** in the marketplace's country, without a postcode. Delivery-specific ranking and personalisation are not reflected.
- **Sponsored places** cover ads in the result grid; sponsored brand banners are reported as `adPlacements`, not as places.
- **US results come from varying US locations.** Pages are read through residential addresses spread across the US, without a postcode, so a delivery-specific result can differ from what a shopper at one address sees.
- **Exact ASIN match only.** A product is found by its own ASIN; another variant of the same listing (a parent or sibling ASIN) is not counted as it.
- **Search volume** is not available: Amazon does not publish it.

### Changelog

- **0.2** (October 2026): keywords Amazon refuses on every proxy tier are read through the marketplace data service (`providerFallback`, `source` on every row); failed keywords say what Amazon answered.
- **0.1** (October 2026): organic and sponsored ranks per keyword and product in 22 marketplaces, who outranks you, keyword competition, result rows, median readings, rank-move filtering and changes since the last run.

# Actor input Schema

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

Search terms, one per line, as shoppers type them into Amazon.

## `asins` (type: `array`):

Optional. ASINs or Amazon product URLs whose rank you want for every keyword: organic place, sponsored place, page, and who ranks above. Leave empty to get only each keyword's results.

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

A country code or domain: US, GB (or UK), DE, FR, IT, ES, CA, MX, BR, JP, IN, AU, NL, SE, PL, BE, TR, AE, SA, SG, EG, IE. Outside the US, pages are read from that country (residential add-on).

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

How deep to look for your products: organic results read per keyword (pages are followed, up to 7; Amazon shows 16 to 48 organic results a page depending on the category).

## `stopWhenFound` (type: `boolean`):

Stop reading pages for a keyword once every product above has been found organically (fewer pages, lower cost).

## `sponsored` (type: `boolean`):

Also record ad (sponsored) places. In the US, Amazon shows ads only to home-network visitors, so pages are read through residential addresses (add-on per page). Off: organic ranks only, cheaper.

## `samples` (type: `integer`):

Read each search 1 to 3 times on fresh sessions and report the median rank, with the range. Organic ranks move by 1 to 3 places between readings; 3 readings steady them (each reading is billed as its pages).

## `resultRows` (type: `boolean`):

Also return every result card read (position, organic or sponsored place, price, rating, reviews, badges, bought in past month) as its own row.

## `changesOnly` (type: `boolean`):

Return only product ranks that changed since the last run with the same monitor name. Pages read are still billed; unchanged ranks are free. Schedule it daily.

## `monitorName` (type: `string`):

Runs with the same name compare against each other.

## `rankChangeMin` (type: `integer`):

A rank move counts as a change from this many places. Amazon reshuffles results by 1 to 3 places between two reads of the same page.

## `rankChangePercent` (type: `integer`):

Deeper ranks move more between reads, so a move must also be this share of the earlier rank: at 25%, rank 4 needs 3 places (the minimum above), rank 21 needs 6, rank 40 needs 10. 0 uses only the minimum above.

## `maxRunCostUsd` (type: `number`):

Optional. A keyword is read only when what this run has charged, plus the most that keyword could cost, stays within this amount. For scheduled runs and tasks, where no spending limit may be set.

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

Optional. Stop after this many rows.

## `fields` (type: `array`):

Optional. Keep only these fields, for example \["keyword", "asin", "organicRank", "sponsoredRank"].

## `providerFallback` (type: `boolean`):

Off by default. When Amazon refuses a keyword on every proxy, read its search results through CleanPull's marketplace data service instead (1 to 5 minutes). Costs $0.015 per keyword plus $0.003 per result record (up to Max results records), instead of the page price: about $0.16 per keyword at 48 results. It gives organic places only, no sponsored places. Only keywords Amazon refused use it. Off: a refused keyword fails and costs nothing.

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

Optional. The actor picks proxies itself (in-country addresses outside the US, residential for ads in the US).

## Actor input object example

```json
{
  "keywords": [
    "stainless steel water bottle"
  ],
  "asins": [
    "B0BZYCJK89"
  ],
  "marketplace": "US",
  "maxResults": 48,
  "stopWhenFound": true,
  "sponsored": true,
  "samples": 1,
  "resultRows": false,
  "changesOnly": false,
  "monitorName": "default",
  "rankChangeMin": 3,
  "rankChangePercent": 25,
  "providerFallback": false
}
```

# Actor output Schema

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

Rank rows per product and keyword, keyword rows, and result rows when asked for. Each row's source is "amazon" (read from Amazon) or "provider" (read through the marketplace data service after Amazon refused the keyword).

## `ranks` (type: `string`):

No description

## `keywords` (type: `string`):

No description

## `searchResults` (type: `string`):

No description

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

Outcome, counts, charges and every keyword that could not be read, with the reason.

# 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": [
        "stainless steel water bottle"
    ],
    "asins": [
        "B0BZYCJK89"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanpull/amazon-keyword-rank-tracker").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": ["stainless steel water bottle"],
    "asins": ["B0BZYCJK89"],
}

# Run the Actor and wait for it to finish
run = client.actor("cleanpull/amazon-keyword-rank-tracker").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": [
    "stainless steel water bottle"
  ],
  "asins": [
    "B0BZYCJK89"
  ]
}' |
apify call cleanpull/amazon-keyword-rank-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cleanpull/amazon-keyword-rank-tracker"
        }
    }
}
```

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/3CeVcV2fOK4jU4R7s/builds/8ccmTU7jTvs1h1XPZ/openapi.json
