# China Supplier Price Comparator: Alibaba & Made-in-China (`mdcurt/china-supplier-price-comparator`) Actor

Compare wholesale supplier offers for any product keyword across Alibaba.com and Made-in-China.com in one run: unit price in USD, MOQ, supplier, badges, ratings and landed cost per unit. No login, no browser.

- **URL**: https://apify.com/mdcurt/china-supplier-price-comparator.md
- **Developed by:** [Matthew Curtis](https://apify.com/mdcurt) (community)
- **Categories:** E-commerce, AI
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 supplier offers

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

## China Supplier Price Comparator: Alibaba & Made-in-China

Type a product keyword and get the supplier offers for it from **Alibaba.com** and **Made-in-China.com** in one dataset with the same fields: unit price in USD, minimum order quantity, supplier, years on the platform, badges, ratings, and the landed cost per unit for your quantity, duty rate and freight. No login, no browser, no API key.

### What it does

Each keyword is searched on both marketplaces. Every offer on the result pages becomes one record, whichever site it came from. A free `COMPARISON` record in the key-value store answers the question most runs are for: the cheapest offer, the cheapest offer your quantity can actually order, and each marketplace's median price and median minimum order.

Measured on 2026-11-14: first record in about 2 seconds, 80 offers in 3 seconds, 7,780 offers for 40 keywords in 132 seconds (about 3,500 offers per minute) with no failed or blocked request.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `queries` | string\[] | required | Product keywords, one per entry (`"yoga mat"`). Up to 50. URLs are rejected and listed in `SUMMARY.invalidQueries`. |
| `marketplaces` | string\[] | both | `made-in-china`, `alibaba` or both. |
| `maxItems` | integer | 80 | Total offer records (1–20000), split evenly: every keyword gets the same share on every marketplace, from the top of the result list. |
| `quantity` | integer | 100 | Units you want to buy. Drives `meetsMoq`, `orderQuantity` and `orderCost`. |
| `dutyRatePercent` | number | 0 | Import duty in percent, applied to the unit price. |
| `freightPerUnitUsd` | number | 0 | Your freight estimate per unit in USD. |
| `proxyConfiguration` | object | Apify Proxy | Datacenter proxies work for both sites. |

### Output

One record per offer:

```json
{
  "kind": "offer",
  "id": "alibaba:1600845559950",
  "marketplace": "alibaba",
  "url": "https://www.alibaba.com/product-detail/Water-Dispenser-Cooler-Wall-Mounted-Bottle_1600845559950.html",
  "title": "Wall Mounted Outdoor Stainless Steel Water Dispenser Cooler Electric Powered Bottle Filling Station Fountain",
  "price": 380,
  "priceMax": 500,
  "currency": "USD",
  "originalPrice": 380,
  "originalPriceMax": 500,
  "originalCurrency": "USD",
  "moq": 10,
  "moqUnit": "units",
  "seller": "Suzhou Puretal Electric Co., Ltd.",
  "sellerUrl": "https://puretal.en.alibaba.com/company_profile.html",
  "sellerType": null,
  "sellerYears": 10,
  "sellerBadges": [
    "Gold Supplier"
  ],
  "sellerRating": 5,
  "productRating": 5,
  "soldText": "177 sold",
  "location": "China",
  "images": [
    "https://s.alicdn.com/@sc04/kf/Hb144ec8caf104d5ebec2e1724a97ea8aF.png"
  ],
  "sponsored": false,
  "rank": 2,
  "titleMatch": 1,
  "meetsMoq": true,
  "landedCost": 408.8,
  "landedCostMax": 537.8,
  "orderQuantity": 500,
  "orderCost": 204400,
  "query": "stainless steel water bottle",
  "scrapedAt": "2026-11-14T20:48:43.858Z"
}

```

How the computed fields work:

- `price` / `priceMax` are the two ends of the price range the supplier shows, in USD. Suppliers quote the low end for large orders. The listing does not say at which quantity each end applies, so both are kept.
- `landedCost = price × (1 + dutyRatePercent / 100) + freightPerUnitUsd`, and `landedCostMax` is the same on `priceMax`.
- `meetsMoq` says whether your `quantity` reaches the minimum order. `orderQuantity` is the larger of the two and `orderCost = landedCost × orderQuantity`, the cheapest order you could place with that supplier.
- `titleMatch` is the share of your keyword's words found in the title. Offers that share no word with the keyword are dropped and never charged (`SUMMARY.irrelevantSkipped`). The comparison only uses offers at 1.
- `sponsored` marks paid placements. `rank` is the position on the marketplace's own result list, ads included.
- Alibaba.com records carry `sellerYears`, `sellerRating`, `productRating`, `soldText` and the Gold Supplier badge. Made-in-China.com records carry `sellerType` (Manufacturer/Factory, Trading Company) where shown, the province in `location`, and badges such as Diamond Member and Audited Supplier.

The key-value store holds two free records. `COMPARISON` has one block per keyword: `cheapest`, `cheapestMeetingMoq`, `lowestOrderCost`, `cheaperMarketplaceByMedian`, and per marketplace the offer count, `minPrice`, `medianPrice` and `medianMoq`. `SUMMARY` has the counts per search, keywords that returned nothing, any marketplace stopped by a challenge page, latency and compute time.

### Pricing

Pay per event: $0.005 per run plus $0.0015 per offer record (Store discount tiers lower both by 10 to 30 % on paid Apify plans). `COMPARISON` and `SUMMARY` are free.

| Run | Cost |
|---|---|
| 1 keyword, top 5 offers per marketplace (10 records) | $0.005 + 10 × $0.0015 = $0.02 |
| 1 keyword, both marketplaces, 80 offers | $0.005 + 80 × $0.0015 = $0.125 |
| 40 keywords, 8,000 offers | $0.005 + 8,000 × $0.0015 = $12.005 |

Alibaba scrapers on the Store have a median price of $0.003 per result. This Actor charges half of that and returns two marketplaces already normalised and costed.

### For AI agents

Pass `queries` (one or more plain product keywords) and a small `maxItems`. Read the `COMPARISON` record first: it holds the cheapest offer and the median USD price per marketplace for each keyword, so you rarely need to rank the offer records yourself. A lookup of two keywords with 20 offers returns in about 5 seconds and costs $0.005 + 20 × $0.0015 = $0.035. Prices are supplier list prices before negotiation. `landedCost` only includes the duty and freight you passed in.

### Monitoring prices

Schedule the Actor with the same keywords and compare runs with [mdcurt/dataset-diff-monitor](https://apify.com/mdcurt/dataset-diff-monitor) keyed on `id`: it reports offers that appeared, disappeared, or changed `price` or `moq`.

### Tutorials

- **Minimum orders on Alibaba.com and Made-in-China.com, 40 products** in `examples/minimum-order-comparison/` of the Actor source: a real 7,900-offer sample (2026-11-14, 280 requests, 0 failed), the per-keyword table, the 89 cases where the same supplier lists the same keyword on both sites, and the script that rebuilds every number. Finding: the median minimum order is 10 units on Alibaba.com and 100 on Made-in-China.com.

### Speed

From the live tests on 2026-11-14: first record after 1.5–2.5 s. 80 offers in 2.7 s, 540 offers in 17.5 s, 7,780 offers (40 keywords × 2 marketplaces, 278 requests) in 132 s. One request returns 30 offers on Made-in-China.com and 40 on Alibaba.com.

### Limitations

- Listing pages only. Quantity price breaks, lead times and certificates are on the product pages, which this Actor does not open.
- Alibaba.com is read through its China catalogue pages, so its offers are from suppliers in China. A keyword Alibaba has no catalogue page for is tried once more in its other number ("phone case" → "phone cases"). If that fails too, the keyword is listed in `SUMMARY.emptySearches` for Alibaba (1 of 40 test keywords).
- 1688, AliExpress and Yiwugo are not included. In testing each answered automated requests with a login wall or a bot challenge, and this Actor does not log in or work around challenges. If a marketplace serves a challenge page during a run, its remaining searches are skipped, nothing is retried, and `SUMMARY.marketplacesStopped` says so.
- A keyword search returns similar products, not one identical item. The cheapest offer is the cheapest offer matching your words. Narrow the keyword (`"tpe yoga mat 6mm"`) to compare like with like.
- About 1 % of Made-in-China.com offers show no price. They are returned with `price: null` and left out of the comparison.
- Minimum-order units are kept as the supplier writes them (Pieces, pieces, Sets, Meters). The Actor does not convert between units.
- Up to 20 result pages per keyword on Made-in-China.com (600 offers) and 15 on Alibaba.com (600 offers).
- Duty and freight are your inputs. This is an estimate for comparing offers, not a customs calculation.
- Only what the marketplaces show publicly is returned: product, price, company name and badges. Images are links.

### Changelog

- 1.0.0 (2026-11-14): first release.

# Actor input Schema

## `queries` (type: `array`):

One product keyword per entry, as you would type it into a wholesale search box (e.g. "yoga mat", "stainless steel water bottle"). Each keyword is searched on every selected marketplace and returns one record per supplier offer: unit price in USD, minimum order, supplier, badges, ratings and landed cost. First record in about 2 seconds. Up to 50 keywords per run.

## `marketplaces` (type: `array`):

Where to search. made-in-china = Made-in-China.com (30 offers per request). alibaba = Alibaba.com supplier offers from its China catalogue pages (40 per request). Listing pages only; both quote in US dollars. Default: both.

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

Maximum number of offer records in total (1–20000). It is split evenly: each keyword gets the same share on each marketplace, taken from the top of that marketplace's result list. 80 with one keyword and both marketplaces = the first 40 offers of each.

## `quantity` (type: `integer`):

How many units you want to buy. Used for meetsMoq (is your quantity at or above the supplier's minimum order?), orderQuantity and orderCost (landed cost × the larger of your quantity and the minimum order).

## `dutyRatePercent` (type: `number`):

Duty rate applied to the unit price for the landed-cost fields, in percent (e.g. 25 for a 25 % tariff). 0 = no duty. landedCost = price × (1 + duty / 100) + freight per unit.

## `freightPerUnitUsd` (type: `number`):

Your shipping cost estimate per unit in US dollars, added to the landed cost (e.g. 0.8). 0 = compare ex-works prices only.

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

Apify Proxy settings. Datacenter proxies work for both marketplaces; switch to a RESIDENTIAL group only if the SUMMARY record reports blocked pages.

## Actor input object example

```json
{
  "queries": [
    "yoga mat"
  ],
  "marketplaces": [
    "made-in-china",
    "alibaba"
  ],
  "maxItems": 80,
  "quantity": 100,
  "dutyRatePercent": 0,
  "freightPerUnitUsd": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `records` (type: `string`):

One record per supplier offer: id, marketplace, title, url, price and priceMax in USD, moq, seller, years, badges, ratings, sold text, location, landedCost, orderCost, meetsMoq, titleMatch, query.

## `comparison` (type: `string`):

COMPARISON record: per keyword the cheapest offer overall, the cheapest offer your quantity can order, the lowest order cost, and per marketplace the offer count, min and median USD price and median minimum order.

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

SUMMARY record: counts per search, empty searches, marketplaces stopped by a challenge page, blocked pages, p95 latency, time to first record and compute seconds.

# 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 = {
    "queries": [
        "yoga mat"
    ],
    "marketplaces": [
        "made-in-china",
        "alibaba"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mdcurt/china-supplier-price-comparator").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 = {
    "queries": ["yoga mat"],
    "marketplaces": [
        "made-in-china",
        "alibaba",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("mdcurt/china-supplier-price-comparator").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 '{
  "queries": [
    "yoga mat"
  ],
  "marketplaces": [
    "made-in-china",
    "alibaba"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call mdcurt/china-supplier-price-comparator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mdcurt/china-supplier-price-comparator"
        }
    }
}
```

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/P84sKhlFWpRLCkMTM/builds/0gGId44o87IlFkSWR/openapi.json
