# Amazon Product Finder - ASIN Search by Filters (`cyprusapi/amazon-product-finder`) Actor

Find Amazon products by criteria instead of by ASIN. Filter on price, sales rank, rating, reviews, category, brand and dozens more - including historical values. Returns up to 10,000 matching ASINs per run. Errors are never charged.

- **URL**: https://apify.com/cyprusapi/amazon-product-finder.md
- **Developed by:** [Torchtechnology LTD](https://apify.com/cyprusapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 matching asins

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 Product Finder

Find Amazon products by **what they are** instead of by what they are called.

A keyword search can only return what Amazon's search box returns. This Actor
queries a product database that already holds the catalogue and its history,
so you can ask for things a search box cannot answer:

> every Electronics product on amazon.de between €20 and €50, with a sales
> rank under 30,000, at least 4.3 stars, fewer than 5 competing new offers,
> and a Buy Box price that dropped by more than 20 % over the last 90 days

You get back the ASINs that match, in the order you asked for.

***

### ⚠️ This Actor returns ASINs, not product details

**The result of a run is a list of ASINs. There are no titles, no prices, no
images, no ratings in the output.** That is what this endpoint does: it is a
fast, cheap filter over the whole catalogue, and it answers with identifiers.

To turn the ASINs into full product records — title, brand, images, current
and historical prices, sales rank, dimensions, FBA fees — feed the dataset of
this run into **[Amazon Product Data](https://apify.com/store)**. The two are
built to be chained: this Actor decides *which* products, that one fetches
*what they are*.

Each result item looks like this:

```json
{
  "asin": "B0CHX1W1XY",
  "marketplace": "de",
  "url": "https://www.amazon.de/dp/B0CHX1W1XY",
  "position": 1,
  "scrapedAt": "2026-08-21T09:14:02Z"
}
```

***

### What you can filter on

Every filter is optional, and all of them are combined with **AND**. Inside a
list field (brands, categories, …) the entries are combined with **OR**. You
must set at least one filter — an empty query would match the entire
catalogue, and the run refuses to start rather than bill you for that.

#### Ready-made fields

| Field | What it does |
|---|---|
| **Title keywords** | Whole words the title must contain. `"digital camera" Canon` requires the phrase *and* the word; `-refurbished` excludes a word. |
| **Brands**, **Manufacturers** | Up to 50 names each, case-insensitive. |
| **Root category IDs**, **Include / Exclude category IDs** | Amazon browse-node IDs. Root categories match anywhere in the tree; include/exclude match direct listings. |
| **Which price to filter on** + **Minimum / Maximum price** | Buy Box, lowest new, Amazon's own, lowest used, lowest new FBA or list price. Given in the marketplace's currency, e.g. `25` for $25.00. |
| **Minimum / Maximum sales rank** | Current sales rank. Lower is better. |
| **Minimum / Maximum rating** | In stars, 0–5. |
| **Minimum / Maximum review count** | Number of reviews. |
| **Minimum / Maximum units sold last month** | Amazon's "bought in past month" figure, where it is published. |
| **Minimum / Maximum number of new offers** | How much competition the listing has. |
| **Product type** | Standard, downloadable, e-book or variation parent. |
| **Amazon availability** | In stock, pre-order, back-order, delayed, unknown, or no Amazon offer at all. |
| **Only products that have reviews / where Amazon holds the Buy Box / exclude adult products** | Simple switches. |
| **Sort results by** + **Sort direction** | Sales rank, price, rating, reviews, monthly sales, sales-rank drops, tracking age or last price change. |

#### `advancedFilters` — the other few hundred criteria

The fields above cover the common cases. The underlying query language is much
larger, and `advancedFilters` is a raw JSON object that is **merged into the
query as-is**, so nothing is out of reach:

```json
{
  "deltaPercent90_BUY_BOX_SHIPPING_gte": 20,
  "isLowest90_NEW": true,
  "outOfStockPercentage90_lte": 5,
  "packageWeight_lte": 2000,
  "salesRankDrops30_gte": 15,
  "isSNS": true
}
```

A key you set here **overrides** the matching ready-made field, so you can
start from the simple form and override one detail.

##### The grammar

Most historical criteria follow one systematic pattern:

```
<family><window>_<PRICE_TYPE>_<bound>
```

| Part | Values |
|---|---|
| `family` | `current`, `avg`, `delta`, `deltaPercent`, `deltaLast`, `lastPriceChange`, `backInStock`, `isLowest`, `isLowest90` |
| `window` | `1`, `7`, `30`, `90`, `180`, `365` — days, for the families that take one (`avg30`, `delta90`, `deltaPercent7`, …) |
| `PRICE_TYPE` | `AMAZON`, `NEW`, `USED`, `SALES`, `LISTPRICE`, `COLLECTIBLE`, `REFURBISHED`, `NEW_FBM_SHIPPING`, `LIGHTNING_DEAL`, `WAREHOUSE`, `NEW_FBA`, `COUNT_NEW`, `COUNT_USED`, `COUNT_REFURBISHED`, `COUNT_COLLECTIBLE`, `RATING`, `COUNT_REVIEWS`, `BUY_BOX_SHIPPING`, `USED_NEW_SHIPPING`, `USED_VERY_GOOD_SHIPPING`, `USED_GOOD_SHIPPING`, `USED_ACCEPTABLE_SHIPPING`, `REFURBISHED_SHIPPING`, `TRADE_IN` |
| `bound` | `_gte` (at least) or `_lte` (at most). The same value on both means an exact match. The boolean families take no bound. |

Examples: `avg90_NEW_lte`, `current_COUNT_REVIEWS_gte`, `deltaPercent30_AMAZON_gte`,
`isLowest_BUY_BOX_SHIPPING`, `backInStock_NEW`.

Beyond the price families there are plain field filters, most with
`_gte` / `_lte` bounds:

- **Attributes** — `partNumber`, `model`, `color`, `size`, `edition`, `format`,
  `author`, `binding`, `genre`, `languages`, `publisher`, `platform`,
  `itemForm`, `scent`, `material`, `pattern`, `style`, `unitType`,
  `itemTypeKeyword`, `targetAudienceKeyword`, `activeIngredients`,
  `brandStoreName`, `frequentlyBoughtTogether` (all string lists)
- **Physical** — `packageLength/Width/Height` (mm), `packageWeight` (g),
  `itemLength/Width/Height`, `itemWeight`, `packageQuantity`,
  `numberOfItems`, `numberOfPages`
- **Media & variations** — `imageCount`, `videoCount`, `variationCount`,
  `hasMainVideo`, `hasAPlus`, `singleVariation`, `hasParentASIN`
- **Stock & deals** — `outOfStockPercentage90`, `outOfStockCountAmazon30/90`,
  `couponOneTimeAbsolute`, `couponOneTimePercent`, `couponSNSPercent`,
  `dealType`, `isDeal`, `lightningStart`, `lightningEnd`
- **Buy Box & sellers** — `buyBoxIsFBA`, `buyBoxIsUnqualified`,
  `buyBoxSellerId`, `sellerIds`, `sellerIdsLowestFBA`, `sellerIdsLowestFBM`,
  `buyBoxStatsAmazon30/90/180/365`, `buyBoxStatsSellerCount30/90/180/365`
- **Ranking history** — `salesRankDrops30/90/180/365`, `salesRankReference`,
  `salesRankDisplayGroup`
- **Flags** — `isHazMat`, `isHeatSensitive`, `isAdultProduct`, `isSNS`,
  `isPrimeExclusive`, `isMerchOnDemand`, `batteriesRequired`,
  `batteriesIncluded`, `isEligibleForSuperSaverShipping`
- **Lifecycle** — `trackingSince`, `listedSince`, `lastPriceChange`,
  `lastOffersUpdate`, `releaseDate`, `publicationDate`

##### Three things to watch in `advancedFilters`

1. **Prices are integers in the smallest currency unit.** `4200` means €42.00.
   (The ready-made price fields do this conversion for you; this one does not.
   Japanese yen has no minor unit: `3199` means ¥3,199.)
2. **Dates are counted in minutes since 2011-01-01T00:00:00Z**, not ISO dates.
3. **`page` and `perPage` are ignored.** Paging is driven by *Maximum ASINs* so
   that no page is fetched — or paid for — twice. `sort` and `minMatch` are
   accepted; `sort` takes up to three `[field, "asc"|"desc"]` pairs, and
   `minMatch` sets how many entries of a list filter must match, e.g.
   `{"minMatch": {"brand": 2}}`.

Every list filter accepts at most 50 entries. Prefix a string value with `✜`
to exclude it.

***

### Search insights (optional)

Switch on **Include search insights** to also get aggregate statistics over
the *entire* match set — not just the page you fetched: average Buy Box price
now / 90 days / 365 days, average rating and review count, the share sold by
Amazon and by FBA, coupon share, seller and brand counts, best and worst sales
rank, top brands and top sellers with their counts.

They are written to the run's key-value store as **`SEARCH_INSIGHTS`** rather
than into the dataset, so that the dataset stays one clean row per ASIN.
Insights are charged as their own event, and only if they actually come back.

***

### Limits and cost

| | |
|---|---|
| ASINs per run | up to **10,000** (upstream ceiling for one query) |
| Page size | 50 – 1,000 rows; 50 is the smallest page the data source will serve |
| Marketplaces | US, UK, DE, FR, IT, ES, NL, CA, MX, BR, AU, JP, IN |
| Billing | one charge per **ASIN delivered**, plus one charge if search insights are returned |

Because the smallest page holds 50 rows, asking for 10 ASINs and asking for 50
cost the data source the same; only your bill differs.

Note that pages are not cached upstream, so the ordering can shift slightly
between pages of a very large query. This Actor de-duplicates ASINs across
pages, so you never get the same ASIN twice.

***

### What is never charged

- Runs that fail validation before any data is fetched.
- Items marked `error` — the request was rejected upstream.
- Items marked `currentlyUnavailable` — shared capacity was momentarily used
  up. The run still finishes successfully; retry in a few minutes.
- An empty result set, reported as a single `notFound` item.

Every run also writes a **`RUN_SUMMARY`** record with `requested`,
`delivered`, `totalMatches`, `notFound`, `unavailable`, `failed` and
`unitsSpent`.

***

### Recipes

**Private-label opportunity scan (US):**
`rootCategories: [3760901]`, `minPrice: 15`, `maxPrice: 45`,
`maxSalesRank: 60000`, `minRating: 4`, `maxReviewCount: 120`,
`maxOfferCountNew: 3`, `sortBy: monthlySold`, `sortOrder: desc`

**Recent price crashes worth repricing against:**
`advancedFilters: {"deltaPercent90_BUY_BOX_SHIPPING_gte": 25, "current_COUNT_REVIEWS_gte": 100}`,
`sortBy: salesRank`

**Everything a brand sells in a market:**
`brands: ["ExampleBrand"]`, `maxItems: 10000`, `sortBy: salesRank`

# Actor input Schema

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

Which Amazon marketplace to search. Prices below are interpreted in this marketplace's currency.

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

How many matching ASINs this run may return, at most 10,000. Billing is one charge per ASIN delivered. Note that a page never holds fewer than 50 rows upstream, so a very small cap saves time but not much money.

## `titleQuery` (type: `string`):

Space-separated keywords the product title must contain, up to 50. Whole words only - no partial matches. Put a phrase in double quotes ("digital camera"), and prefix a word with a minus to exclude it (-refurbished).

## `brands` (type: `array`):

Match any of these brands, case-insensitive. Up to 50 entries.

## `manufacturers` (type: `array`):

Match any of these manufacturers, case-insensitive. Up to 50 entries.

## `rootCategories` (type: `array`):

Only products inside these Amazon root categories (browse node IDs), for example 172282 for Electronics on amazon.com. Up to 50 entries.

## `categoriesInclude` (type: `array`):

Only products listed directly in these sub-categories (browse node IDs). Up to 50 entries.

## `categoriesExclude` (type: `array`):

Drop products listed directly in these sub-categories (browse node IDs). Up to 50 entries.

## `priceType` (type: `string`):

The price series that the minimum and maximum price below apply to. Buy Box is the price a customer actually pays; New is the lowest new offer; Amazon is Amazon's own offer.

## `minPrice` (type: `string`):

Lowest acceptable current price, in the marketplace's currency (for example 25 for $25.00). Leave empty for no lower bound. Lowest price to include, e.g. "24.99". Decimals are allowed - enter the price as shown on Amazon, in the marketplace currency.

## `maxPrice` (type: `string`):

Highest acceptable current price, in the marketplace's currency. Leave empty for no upper bound. Highest price to include, e.g. "199.00". Decimals are allowed - enter the price as shown on Amazon, in the marketplace currency.

## `minSalesRank` (type: `integer`):

Lower bound on the current sales rank. A higher rank number means a slower seller, so use this to exclude the very top of a category.

## `maxSalesRank` (type: `integer`):

Upper bound on the current sales rank, for example 50000 to keep only reasonably fast sellers.

## `minRating` (type: `string`):

Lowest acceptable star rating, from 0 to 5. Products without a rating are excluded once this is set. Star rating from 1 to 5, decimals allowed, e.g. "4.3".

## `maxRating` (type: `string`):

Highest acceptable star rating, from 0 to 5. Useful for finding weak listings in a strong category. Star rating from 1 to 5, decimals allowed, e.g. "4.3".

## `minReviewCount` (type: `integer`):

Lowest acceptable number of reviews.

## `maxReviewCount` (type: `integer`):

Highest acceptable number of reviews, for example 50 to find niches that are not yet crowded.

## `minMonthlySold` (type: `integer`):

Lower bound on Amazon's "bought in past month" figure. Amazon publishes it for a minority of products only, so this filter also excludes everything without the figure.

## `maxMonthlySold` (type: `integer`):

Upper bound on Amazon's "bought in past month" figure.

## `minOfferCountNew` (type: `integer`):

Lower bound on how many new marketplace offers the product currently has.

## `maxOfferCountNew` (type: `integer`):

Upper bound on how many new marketplace offers the product currently has, for example 3 to find products with little competition.

## `productType` (type: `string`):

Restrict to one kind of catalogue entry. Variation parents carry only a sales rank and their child variations.

## `availability` (type: `array`):

Keep only products whose Amazon offer is in one of these states. Leave empty to accept any state.

## `onlyWithReviews` (type: `boolean`):

Drop products without a single review.

## `onlyBuyBoxByAmazon` (type: `boolean`):

Keep only products whose Buy Box is currently won by Amazon itself.

## `excludeAdultProducts` (type: `boolean`):

Drop everything flagged as an adult product.

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

Which field orders the result set. The default is the current sales rank, ascending - best sellers first.

## `sortOrder` (type: `string`):

Ascending starts with the smallest value, which for sales rank means the best sellers.

## `advancedFilters` (type: `object`):

Anything the fields above do not cover, merged into the query as-is. Keys follow the pattern <family><window>*\<PRICE\_TYPE>*\<gte|lte>, for example {"deltaPercent90\_BUY\_BOX\_SHIPPING\_gte": 20, "isLowest90\_NEW": true, "outOfStockPercentage90\_lte": 5}. Prices here are integers in the smallest currency unit (cents), and dates are in the upstream minute format - the fields above do that conversion for you, this one does not. A key set here overrides the matching field above. "page" and "perPage" are ignored: paging is driven by "Maximum ASINs". See the README for the full grammar.

## `includeSearchInsights` (type: `boolean`):

Adds aggregate statistics over the entire match set - average Buy Box price, average rating, share sold by Amazon, top brands and sellers - stored as SEARCH\_INSIGHTS in the key-value store. Charged as a separate event, only when the statistics are actually returned.

## `maxWaitSeconds` (type: `integer`):

If the shared data capacity is momentarily used up, wait up to this long for it to refill. Anything still unserved afterwards is reported as currently unavailable - and never charged.

## `apiKey` (type: `string`):

Advanced: run this Actor against your own upstream account instead of the bundled capacity. Leave empty to use the included capacity.

## Actor input object example

```json
{
  "marketplace": "com",
  "maxItems": 10,
  "brands": [],
  "manufacturers": [],
  "rootCategories": [],
  "categoriesInclude": [],
  "categoriesExclude": [],
  "priceType": "buyBox",
  "productType": "any",
  "availability": [],
  "onlyWithReviews": false,
  "onlyBuyBoxByAmazon": false,
  "excludeAdultProducts": false,
  "sortBy": "salesRank",
  "sortOrder": "asc",
  "advancedFilters": {},
  "includeSearchInsights": false,
  "maxWaitSeconds": 60
}
```

# Actor output Schema

## `results` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("cyprusapi/amazon-product-finder").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("cyprusapi/amazon-product-finder").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 '{}' |
apify call cyprusapi/amazon-product-finder --silent --output-dataset

```

## MCP server setup

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

```

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/usfQp2aIxOFlwLFQW/builds/HwGOQc9bwQpnamYpu/openapi.json
