# 1688 Supplier Price & MOQ Monitor (`zinin/china-1688-supplier-monitor`) Actor

Monitor public 1688 wholesale offers for price tiers, MOQ, stock, supplier and promotion changes.

- **URL**: https://apify.com/zinin/china-1688-supplier-monitor.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.10 / 1,000 1688 product checkeds

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/platform/actors/running/actors-in-store#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

## 1688 Supplier Price & MOQ Monitor

Monitor a fixed list of public 1688 wholesale offers and receive one structured row
per successful check. Track price tiers, minimum order quantity, public stock,
supplier identity, badges and promotions without a 1688 login.

This Actor is built for scheduled procurement monitoring, sourcing teams and agents
that need stable JSON instead of repeatedly reading product pages. It does not search
1688: you submit the exact offer URLs you are permitted to monitor.

### What it monitors

- wholesale price range and quantity-price tiers;
- MOQ, public bookable stock and unit;
- offer title and stable offer ID;
- supplier ID, company name and login ID;
- public supplier badges and promotion labels;
- deterministic field-level changes against the previous successful run of the same
  `watchName`.

The first successful check creates a baseline. Later checks return `changed` or
`no_change`. A blocked, malformed or partial page is unknown state: it produces an
honest free error row and never erases or advances the previous baseline.

### Quick start

```json
{
  "productUrls": [
    "https://detail.1688.com/offer/1000406623486.html"
  ],
  "watchName": "main-supplier-watch",
  "maxChanges": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "CN"
  }
}
```

Run this input once to create a baseline, then add an Apify Schedule using the same
`watchName`. Use a different watch name for a logically independent procurement list.
If an owner-token portal calls the Actor for multiple customers, the portal must
prefix `watchName` with its authenticated tenant ID; never accept a tenant namespace
from an unauthenticated request.

### Input

| Field | Required | Description |
| --- | --- | --- |
| `productUrls` | yes | 1–50 public URLs in the exact `https://detail.1688.com/offer/<id>.html` form. Query and fragment are stripped. |
| `watchName` | yes | Stable baseline scope, 1–80 characters. Keep it unchanged across scheduled runs. |
| `maxChanges` | no | Stop checking new targets after this many `changed` rows, 1–50; default 20. |
| `proxyConfiguration` | no | Residential CN is the tested default. Custom proxy URLs are allowed; direct fallback is not. |

Only HTTPS `detail.1688.com` product URLs are accepted as input. After strict ID
normalization, the Actor fetches the matching robots-allowed public
`https://m.1688.com/offer/<id>.html` document as its evidence page. Credentials,
custom ports, arbitrary hosts and non-offer paths are rejected before network access.
Redirects to login, challenge or any other URL are refused.
Up to three bounded fresh proxy sessions may be tried when public HTML is incomplete;
an attempt succeeds only after the offer is semantically parsed. This does not solve
or bypass challenges.

### Output

Each successfully parsed product creates exactly one paid Dataset row. The important
fields are:

```json
{
  "watchName": "main-supplier-watch",
  "source": "1688",
  "targetId": "1000406623486",
  "targetUrl": "https://detail.1688.com/offer/1000406623486.html",
  "evidenceUrl": "https://m.1688.com/offer/1000406623486.html",
  "found": true,
  "changeType": "changed",
  "changedFields": ["priceMin", "priceTiers", "promotions"],
  "previous": {"offerId": "1000406623486", "priceMin": 4.8},
  "current": {
    "offerId": "1000406623486",
    "title": "Example wholesale offer",
    "priceMin": 4.5,
    "priceMax": 5.2,
    "currency": "CNY",
    "priceTiers": [{"beginAmount": 10, "price": 5.2}, {"beginAmount": 100, "price": 4.5}],
    "moq": 10,
    "stock": 8000,
    "unit": "件",
    "supplier": {"id": "b2b-example", "name": "Example Supplier", "loginId": "example"},
    "badges": [],
    "promotions": []
  },
  "partial": false,
  "partialReason": "",
  "error": "",
  "checkedAt": "2026-08-06T05:00:00.000Z",
  "isDemo": false
}
```

`baseline_created`, `changed` and `no_change` are all successful checks: they incur
the same retrieval cost and each is one paid row. Error rows have `partial: true`,
preserve the previous snapshot and are free. The `OUTPUT` key-value record contains
terminal status, counters and the baseline-store name.

### Pricing

Pay per event: **$0.005 per run start + $0.006 per successfully delivered product
check** on the FREE tier. Errors and partial rows are free. Account-tier discounts
follow the standard six-step ladder:

