# 1688 Wholesale Product Scraper (`w3crawler/alibaba-1688-wholesale-scraper`) Actor

Extract public 1688.com wholesale products with tier pricing, MOQ, supplier details, SKU attributes, and images.

- **URL**: https://apify.com/w3crawler/alibaba-1688-wholesale-scraper.md
- **Developed by:** [w3crawler](https://apify.com/w3crawler) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 wholesale products

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### 1688 Wholesale Product Scraper

Extracts rich public wholesale product data from 1688.com. The Actor supports keyword searches, multiple public sources, bounded pagination, global filters/sorting/deduplication, optional Apify Proxy routing, and fail-closed diagnostics.

The dataset is marketplace-focused. Product rows do not contain Actor-debugging wrappers such as `recordId`, `recordType`, `status`, `success`, `ok`, `dataAvailable`, `found`, `fieldCoverage`, `dataQuality`, `extractionMethod`, `fallbackMode`, or `usedProxy`. Operational counts remain in `OUTPUT_SUMMARY`.

The Actor only requests publicly exposed 1688 pages. It does not sign in, solve CAPTCHA or security challenges, rotate identities to evade controls, or call private APIs. If 1688 presents a login, challenge, denial, or rate limit, the run stops at that boundary and records a bounded diagnostic instead of inventing a product row. A successful run is therefore environment-dependent and cannot be guaranteed from every region or Cloud transport.

### Extracted fields

Depending on public availability, a product row can include:

- identity and provenance: `url`, `productId`, `title`, `name`, `productUrl`, `source`, `sourceDomain`, `sourceUrl`, `pageNum`, `position`, `scrapedAt`
- pricing: `price`, `priceMin`, `priceMax`, `currency`, `priceFormatted`, `tierPricing`
- wholesale facts: `moq`, `moqUnit`, `salesVolume`, `transactionCount`, `reviewCount`, `rating`, `availability`
- supplier: `supplierName`, `supplierProfileUrl`, `supplierLocation`, `supplierYears`, `supplierResponseRate`
- media and catalog facts: `images`, `thumbnail`, `imageCount`, `attributes`, `categories`, `badges`, `description`, `shippingInfo`, `leadTime`

Missing values are omitted rather than guessed. `thumbnail` is always `images[0]` when images are present. Product images are scoped to the product record and filtered for common logos, icons, placeholders, and loading assets.

### Input

#### Default keyword search

```json
{
  "keywords": "wireless earbuds",
  "maxItems": 50,
  "maxPages": 3,
  "sortBy": "relevance"
}
```

#### Filters and sorting

```json
{
  "keywords": "cotton tote bag",
  "minPrice": 1.5,
  "maxPrice": 12,
  "minMoq": 10,
  "minSalesVolume": 100,
  "minRating": 4,
  "minReviewCount": 20,
  "supplierLocation": "Shenzhen",
  "requiredBadges": ["诚信通"],
  "sortBy": "sales_desc",
  "maxItems": 25,
  "maxPages": 5,
  "deduplicate": true
}
```

#### Multiple sources, developer controls, and proxy

```json
{
  "startUrls": [
    { "url": "https://s.1688.com/selloffer/offer_search.htm?keywords=packaging" },
    { "url": "https://s.1688.com/selloffer/offer_search.htm?keywords=gift%20bags" },
    { "url": "https://detail.1688.com/offer/123456789.html" }
  ],
  "maxItems": 100,
  "maxPages": 4,
  "requestDelayMs": 1500,
  "maxConcurrency": 2,
  "maxRequestRetries": 3,
  "requestTimeoutSecs": 45,
  "includeImages": true,
  "includeAttributes": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

`maxPages: 0` continues until a source returns no new products, with a hard 100-page cap. `maxItems` is global across all sources. Product/detail URLs are fetched once. A proxy only changes transport routing; it does not authorize access or bypass login, CAPTCHA, or security controls. `includeDiagnostics: false` suppresses diagnostic rows but the run summary still reports `diagnosticsFound` and retains the blocked/no-data status.

Supported `sortBy` values are `relevance`, `price_asc`, `price_desc`, `sales_desc`, `rating_desc`, `reviews_desc`, and `supplier_years_desc`.

#### Deterministic local QA

```json
{
  "keywords": "cotton tote",
  "fixtureFile": "fixtures/sample.html",
  "maxItems": 10,
  "maxPages": 2,
  "requestDelayMs": 0,
  "includeDiagnostics": true
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Product output example

```json
{
  "source": "1688.com",
  "sourceDomain": "s.1688.com",
  "sourceUrl": "https://s.1688.com/selloffer/offer_search.htm?keywords=cotton+tote",
  "url": "https://detail.1688.com/offer/FIXED-1688-1.html",
  "productId": "FIXED-1688-1",
  "title": "Cotton Tote Wholesale",
  "productUrl": "https://detail.1688.com/offer/FIXED-1688-1.html",
  "price": 1.9,
  "priceMin": 1.9,
  "priceMax": 2.5,
  "currency": "CNY",
  "priceFormatted": "¥1.9-2.5",
  "tierPricing": [
    { "minQuantity": 10, "price": 2.5, "currency": "CNY" },
    { "minQuantity": 100, "price": 1.9, "currency": "CNY" }
  ],
  "moq": 10,
  "moqUnit": "pieces",
  "salesVolume": 1250,
  "transactionCount": 1250,
  "reviewCount": 120,
  "rating": 4.8,
  "supplierName": "Shenzhen Supply",
  "supplierProfileUrl": "https://shop12345.1688.com/",
  "supplierLocation": "Guangdong Shenzhen",
  "supplierYears": 5,
  "supplierResponseRate": "96%",
  "images": [
    "https://cbu01.alicdn.com/img/fixed-tote.jpg",
    "https://cbu01.alicdn.com/img/fixed-tote-2.jpg"
  ],
  "thumbnail": "https://cbu01.alicdn.com/img/fixed-tote.jpg",
  "imageCount": 2,
  "attributes": { "Material": "Cotton canvas", "Style": "Tote" },
  "shippingInfo": "Ships within 48 hours",
  "leadTime": "3-7 days",
  "badges": ["诚信通", "实力商家"],
  "categories": ["Bags", "Canvas bags"],
  "availability": "InStock",
  "pageNum": 1,
  "position": 1,
  "scrapedAt": "2026-09-05T00:00:00.000Z"
}
```

Blocked or unavailable public pages produce a deliberately small diagnostic row:

```json
{
  "url": "https://s.1688.com/selloffer/offer_search.htm?keywords=wireless+earbuds",
  "error": "A public 1688 access barrier was visible; the Actor stopped without bypassing it.",
  "errorCode": "ACCESS_BARRIER_LOGIN_REQUIRED",
  "scrapedAt": "2026-09-08T07:17:41.304Z"
}
```

### Local validation

```bash
npm ci --omit=dev
npm test
apify validate-schema
apify run --purge --input-file .actor/input.json
npm run validate
```

The validator checks the strict marketplace schema, canonical URLs, product-scoped image URLs, `thumbnail === images[0]`, and the absence of Actor-debugging fields. Live availability can vary by region, session, and access policy; the correct response to a blocked page is a diagnostic, not fabricated product data. The diagnostic itself is intentionally small: `url`, `error`, `errorCode`, and `scrapedAt`.

# Actor input Schema

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

Search terms used to construct a public 1688 search URL when Start URLs is empty.

## `startUrls` (type: `array`):

Optional public 1688 search or product URLs. When supplied, these URLs take precedence over generated keywords; each URL is paginated independently up to Max Pages.

## `minPrice` (type: `number`):

Keep products whose price range reaches this value. Products without a price are excluded when this filter is set.

## `maxPrice` (type: `number`):

Keep products whose price range starts at or below this value.

## `minMoq` (type: `integer`):

Minimum minimum-order quantity. Products without a parsed MOQ are excluded when this filter is set.

## `maxMoq` (type: `integer`):

Maximum minimum-order quantity.

## `minSalesVolume` (type: `integer`):

Minimum parsed sales or transaction count.

## `minRating` (type: `number`):

Minimum public product rating from 0 to 5.

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

Minimum public review count.

## `supplierLocation` (type: `string`):

Case-insensitive text matched against the parsed supplier location.

## `requiredBadges` (type: `array`):

Keep products whose parsed badge list contains every requested badge, such as 诚信通 or Verified.

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

Sorting is applied globally across all fetched pages before Max Items is selected.

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

Maximum unique product rows emitted across all start URLs and pages.

## `maxPages` (type: `integer`):

Maximum search pages per start URL. Use 0 to continue until no new products are found, with a hard safety cap of 100 pages. Product URLs are fetched once.

## `deduplicate` (type: `boolean`):

Remove repeated product IDs or URLs across pages and multiple start URLs.

## `includeDiagnostics` (type: `boolean`):

Emit a rich fail-closed diagnostic row when a page is blocked, unavailable, empty, or fails after bounded retries.

## `includeImages` (type: `boolean`):

Include validated product image URLs, thumbnail, and imageCount fields.

## `includeAttributes` (type: `boolean`):

Include normalized SKU/specification attributes when public structured data or DOM tables expose them.

## `requestDelayMs` (type: `integer`):

Developer option: delay before each public page request. A respectful non-zero value is recommended for live runs.

## `maxConcurrency` (type: `integer`):

Developer option: maximum number of independent start-URL/page requests in flight. Higher values can increase blocking risk.

## `maxRequestRetries` (type: `integer`):

Developer option: bounded retries for timeouts, transient network failures, and retryable HTTP responses. Login, CAPTCHA, and access barriers are never bypassed or retried.

## `requestTimeoutSecs` (type: `integer`):

Developer option: timeout for each public HTTP request.

## `timeoutMs` (type: `integer`):

Legacy compatibility alias. requestTimeoutSecs takes precedence when both are supplied.

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

Optional standard Apify Proxy configuration. Direct public access is the default; a proxy only changes transport routing and never bypasses authentication, CAPTCHA, or access controls.

## `fixtureFile` (type: `string`):

Optional Actor-relative HTML fixture for deterministic parser and schema QA. Omit this in production to request public 1688 pages.

## Actor input object example

```json
{
  "keywords": "wireless earbuds",
  "sortBy": "relevance",
  "maxItems": 50,
  "maxPages": 3,
  "deduplicate": true,
  "includeDiagnostics": true,
  "includeImages": true,
  "includeAttributes": true,
  "requestDelayMs": 1000,
  "maxConcurrency": 2,
  "maxRequestRetries": 3,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Product and fail-closed diagnostic rows.

## `runSummary` (type: `string`):

Counts, filter/sort settings, pagination, source health, proxy routing, and completion status.

## `runOutputAlias` (type: `string`):

Compatibility alias containing the same summary as OUTPUT\_SUMMARY.

# 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("w3crawler/alibaba-1688-wholesale-scraper").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("w3crawler/alibaba-1688-wholesale-scraper").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 w3crawler/alibaba-1688-wholesale-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,w3crawler/alibaba-1688-wholesale-scraper"
        }
    }
}
```

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/Ki3NJwng5LEuGkyFM/builds/tSOMvevoKLCkcZJOe/openapi.json
