# Amazon Niche Research: Revenue, Demand & Competition (`amazonscrapers/amazon-niche-research`) Actor

Survey an Amazon category and see how much money moves in it. Units bought last month, revenue estimate, rating, review count, bestseller rank and seller count per product. 19 marketplaces. You only pay for rows that arrive with a price.

- **URL**: https://apify.com/amazonscrapers/amazon-niche-research.md
- **Developed by:** [Amazon Scrapers](https://apify.com/amazonscrapers) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 products with a prices

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Amazon niche research: revenue, demand and competition per category

Give it a category. Get back every product in it with the numbers that decide
whether the niche is worth entering: how much each one sells, what that is worth
in money, how many reviews stand between you and the top, and how many sellers
are already there.

Twenty-three fields per product, nineteen marketplaces, and revenue estimates
built on Amazon's own units figure rather than on a formula somebody invented.

### The four numbers that decide a niche

Most category research stops at price and rating, because those are on the search
page and cost nothing to collect. They also tell you nothing about whether you
could win.

**Money, not rank.** `estimatedMonthlyRevenue` is `boughtInPastMonth` times
price. A category where the top ten each turn over four hundred dollars a month
is a hobby. One where they turn over forty thousand is a business, and the
difference is invisible if you only look at rank.

**Volume in Amazon's own words.** `boughtInPastMonth` is the figure Amazon prints
as "10K+ bought in past month", and `boughtInPastMonthText` keeps the original
wording so you can see how rounded it was.

**The wall.** `reviewCount` and `rating` together. Four hundred reviews at 4.8
stars is a wall you will not climb this year. Four hundred at 3.9 is an opening:
the demand is proven and the incumbent is not loved.

**The crowd.** `otherSellersCount` on every listing. A category where each
product has one seller is a category of brands. One where each has nine is a
commodity fight.

Plus the two badges Amazon hands out itself, `isBestSeller` and `isAmazonChoice`,
which move independently of rank and independently of each other.

### Every field it returns

Twenty-three per product, all of them pointed at one question: is this category
worth my time.

#### Price and offer

| Field | What it holds |
| --- | --- |
| `price` | Current price from Amazon's own buy box data **(this is what you are charged for)** |
| `listPrice` | The struck-through price, when Amazon shows one |
| `discountPercent` | How much is off as a percentage |
| `currency` | Three-letter code, from the page itself |
| `otherSellersCount` | How many other sellers offer it |

#### Demand and rank

| Field | What it holds |
| --- | --- |
| `boughtInPastMonth` | Units bought last month as a number |
| `boughtInPastMonthText` | Amazon's own wording, such as 10K+ bought in past month |
| `estimatedMonthlySales` | Units, derived from the line above |
| `estimatedMonthlyRevenue` | Units times price |
| `bestsellerRanks` | Every rank with its category, not just the first |
| `isBestSeller` | The orange best seller badge |
| `isAmazonChoice` | The Amazon's Choice badge |
| `rating` | Average stars, read in every shop language |
| `reviewCount` | How many ratings, as a number |

#### Stock and delivery

| Field | What it holds |
| --- | --- |
| `isPrime` | Prime delivery on this offer |

#### Identity and catalogue

| Field | What it holds |
| --- | --- |
| `asin` | The product id |
| `title` | Full product title, shortened only past 1000 characters |
| `brand` | Brand name |
| `marketplace` | Which shop this row came from |
| `url` | The page this was read from |
| `scrapedAt` | Timestamp of the read |

#### Description, media and variants

| Field | What it holds |
| --- | --- |
| `category` | The most specific category |
| `categories` | The full breadcrumb path |

### Reading a category

Run it on a bestseller list and you get up to a hundred rows. What you do with
them is the actual research, and three cuts do most of the work.

**Sort by revenue.** Not by rank. Rank tells you the order, revenue tells you the
size, and a category can have a tidy rank order over almost no money.

**Look at the review spread.** If the top ten all have thousands of reviews and
the rest have under fifty, the category is closed: the incumbents are entrenched
and nobody new is getting traction. If reviews are spread evenly, new entrants
are landing.

**Look at the seller counts.** Every listing with one seller is a brand
protecting its listing. Every listing with nine is a commodity where price is the
only lever.

The rows carry `categories`, the full breadcrumb, so you can also see how deep in
the tree the products actually sit. A category page that turns out to contain
products from six different subcategories is telling you the niche is not a
niche.

### How to read the estimates honestly

`boughtInPastMonth` is Amazon's own number and it is rounded: "10K+" becomes
10000, "50+" becomes 50. It only appears on listings with enough recent volume.
An empty value means Amazon did not print it, not that nothing sold, and on a
category page the empty ones are usually the tail.

`estimatedMonthlyRevenue` is that number times the current price, which assumes
every unit sold at today's price. On a product that was on deal last week it is
an overestimate. It is there to sort a category, not to underwrite a loan.

`boughtInPastMonthText` is included precisely so you can see the rounding for
yourself rather than trusting the number.

### It will not guess a price

Amazon puts up to nine price-shaped numbers on a product page. Measured on this
engine: prices read from the markup were correct zero times out of six, prices
from the buy box data Amazon itself uses were correct nine out of nine.

For niche research a wrong price is worse than a missing one, because it feeds
the revenue estimate and moves that product up your sorted list. So the buy box
data is the only source, and when it is absent you get no price rather than a
wrong one. The row still arrives with the units, the rank and the reviews.

**You are not charged for a row without a price.**

### A real row

```
asin                     B0CP9YB3Q4
title                    STANLEY Quencher H2.0 Tumbler with Handle and Straw
brand                    STANLEY
price                    45.00
currency                 USD
listPrice                50.00
discountPercent          10
otherSellersCount        4
boughtInPastMonth        50000
boughtInPastMonthText    50K+ bought in past month
estimatedMonthlyRevenue  2250000
bestsellerRanks          #2 in Tumblers
isBestSeller             false
isAmazonChoice           true
rating                   4.6
reviewCount              128740
category                 Tumblers
categories               Home & Kitchen > Kitchen & Dining > Tumblers
```

Two and a quarter million dollars a month at rank two, with a hundred and
twenty-eight thousand reviews. That is a category with real money in it and no
room at the top, which is exactly the shape most research misses when it only
looks at rank.

### What to put in

**A category or bestseller link.** The main way in. Paste
`https://www.amazon.com/gp/bestsellers/kitchen` or any category link.

**A search term**, when the niche is defined by what shoppers type rather than by
Amazon's tree. Often the more honest definition.

**A filtered search URL.** Build it in your browser with the price band and the
rating filter you want, paste the address, and this Actor continues from there.

**ASINs**, when you already have the incumbents and want the numbers on them.

### Settings worth knowing about

| Setting | What it does |
| --- | --- |
| `marketplace` | One of nineteen. Read the marketplace note below before researching a European shop. |
| `proxyCountry` | Leave empty and it follows the marketplace. |
| `maxItems` | Hard ceiling on delivered products. Zero means no ceiling. |
| `maxItemsPerList` | How many products to take from each category. Prefilled at ten so your first click is quick; a real pass wants fifty or a hundred. |
| `maxListPages` | How deep to walk. Amazon caps a bestseller list at a hundred products. |
| `lanes` | How many products are read at once. Eight by default. |
| `maxAttempts` | Attempts per product, each from a different address. Twelve by default. |
| `residentialFallback` | Off by default. On product pages it buys almost nothing: measured 2026-08-26, it cost roughly six times as much and returned two more products out of sixty. On the search and category pages this Actor starts from, it is a different story. Measured 2026-08-30, during hours when Amazon refused every listing page with a two kilobyte stub, twenty datacenter retries returned nothing and residential returned a full page in eight attempts. Turn it on if a run comes back empty. |
| `economical` | Off by default. It hangs up before the rank and demand blocks arrive, which are most of the point here. |

### How it works, in plain terms

Two jobs in one run. First it walks the category page and collects the ASINs.
Then it opens every product and reads it properly, because the units figure, the
seller count and the full rank list are on the product page and nowhere else.

Amazon refuses roughly six requests in ten to a fresh address, so every product
gets up to twelve attempts, each from a different exit address, and the same
address is never used twice in a row. Addresses that work are remembered for the
run. When refusals climb the runner slows down instead of pushing harder.
Anything still refused goes into a second pass at half speed.

The category page gets the same treatment, and it needs it more: a refused
listing page costs you every product inside it. Measured 26 August 2026, a
category run came back with zero products because Amazon answered the link with
four kilobytes and no error code, which the engine read as an empty category. It
now recognises a refusal without an error code and retries it.

### Reading the run log

```
Done: 20 charged, 0 refused by Amazon, 0 other. 932 KB per charged result, 189 attempts in total.
Exit addresses: 151 used, 3 proven good, 13 burned.
Attempts by outcome: {"refused by Amazon":141,"page did not carry the field this Actor needs":28,"ok":20}
```

`charged` is products that came back with a price. The bracketed number arrived
complete without one and cost you nothing.

If a run ever delivers rows and charges for none of them, the log says so in
capitals at the bottom.

### Reliability, measured

Three consecutive runs of twelve products on 26 August 2026, at the default
settings:

```
run 1   11 of 12 delivered, 10 with a price
run 2   12 of 12 delivered, 11 with a price
run 3   11 of 12 delivered, 11 with a price
```

And one run of sixty products the same day: 28 delivered,
26 with a price, in 7.2 minutes.

One thing is worth reading out of that, and it is not the one you would expect.
The sixty product run delivered 28, which sounds worse than the 34 of 36 above
until you notice what it was asked for: a category page, and Amazon only offered
28 products on it that day. A list Actor is bounded by what the list holds, so
"delivered" here means "everything that was there", not "everything we wanted".

The second is the residential switch, and the honest version is less dramatic
than it sounds. Measured 26 August on the same sixty products, twice: with the
switch off, fifty-one came back with the field this Actor charges on, for $0.0205
of platform usage. With it on, fifty-three came back, for $0.1192. Two more
products for roughly six times the cost.

That is why it is off by default. It is in your input form, so if a marketplace
is refusing almost everything you can turn it on and pay for the difference.

### What you can build with it

**A niche scorecard.** One run per candidate category, then a single sheet
comparing total revenue, median review count and median seller count. That
comparison is the decision.

**A competitor profile.** Search a brand name and you get their whole catalogue
with revenue on each, which tells you where their business actually is rather
than where their marketing is.

**A seasonality check.** Run the same category monthly into one dataset. Twelve
runs and you know when the category wakes up.

**A gap analysis.** Sort by revenue, then look for products with high volume and
a rating under four. Those are proven demand with an unhappy incumbent.

**A pricing band.** The spread of `price` across a category tells you where the
customer expectation sits before you set yours.

### Working it into your stack

Every run writes to a dataset you can download as CSV, JSON, Excel or XML, or
pull through the API. For research the spreadsheet export is usually what you
want; the output is flat apart from `bestsellerRanks` and `categories`, which are
lists.

Schedules take a cron expression. A monthly pass into one named dataset turns a
snapshot into a trend.

### Marketplaces

Nineteen, from amazon.com to amazon.co.jp, read in their own language. A German
rating saying "4,5 von 5 Sternen" and a Japanese one putting the number last both
come back as 4.5.

Prices do not travel everywhere, and here that matters twice because price feeds
the revenue estimate. Measured on 2026-08-24:

| Marketplace | Products priced |
| --- | --- |
| amazon.com | 57 of 60 |
| amazon.ca | 5 of 5 |
| amazon.co.uk | 5 of 6 |
| amazon.fr | 4 of 5 |
| amazon.it | 1 of 5 |
| amazon.es | 1 of 5 |
| amazon.de | 0 of 8 |
| amazon.com.au | 0 of 5 |

Ranks, ratings, review counts and demand figures arrive on all of them, and rows
without a price are free. On a European marketplace you can still do the
competition half of the research; you just cannot do the revenue half.

### Pricing

Four dollars per thousand products with a price, plus three cents to start a run.

Researching five categories of a hundred products each costs about two dollars.
You are not charged for rows without a price or for products that never arrived,
and platform usage is included.

### The rest of this family

Eleven Actors on one engine. Around a niche pass:

- **Amazon Dropshipping Product Finder** when you have picked the category and
  need weight and dimensions to work out the margin.
- **Amazon BSR Tracker** to watch the incumbents after you decide to enter.
- **Amazon Bestsellers Scraper** for the same category with all sixty-four
  fields.
- **Amazon Search Results Scraper** when the niche is defined by a search term
  rather than a category.

### Questions people ask

**Why is boughtInPastMonth empty on half the category.** Amazon only prints it
above a volume threshold. On a bestseller list the top is usually filled and the
tail is usually not, and that pattern is itself information.

**Are the revenue estimates reliable.** They are Amazon's own rounded units
figure times the current price. Good enough to rank a category, not good enough
to build a business plan on. Nothing public is.

**How many products per category.** Amazon shows up to a hundred per bestseller
list. Set the maximum to zero and it takes them all.

**Can I crawl subcategories automatically.** Give the subcategory links directly.
This Actor does not walk down a category tree on its own, because doing so
quietly multiplies what you are charged.

**What is the difference between this and the dropshipping finder.** That one
adds weight and dimensions and is pointed at picking a product. This one adds the
badges and the full breadcrumb and is pointed at judging a category.

**How often should I run it.** Once when you are choosing, then monthly if you
want to watch the niche change.

### What it does not collect

No review text, no reviewer names, no customer questions, no seller names. You
get the aggregate rating and the count, which are facts about a product rather
than about a person.

### Legal note

This Actor reads public pages and takes product facts: prices, ranks, demand
figures, aggregate ratings, offer counts. Business information about items, not
information about people.

You are responsible for what you do with the output. Check Amazon's terms for
your own use case.

# Actor input Schema

## `search` (type: `array`):

Anything that lists products: a plain search term ("tower fan"), an Amazon search URL, a category link, or a bestsellers page. Each one is crawled and every product found is scraped. Use this when you do not know the ASINs up front.

## `productUrls` (type: `array`):

Amazon product URLs or bare ASINs, one per line. Leave empty if you are using Search instead. Duplicates are removed so you are never charged twice.

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

Which Amazon site to read. The currency of the price follows the marketplace and the proxy country.

## `proxyCountry` (type: `string`):

Which country the requests should appear to come from. Leave empty and it follows the marketplace: amazon.de is read from Germany, amazon.co.uk from the UK. This matters more than it looks -- Amazon shows different prices, currencies and even availability depending on where you appear to be.

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

Hard ceiling on delivered products. 0 means no ceiling: the Actor keeps going until the lists run out or your limits stop it.

## `maxItemsPerList` (type: `integer`):

Products to take from each search term or category link. Up to 10000.

## `maxListPages` (type: `integer`):

Result pages to walk per list. Up to 100. Amazon itself stops earlier on most searches.

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

Datacenter proxies were enough in testing: 30 out of 30 products returned with zero blocks. They are the cheaper option and the default. Switch to residential if you start seeing blocked pages at higher volume. Running without any proxy stops after roughly 85-120 products, because Amazon closes the door on a single IP address for over an hour.

## `lanes` (type: `integer`):

How many products to read at the same time. Each lane uses its own exit address, so more lanes never means asking one address more often. Eight is the tested default and the most accurate. Sixteen finishes the same sixty products in about half the time, but measured on 2026-08-24 it returned six more products without a price, because Amazon strips the buy box sooner under pressure. Raise it when speed matters more than the last few prices.

## `maxAttempts` (type: `integer`):

How often to retry a product Amazon refuses, each time from a different exit IP. A refusal is a property of one address, not of the product, and a refused attempt costs about 4 KB. Twelve tries is cheap insurance against a run that comes back short.

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

After half the attempts have failed, retry through residential addresses instead of datacenter ones. Measured 2026-08-26: residential transfer was 90 percent of the bill on a sixty product run ($0.150 of $0.167) while a run that never touched it delivered all sixty anyway. Leave it off unless you are losing products; turn it on when a marketplace refuses everything.

## `economical` (type: `boolean`):

Hang up on each product page once the price is in, instead of reading it to the end. Roughly three times less traffic and about three times faster. Measured cost: over 30 products this lost 2 ratings, 4 review counts and 1 brand, because Amazon sometimes puts the rating below the price. Prices were identical either way. Leave this off unless you only need prices and are paying per gigabyte.

## `minDelayMs` (type: `integer`):

Pause between products. Measured 2026-08-23: at 1-2 seconds this returned 10 of 15 products; at 8-15 seconds it returned 12 of 15 on the same list. Pace turned out to matter more than anything else. The market leader waits about 14 seconds per product.

## `maxDelayMs` (type: `integer`):

Upper bound for the pause between products. The actual pause is random between the minimum and this value, which looks less mechanical than a fixed interval.

## `retryPauseMs` (type: `integer`):

How long to wait before trying a refused product again. Kept short because the retry already switches to a different exit IP, and waiting longer only makes the run more expensive.

## Actor input object example

```json
{
  "search": [
    "https://www.amazon.com/gp/bestsellers/kitchen"
  ],
  "productUrls": [],
  "marketplace": "com",
  "maxItems": 0,
  "maxItemsPerList": 10,
  "maxListPages": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "lanes": 8,
  "maxAttempts": 12,
  "residentialFallback": false,
  "economical": false,
  "minDelayMs": 8000,
  "maxDelayMs": 15000,
  "retryPauseMs": 300
}
```

# Actor output Schema

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

One row per product with demand and competition signals. Rows without a price are delivered in full and never charged for.

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

Counts per outcome, exit addresses used, bytes per charged result.

# 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 = {
    "search": [
        "https://www.amazon.com/gp/bestsellers/kitchen"
    ],
    "productUrls": [],
    "maxItemsPerList": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("amazonscrapers/amazon-niche-research").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 = {
    "search": ["https://www.amazon.com/gp/bestsellers/kitchen"],
    "productUrls": [],
    "maxItemsPerList": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("amazonscrapers/amazon-niche-research").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 '{
  "search": [
    "https://www.amazon.com/gp/bestsellers/kitchen"
  ],
  "productUrls": [],
  "maxItemsPerList": 10
}' |
apify call amazonscrapers/amazon-niche-research --silent --output-dataset

```

## MCP server setup

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

```

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/CirqceU4BbwkrZ48s/builds/IJyQ6ig84rGOewx5U/openapi.json