| Tier | Start | Product check | Discount |
| --- | ---: | ---: | ---: |
| FREE | $0.00500 | $0.00600 | 0% |
| BRONZE | $0.00475 | $0.00570 | 5% |
| SILVER | $0.00450 | $0.00540 | 10% |
| GOLD | $0.00425 | $0.00510 | 15% |
| PLATINUM | $0.00410 | $0.00492 | 18% |
| DIAMOND | $0.00400 | $0.00480 | 20% |

The Dataset delivery and the `item-checked` charge use one SDK call. If pricing or
the remaining charge budget cannot be verified, paid work fails closed.

### API and automation

#### JavaScript

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('zinin/china-1688-supplier-monitor').call({
  productUrls: ['https://detail.1688.com/offer/1000406623486.html'],
  watchName: 'main-supplier-watch'
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient
import os

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('zinin/china-1688-supplier-monitor').call(run_input={
    'productUrls': ['https://detail.1688.com/offer/1000406623486.html'],
    'watchName': 'main-supplier-watch',
})
print(client.dataset(run['defaultDatasetId']).list_items().items)
```

#### CLI / REST

```bash
apify call zinin/china-1688-supplier-monitor -p '{"productUrls":["https://detail.1688.com/offer/1000406623486.html"],"watchName":"main-supplier-watch"}'
```

Apify Schedules can run either included Task input on an hourly or daily cadence.
Use a webhook on `ACTOR.RUN.SUCCEEDED` and read the Dataset `changes` view in your
n8n, Make, Slack or procurement pipeline.

### 中文说明

此 Actor 用于监控固定的 1688 公开商品链接。它会提取批发价格区间、阶梯价、
最小起订量（MOQ）、公开库存、供应商信息、认证标签和促销信息，并与同一个
`watchName` 的上一次成功结果进行比较。

第一次成功运行会建立基线；之后结果为 `changed` 或 `no_change`。如果页面被
风控拦截、需要登录、内容不完整或解析失败，Actor 会返回免费的错误记录，且
不会覆盖旧基线。默认使用 Apify Residential Proxy 的中国出口节点。不使用登录、
Cookie、验证码绕过或私有接口。输入仍使用 `detail.1688.com` 商品链接；Actor 在严格
校验商品 ID 后读取 robots 允许的 `m.1688.com/offer/<数字>.html` 公开移动页面作为证据。

建议先手动运行一次并检查 Dataset，然后创建 Apify Schedule。定时任务必须保持
相同的 `watchName`。本工具不提供关键词搜索，只接受格式为
`https://detail.1688.com/offer/<数字>.html` 的公开商品链接。

### Limitations and responsible use

- Public page structure can change. Failed parsing is reported as unknown state, not
  as a product disappearance.
- Prices are CNY values published in the fetched offer state. Tax, shipping,
  negotiation, login-only discounts and final checkout terms are outside scope.
- Public stock may be absent or approximate; `null` means the page did not publish a
  reliable value.
- The Actor intentionally does not search 1688, sign in, solve challenges, fetch
  private APIs or follow redirects.
- You are responsible for lawful use and for respecting 1688 terms and applicable
  data rules. Keep schedules proportionate to your procurement need.

Built by [zinin](https://apify.com/zinin). Questions: Telegram
[@timzinin](https://t.me/timzinin).

# Actor input Schema

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

Clean public URLs in the form https://detail.1688.com/offer/123456789.html. Query strings are removed.

## `watchName` (type: `string`):

Stable private name that scopes this monitor baseline. Reuse it on scheduled runs.

## `maxChanges` (type: `integer`):

Stop before checking more products after this many changed rows. Baseline and no-change rows already delivered still count normally.

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

Residential CN is the tested default. The Actor never silently falls back to datacenter access.

## Actor input object example

```json
{
  "productUrls": [
    "https://detail.1688.com/offer/1000406623486.html"
  ],
  "watchName": "main-supplier-watch",
  "maxChanges": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}
```

# Actor output Schema

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

API URL for paid successful checks and free error rows in the default Dataset.

## `OUTPUT` (type: `string`):

API URL for counters, status and storage links.

# 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 = {
    "productUrls": [
        "https://detail.1688.com/offer/1000406623486.html"
    ],
    "watchName": "main-supplier-watch",
    "maxChanges": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/china-1688-supplier-monitor").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 = {
    "productUrls": ["https://detail.1688.com/offer/1000406623486.html"],
    "watchName": "main-supplier-watch",
    "maxChanges": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/china-1688-supplier-monitor").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 '{
  "productUrls": [
    "https://detail.1688.com/offer/1000406623486.html"
  ],
  "watchName": "main-supplier-watch",
  "maxChanges": 20
}' |
apify call zinin/china-1688-supplier-monitor --silent --output-dataset

```

## MCP server setup

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

```

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/fqe5yr2pjSDOzg3la/builds/j2Sw0cRonwQ1TZ6nc/openapi.json
