# 1688 Supplier Due Diligence & Sourcing Data (`aligeng/1688-products-search-scraper`) Actor

Search 1688.com in English and get the supplier's official record with every listing — years verified, repeat-buyer rate, 1688's six service scores, factory vs trading company, inspection reports — plus category stats showing price spread and supplier concentration. Facts only, no invented scores.

- **URL**: https://apify.com/aligeng/1688-products-search-scraper.md
- **Developed by:** [David](https://apify.com/aligeng) (community)
- **Categories:** E-commerce, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 products

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/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 Sourcing Intelligence

Search **1688.com** and get back what an experienced sourcing team actually looks at before
committing money: whether the **category** is worth entering, how each supplier compares to
**its own category's norms**, and where the weak spot is that a headline score hides.

**No login. No invented scores. Everything in English.**

### Most 1688 scrapers answer "what's for sale". This one answers "what should I do".

A list of products with 50 fields still leaves you the hard part. A ¥3 phone case tells you
nothing on its own — *¥3 when the category median is ¥8, from a supplier whose repeat-buyer
rate is 14 points below its peers, whose logistics score is 1.6 while its headline is 4.0*
is a decision.

That comparison requires seeing the whole category at once. It cannot be produced by
scraping one product at a time.

#### What you get that a field dump can't give you

| Field | Why it changes a decision |
|---|---|
| `categoryPriceIqrRatio` | Price spread of the category. Near 1–3: everyone competes on price, no room to differentiate. Above ~5: cheap and premium coexist, so you can position. |
| `priceVsCategoryPct` | This product against its own category's median — not an absolute price you have no reference for. |
| `pricePercentile` | Exactly where it sits in the price distribution. |
| `repeatRateVsCategoryPts` | Repeat business relative to category norms. 40% is strong in one category, average in another. |
| `weakestServiceArea` + `weakestServiceScore` | **Names the collapsed dimension.** A 4.0 overall can hide logistics at 1.6. |
| `supplierKeywordSpread` | How many of your searched categories this seller appears in. A seller across unrelated categories is a reseller, not a specialist. |
| `legalEntityHint` | What the **registered company name** implies — factory, trading company, e-commerce reseller, sole trader. |
| `bizTypeMatchesLegalName` | `false` when a supplier calls itself a manufacturer but is registered as a trading entity. |
| `shopNameMatchesLegalEntity` | `false` when the shopfront name and the registered business differ. |
| `customizationOffered` | Whether the supplier offers customisation — the starting point for any private-label plan. |

Real example from a live run: a supplier appearing in both *data cables* and *screen
protectors*, self-declared **Manufacturer**, registered as **深圳市阚及贸易有限公司** —
"trading company" written into its own legal name.

### We search in Chinese, so you don't get the tourist price

Type "usb cable" into 1688 and you land in the slice built for cross-border resellers.
Type 数据线 and you're in the domestic wholesale market where the factories are. Same
platform, different world — and nothing tells an English-speaking buyer which one they're
looking at.

Measured on the same three products, English term vs. Chinese term, 40 listings each:

| | phone case → 手机壳 | usb cable → 数据线 | screen protector → 钢化膜 |
|---|---|---|---|
| Median price | ¥3.9 → ¥3.9 | **¥8 → ¥2.3** | **¥4.6 → ¥1.82** |
| Share that are factories | **13% → 65%** | 80% → 85% | 60% → 55% |
| Listings with sales data | 85% → 90% | 80% → **100%** | 60% → **100%** |
| Listings with inspection badges | 1 → 5 | 11 → 19 | 4 → 12 |

So English keywords are converted to the term Chinese wholesalers actually type before the
search runs. `keyword` keeps what you entered; `searchedAs` shows what was actually
searched, so you can always check the conversion. Turn it off with `searchInChinese: false`.

> This needs an API key (the same free-tier key used for translation). Without one, your
> English term is searched as given and the run log says so — we don't guess at
> translations, because a machine-translated keyword once turned "yoga mat" into "wet
> wipes", and you would never have known.

### The supplier's official 1688 record

Alongside every listing, in English:

| Field | What it is |
|---|---|
| `supplierYears` | Years holding a paid, identity-verified 1688 membership (诚信通) |
| `repeatBuyerRate` | Share of buyers who ordered again within 90 days (回头率) |
| `serviceScoreOverall` + 5 dimensions | 1688's official merchant service rating (新灯塔), out of 5 |
| `businessTypeEn` | Manufacturer, trading company, agency… |
| `certificationsEn` | Deep factory / business inspection, Super Factory |
| `serviceCommitmentsEn` | Return shipping covered, buy-now-pay-later, counterfeit compensation |
| `inspectionReportUrl` | Opens the actual third-party verification report |

**We deliberately do not compute a trust score or rank the results.** A vendor-invented
0–100 number is unauditable. You get the facts 1688 itself publishes, normalised against the
category so they mean something, and the benchmarks to read them.

### How to use it — the playbook

Every run writes a **`SOURCING_PLAYBOOK`** record naming the exact fields for each step:

1. **Pick the category first.** Compare `category*` columns across keywords before opening a
   single product. Stop if `categoryKeywordMatchPct` is near zero — 1688 didn't recognise
   your keyword and returned unrelated filler.
2. **Shortlist by filter, not by reading.** `repeatRateVsCategoryPts > 0`,
   `supplierYears >= 3`, `businessTypeEn = Manufacturer`, MOQ within your test budget.
3. **Hunt the hidden problem.** `weakestServiceArea`, `shopNameMatchesLegalEntity`,
   `bizTypeMatchesLegalName`, `supplierKeywordSpread`.
4. **Verify before contacting.** Open `inspectionReportUrl` and `shopUrl`.
5. **Know the price breaks before you message.** `priceTiersEn`, `minOrderQuantity`.
6. **Run daily to see movement.** `trend`, `salesGrowthPct`, `daysTracked`.

Open **`START_HERE`** in the key-value store for the same thing as a formatted page: all six
steps, plus every field with its official 1688 scale and the market benchmark to read it
against — so "67%" becomes "67%, against a platform average of 20–30%". (`SOURCING_PLAYBOOK`
and `FIELD_GUIDE` hold the same content as JSON if you're consuming this via the API.)

You don't have to open anything, though: the run log ends with what the data actually says
about the categories you searched, and which view to switch to next.

### English output

Titles, locations, units, tags, certifications and price tiers all come back in English.
Company and shop names stay in Chinese on purpose — you need the real name to verify a
business or search it. Set `includeOriginalChinese` to get the Chinese alongside.

Translation works with **no API key** (a free service is used). For unlimited translation
and better wording on marketplace jargon, add any OpenAI-compatible key — **free-tier keys
work** (Google Gemini, Groq, OpenRouter). Translations are cached and reused across runs.

### Input

```json
{
  "keywords": ["phone case", "screen protector"],
  "maxResultsPerKeyword": 40,
  "translateToEnglish": true,
  "trackTrend": true
}
```

| Input | Notes |
|---|---|
| `keywords` | Chinese or English. **Search related keywords together** — that's what makes `supplierKeywordSpread` meaningful. |
| `maxResultsPerKeyword` | Broad keywords fill 100+; long-tail keywords stop early on their own |
| `maxConcurrency` | Keywords processed in parallel (default 4) |
| `includeAds` | Off by default — organic listings only |
| `includeOriginalChinese` | Off by default; on = Chinese originals alongside the English |
| `trackTrend` | Keeps snapshot history so trends can build up |
| `proxyConfiguration` | Residential proxies strongly recommended — 1688 rate-limits hard |

### Reliability

1688 does not fail loudly, so the usual failure mode of a scraper here is *silently
returning less than it should*:

- Detects **silent throttling** — a success response carrying no products — and retries
  instead of mistaking it for the end of the results. Fixing this alone took one test
  keyword from 49 results to the full 100.
- Recovers from anti-bot blocks by rotating residential IP and re-establishing the session
  from a shallow page before resuming a deep one.
- Drops the **empty placeholder records** 1688 mixes into fallback results — they are never
  billed to you.
- De-duplicates by `offerId`; 1688's deep pagination returns overlapping pages.
- Survives flaky proxy connections without abandoning the rest of the keyword.

### Notes

- Only publicly visible search data is collected — no login, no personal data.
- All supplier metrics are reported by 1688, not computed by us. Relative measures
  (`*VsCategory*`, percentiles) are arithmetic on those facts. None of it is a guarantee —
  it is where due diligence starts, not ends.
- Supply-side only. Demand, resale price and competition in your own market are not on
  1688 and must come from your destination marketplace.

# Actor input Schema

## `keywords` (type: `array`):

Keywords to search on 1688.com. Chinese or English.

## `maxResultsPerKeyword` (type: `integer`):

How many products to return per keyword. Broad keywords (e.g. 'phone case') can fill 100+; narrow or long-tail keywords have a smaller result pool and will stop early on their own. For wider coverage, add more keywords rather than only raising this number.

## `includeAds` (type: `boolean`):

Include sponsored/P4P listings. Off by default for cleaner organic results.

## `trackTrend` (type: `boolean`):

Store sales snapshots across runs to detect rising products. Run daily (schedule) for this to build up trend data. First run only marks products as 'new'.

## `searchInChinese` (type: `boolean`):

On by default. English keywords are converted to the term Chinese wholesalers actually use before searching, because 1688's English results skew toward cross-border resellers. In our tests the English term returned up to 3.5x the median price and, on one keyword, 13% factories versus 65% for the Chinese equivalent. Requires an API key (see below) — without one the English term is searched as-is and a note is written to the log. The keyword you typed is kept in 'keyword'; what was actually searched appears in 'searchedAs'.

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

How many keywords to scrape at the same time. Each keyword uses its own residential IP, so raising this does not increase the request rate per IP. Lower it if you are on a small proxy allowance.

## `includeOriginalChinese` (type: `boolean`):

Off by default, so the output is English-only. Turn on to also get the original Chinese for titles, locations, tags and price tiers — useful if you paste terms back into 1688 or forward listings to a sourcing agent in China. Company and shop names are always kept in Chinese, since you need the real name to verify a business.

## `translateToEnglish` (type: `boolean`):

Adds an English title to every product. Works with no API key at all — a free translation service is used by default. For better quality on e-commerce jargon, add an API key below (a free-tier key works).

## `llmApiKey` (type: `string`):

Leave empty to use the free no-key translator (fine for a daily run; limited to roughly 5,000 characters per day). Provide any OpenAI-compatible key for better wording — FREE keys work: Google Gemini, Groq and OpenRouter all offer free tiers. See the base URL field for their endpoints.

## `llmModel` (type: `string`):

Model name for your provider. Providers retire model names often — check your provider's current model list rather than trusting a name copied from anywhere. On Gemini pick a current Flash or Flash-Lite model; on Groq pick a current Llama model; on OpenAI, gpt-4o-mini is fine. Any model can handle title translation, so choose the cheapest/fastest tier.

## `llmBaseUrl` (type: `string`):

OpenAI-compatible endpoint. Free providers: Gemini = https://generativelanguage.googleapis.com/v1beta/openai ; Groq = https://api.groq.com/openai/v1 ; OpenRouter = https://openrouter.ai/api/v1

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

Residential proxies recommended to avoid rate limits.

## Actor input object example

```json
{
  "keywords": [
    "蓝牙耳机",
    "phone case"
  ],
  "maxResultsPerKeyword": 40,
  "includeAds": false,
  "trackTrend": true,
  "searchInChinese": true,
  "maxConcurrency": 4,
  "includeOriginalChinese": false,
  "translateToEnglish": false,
  "llmModel": "gpt-4o-mini",
  "llmBaseUrl": "https://api.openai.com/v1",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

## `shortlist` (type: `string`):

No description

## `supplierDueDiligence` (type: `string`):

No description

## `thingsToCheck` (type: `string`):

No description

## `spreadsheet` (type: `string`):

No description

## `howToRead` (type: `string`):

No description

## `categoryReport` (type: `string`):

No description

## `fieldGuide` (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 = {
    "keywords": [
        "蓝牙耳机"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("aligeng/1688-products-search-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 = {
    "keywords": ["蓝牙耳机"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("aligeng/1688-products-search-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 '{
  "keywords": [
    "蓝牙耳机"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call aligeng/1688-products-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aligeng/1688-products-search-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/m9UeDevNe0T5gAh75/builds/eTYBCWhvimDJUIrI5/openapi.json
