# AliExpress to 1688 Sourcing Bridge: Suppliers & Margins (`crawleast/aliexpress-to-1688-sourcing-bridge`) Actor

Find 1688.com suppliers for AliExpress products by image search. Each row: wholesale and consign price in CNY, MOQ, factory signals and an estimated per-unit margin. $0.005 per AliExpress lookup, $0.008 per supplier row, $0.00005 run base fee. Failed lookups are free.

- **URL**: https://apify.com/crawleast/aliexpress-to-1688-sourcing-bridge.md
- **Developed by:** [Kyle Wang](https://apify.com/crawleast) (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.60 / 1,000 1688 supplier matches

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

## AliExpress → 1688 Sourcing Bridge

Turn AliExpress product URLs into a **1688 supplier shortlist** — one row per supplier, with wholesale and consign prices in CNY, MOQ, factory signals, and an **estimated per-unit margin**.

Most AliExpress scrapers sell raw listings. Most 1688 image-search Actors accept a photo. This Actor joins the two: it reads an AliExpress product, takes its main image, runs a reverse image search on 1688.com, and returns sourcing rows you can act on.

### What you get

Three flat row types in one dataset (`type` tells them apart):

| `type` | Meaning |
| --- | --- |
| `source` | One AliExpress product lookup: title, main image, USD price, sold text, rating, fetch status |
| `match` | One 1688 supplier offer: wholesale/consign price (CNY), MOQ, booked count, supplier city/province, years on 1688, factory flags, offer URL, estimated unit margin |
| `summary` | Per-item rollup: match count, best margin, best supplier, factory count, top 3 margins |

The run report is stored as `RUN_SUMMARY` in the key-value store: requested/delivered counts, skipped items by reason, coverage metrics, request usage, FX rate and charged amount. The completeness identity `delivered.summaries + sum(skippedBy) = requested.dedupedItems` is verified before exit, so items are never silently dropped.

### Input

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `aliexpressUrls` | string\[] | — | Up to 100 product URLs (`aliexpress.com/item/<id>.html`, `aliexpress.us/item/<id>.html`; query strings are fine) |
| `imageUrls` | string\[] | — | Up to 100 direct product image URLs. Skips AliExpress lookup; no lookup fee, no AE price, so margin is null |
| `maxSuppliersPerItem` | int | 10 | 1–20, in similarity order |
| `shipTo` | string | `US` | Two-letter destination used for the AliExpress session (prices vary by country) |
| `marginCurrency` | enum | `USD` | `USD` or `CNY` |
| `maxTotalChargeUsd` | number | 2 | Hard per-run charge cap, minimum 0.04 |
| `maxRequestsPerRun` | int | 1200 | Request quota guard, 50–2000 |

You can mix URL and image inputs in one run. Duplicates are removed by AliExpress item id (URLs) or by exact image URL.

### Output example

```json
{
  "type": "match",
  "itemKey": "ae:1005012030698792",
  "aeItemId": "1005012030698792",
  "offerId": "692120494348",
  "similarityRank": 1,
  "title1688": "源头工厂不入耳无线蓝牙耳机X15电竞游戏双模式无延迟tws蓝牙耳机",
  "priceYuan": 8.2,
  "consignPriceYuan": 7.5,
  "moq": 5,
  "bookedCount": 1200,
  "supplierName": "深圳某某科技有限公司",
  "supplierCity": "深圳",
  "supplierProvince": "广东",
  "yearsOnPlatform": 4,
  "compositeScore": 3.1,
  "isFactory": true,
  "isSuperFactory": false,
  "offerUrl": "https://detail.1688.com/offer/692120494348.html",
  "estMarginPerUnit": 2.15,
  "estMarginPct": 53.8,
  "marginBasis": "consign",
  "matchedBy": "image"
}
```

`estMarginPerUnit` is negative when the 1688 cost exceeds the AliExpress price. Negative margins are reported as-is: a product to avoid is also an answer.

### Pricing (pay-per-event)

All prices are **FREE-tier list prices**. Subscription tiers receive the discounts below.

| Event | FREE | BRONZE (−10%) | SILVER (−20%) | GOLD (−30%) | PLATINUM (−30%) | DIAMOND (−30%) | Charged when |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| `run-base-fee` | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 | Once per run, only if at least one billable row is delivered |
| `ae-item-lookup` | $0.005 | $0.0045 | $0.004 | $0.0035 | $0.0035 | $0.0035 | Per AliExpress item with `fetchStatus: "ok"` |
| `supplier-match` | $0.008 | $0.0072 | $0.0064 | $0.0056 | $0.0056 | $0.0056 | Per match row actually written to the dataset |

Discounts are applied by Apify according to the subscriber's plan. There is no platform start fee.

**Free:** blocked or region-unavailable AliExpress lookups, items stopped by budget/quota/deadline, image-conversion failures, zero-match image searches, and matches cut by your budget. You pay only for rows actually delivered.

Worked examples (FREE tier):

| Order | Calculation | Total |
| --- | --- | --- |
| 1 AE product, 10 matches | $0.00005 + $0.005 + 10 × $0.008 | **$0.08505** |
| 10 AE products, 10 matches each | $0.00005 + 10 × $0.005 + 100 × $0.008 | **$0.85005** |
| 10 image URLs, 10 matches each | $0.00005 + 100 × $0.008 | **$0.80005** |
| 1 AE product, no 1688 match | $0.00005 + $0.005 | **$0.00505** |

The default `maxTotalChargeUsd` is $2, which covers roughly 23 fully matched AE products at 10 suppliers each. Raise it for larger batches; when the cap is reached the run stops gracefully and reports `trigger: "budget"` plus `skippedBy.budget`.

### Margin math

One USD/CNY rate is captured at the start of the run and reported in `RUN_SUMMARY.fx` (rate, source, timestamp). No multi-currency matrix is maintained.

- Cost basis: `consignPriceYuan` when the 1688 offer exposes a dropship/consign price, otherwise `priceYuan` (`marginBasis` records which).
- AE unit revenue uses the **regular listing price** for the selected variant. New-shopper prices, coupon codes and "save $X" banners are deliberately excluded, so margins are not inflated by one-off discounts.
- USD: `estMarginPerUnit = aePriceUsd − costCNY ÷ fx`
- CNY: `estMarginPerUnit = aePriceUsd × fx − costCNY`
- `estMarginPct = estMarginPerUnit ÷ AE unit revenue × 100`

Margin estimates are **indicative, not guaranteed**. They exclude shipping, duties, payment fees, returns and platform commissions. Always verify with a sample order.

### How it works

1. **AliExpress leg** — a real browser with a fresh sticky residential session per item (country = `shipTo`) opens the product page and reads publicly visible data. If the page is anti-bot challenged, the session is rotated up to two times. No challenge is ever solved, no login is used.
2. **Image conversion** — the main image is downloaded and inspected by **magic bytes**, not by file extension. AliExpress CDN often serves WebP bytes from `.jpg` URLs. WebP/AVIF images are converted to real JPEG (max 800×800, quality 85) before upload.
3. **1688 leg** — the converted JPEG is uploaded to 1688's image service and searched with the existing production image-search engine: per-identity quotas, residential China sessions, token cache, risk-control rotation. Card fields come straight from the search response (no extra 1688 detail calls).

### Limits and honest caveats

- **Visual similarity ≠ same product or same factory.** Match rows are ordered by the platform's similarity rank. Marketing photos and lifestyle shots recall worse than clean product shots. Verify before ordering.
- **AliExpress anti-bot is real.** Detail pages are protected. A blocked item is returned as a `source` row with `fetchStatus: "blocked"` and is **not billed**. The run report counts it under `skippedBy.blocked`.
- **`imageUrls` input has no AliExpress price**, so margin fields are null. Match rows are still full price; the 1688 supplier data is the deliverable.
- **Prices vary by destination.** `shipTo` changes the AliExpress price. The Actor forces a USD display where the site allows it; if only a non-USD price is available, the item is marked `unavailable_in_region` and not billed.
- **AliExpress sold/rating fields are platform-displayed values**, not independently verified.
- **Supplier names stay in Chinese** as registered on 1688. `compositeScore` and `isFactory` are raw platform signals. This Actor does not claim a supplier is "verified"; the judgment is yours.
- **Run window.** Default timeout is 1,200 seconds. Large batches can hit the deadline or budget; the run stops gracefully and reports `partial: true` with the exact reason.
- **Public data only.** No login, no cookies from you, no personal data, no buyer review text.

### Disclosure

> Finds wholesale suppliers on 1688.com for AliExpress products using image search. Scrapes publicly available data without login. Users are responsible for complying with AliExpress's and 1688's terms of service.

> You are billed only for rows actually delivered. Failed, blocked and empty lookups are never billed.

> Margin estimates use a single exchange rate captured at run time (disclosed in run summary). They are indicative, not guaranteed.

### Files

- `src/main.js` — orchestration, gates, billing, completeness
- `src/ae-client.js` — AliExpress browser layer (detail + search fallback)
- `src/ae-parse.js` — pure parsers for AliExpress HTML/JSON
- `src/image-convert.js` — magic-byte detection and JPEG normalization
- `src/margin.js`, `src/fx.js` — unit economics
- `src/image-search.js`, `src/image-search-probe.js` — 1688 reverse image search engine
- `src/token-cache.js` — cross-run mtop token cache
- `src/billing.js` — pay-per-event ledger

# Changelog

This Actor's version history is a separate document: https://apify.com/crawleast/aliexpress-to-1688-sourcing-bridge/changelog.md

# Actor input Schema

## `aliexpressUrls` (type: `array`):

Public AliExpress product URLs, up to 100 per run. Accepted forms include aliexpress.com/item/<id>.html and aliexpress.us/item/<id>.html (query parameters are fine). Each successfully looked-up item costs one $0.005 ae-item-lookup event; blocked, region-unavailable and empty lookups are free. Batch items in one run to pay the $0.00005 run base fee once.

## `imageUrls` (type: `array`):

Public product photo URLs (jpg/png/webp/avif, about 1 MB or less), up to 100 per run. These skip the AliExpress lookup entirely: no ae-item-lookup fee, no AliExpress price, so margin fields are null. Mix with aliexpressUrls to process both kinds in one run.

## `maxSuppliersPerItem` (type: `integer`):

How many visually matching 1688 offers to return per item, in similarity order. Each delivered match row costs $0.008 (FREE tier); matches cut by your maxTotalChargeUsd are not charged.

## `shipTo` (type: `string`):

Two-letter destination country code passed to AliExpress (default US). AliExpress prices vary by destination; the Actor forces USD display where possible. The AliExpress leg uses a residential proxy in this country; the 1688 leg always uses China residential sessions.

## `marginCurrency` (type: `string`):

Currency for estMarginPerUnit / estMarginPct: USD (default) computes aePriceUsd − consignPriceYuan ÷ USD/CNY; CNY computes aePriceUsd × USD/CNY − consignPriceYuan. One run-time FX rate is captured and reported in RUN_SUMMARY. No multi-currency matrix.

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

Informational only. The Actor enforces RESIDENTIAL proxies internally: the AliExpress leg uses one sticky residential session per item in the ship-to country (US by default), and the 1688 image-search leg uses China residential sessions. Datacenter proxies are known to be blocked by AliExpress.

## `maxTotalChargeUsd` (type: `number`):

Hard budget cap for this run including the run base fee. When the next item cannot be delivered within the cap, the run stops gracefully, marks the remaining items in skippedBy.budget and reports trigger="budget". Minimum 0.04 (Apify platform limit).

## `maxRequestsPerRun` (type: `integer`):

Request quota guard across both legs (AliExpress navigations, image downloads, 1688 uploads/searches). When exhausted, remaining items are marked skippedBy.quota and trigger="quota". The default 1,200 covers 100 items with retry headroom.

## Actor input object example

```json
{
  "aliexpressUrls": [
    "https://www.aliexpress.com/item/1005000000000000.html",
    "https://www.aliexpress.us/item/3256800000000000.html"
  ],
  "imageUrls": [
    "https://example.com/product-photo.jpg"
  ],
  "maxSuppliersPerItem": 10,
  "shipTo": "US",
  "marginCurrency": "USD",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "maxTotalChargeUsd": 2,
  "maxRequestsPerRun": 1200
}
```

# Actor output Schema

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

Source rows (AliExpress lookups), match rows (1688 suppliers with unit economics) and per-item summaries, in delivery order.

## `sources` (type: `string`):

The dataset filtered to source rows: title, main image, USD price, sold text, rating and fetch status.

## `matches` (type: `string`):

The dataset filtered to match rows: 1688 offer, wholesale/consign price, MOQ, factory flags and estimated unit margin.

## `summaries` (type: `string`):

The dataset filtered to summary rows: match count, best margin, factory count and top margins per item.

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

Machine-readable report: requested/delivered counts, skipped items by reason, coverage metrics, request usage, FX rate and billed amount.

# 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 = {
    "aliexpressUrls": [
        "https://www.aliexpress.com/item/3256811844384040.html",
        "https://www.aliexpress.com/item/3256812407941674.html",
        "https://www.aliexpress.com/item/3256812252345681.html",
        "https://www.aliexpress.com/item/3256810467352274.html",
        "https://www.aliexpress.com/item/3256809923254045.html"
    ],
    "imageUrls": [
        "https://ae-pic-a1.aliexpress-media.com/kf/S623d5c89b35e423e8575ff54bbfcf345r.jpg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawleast/aliexpress-to-1688-sourcing-bridge").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 = {
    "aliexpressUrls": [
        "https://www.aliexpress.com/item/3256811844384040.html",
        "https://www.aliexpress.com/item/3256812407941674.html",
        "https://www.aliexpress.com/item/3256812252345681.html",
        "https://www.aliexpress.com/item/3256810467352274.html",
        "https://www.aliexpress.com/item/3256809923254045.html",
    ],
    "imageUrls": ["https://ae-pic-a1.aliexpress-media.com/kf/S623d5c89b35e423e8575ff54bbfcf345r.jpg"],
}

# Run the Actor and wait for it to finish
run = client.actor("crawleast/aliexpress-to-1688-sourcing-bridge").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 '{
  "aliexpressUrls": [
    "https://www.aliexpress.com/item/3256811844384040.html",
    "https://www.aliexpress.com/item/3256812407941674.html",
    "https://www.aliexpress.com/item/3256812252345681.html",
    "https://www.aliexpress.com/item/3256810467352274.html",
    "https://www.aliexpress.com/item/3256809923254045.html"
  ],
  "imageUrls": [
    "https://ae-pic-a1.aliexpress-media.com/kf/S623d5c89b35e423e8575ff54bbfcf345r.jpg"
  ]
}' |
apify call crawleast/aliexpress-to-1688-sourcing-bridge --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawleast/aliexpress-to-1688-sourcing-bridge"
        }
    }
}
```

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/JPMtV66NBN8LcjT44/builds/hbgsnTdq0Ge6xZRu8/openapi.json
