DEV Community

Cover image for How to scrape 1688.com wholesale prices, MOQ and suppliers with Python
Norbert Sobala
Norbert Sobala

Posted on

How to scrape 1688.com wholesale prices, MOQ and suppliers with Python

If you sell on Amazon, Shopify or Allegro, the number you care about most is the factory price. For a lot of consumer goods that price lives on 1688.com, the Chinese B2B marketplace run by Alibaba where manufacturers sell to resellers. The site is in Chinese, prices are in yuan, and the useful bits (quantity tiers, minimum order, how long a supplier has been around) are spread over search cards.

This guide shows how to pull that into a table with the 1688 Scraper on Apify, first without code and then with Python and pandas. I tested it on one keyword, 蓝牙耳机 (Bluetooth earphones), with 40 results. Every number below comes from that run.

1688 Scraper results for Bluetooth earphones

What the run returned

The run took 82 seconds and saved 40 offers. A few things stood out once the data was in a spreadsheet:

  • Prices ranged from 6.29 to 54.87 CNY, with a median of 12.0 CNY.
  • 8 of the 40 offers were paid placements (isAd: true). Without them the median drops to about 9.95 CNY, so filter ads out before you average anything.
  • 35 of 40 suppliers were in Guangdong province: 17 in Dongguan and 16 in Shenzhen.
  • 27 suppliers were labelled 生产加工 (manufacturer) and 3 as 经销批发 (trading/wholesale). 10 had no type.
  • The median supplier had been on 1688 for 3 years. 12 had been there for 5 years or more.
  • 5 offers showed 10,000+ units sold. The top one claimed 100,000.

The tier data is where it gets interesting. One single-ear headset was listed at 12 CNY for 10 to 999 pieces, 4.5 CNY for 1,000 to 2,999 and 4.3 CNY from 3,000 up. The headline price in search was 12 CNY. If you only look at that number, you overestimate your landed cost by more than half at volume.

Fields you get

Field What it contains
offerId, url 1688 offer ID and link
title, titleEn Chinese title and optional machine translation
price, currency Headline price, always CNY
priceTiers List of {minQuantity, maxQuantity, unit, price}
minOrderQuantity, unit MOQ, filled when the offer shows tiers
salesCount, salesText, bookedCount Sales figures as shown on the card
repurchaseRate Share of repeat buyers, e.g. 24%
supplierName, supplierShopUrl Company name and shop link
supplierYearsOn1688, supplierType Years on the platform, manufacturer or trader
province, city Supplier location
serviceScores, serviceTags Overall, consultation, logistics, dispute, returns and goods scores, plus verification badges
isAd, page, position Ranking context

Coverage in my run: titleEn was filled on all 40 offers, serviceScores on 38, repurchaseRate on 28 and minOrderQuantity on 18. MOQ is empty when 1688 does not show quantity tiers on the search card, which is a site limitation, so plan for gaps in that column.

Supplier fields describe companies and their shops. There is no data about private individuals in the output.

Input options

There are only four settings, which keeps it simple:

  • searchQueries: a list of keywords. Chinese keywords return the most results (手机壳 for phone case, 充电宝 for power bank). English works too, but the hit count is lower.
  • maxItemsPerQuery: how many offers per keyword, up to about 2,000. That ceiling comes from 1688 search itself.
  • translateTitles: adds titleEn. It uses a free translation service, so treat it as a rough guide. If the service is down, the field stays empty and the run still finishes.
  • proxyFallback: on by default. The actor tries without a proxy first and only switches to datacenter and then residential proxy if 1688 blocks it.

1688 Scraper input form

Option 1: no code

  1. Open the actor page and click Try for free. You need a free Apify account.
  2. Type your keyword in Search keywords. I used 蓝牙耳机. If you do not read Chinese, Google Translate is good enough to find the right term.
  3. Set Max offers per keyword to something small for a first test, like 40.
  4. Tick Translate titles to English if you want readable titles.
  5. Click Start. A 40 offer run finished in under a minute and a half for me.
  6. Open the Output tab and export as CSV, Excel or JSON.

In Excel, sort by price and hide the rows where isAd is TRUE. That alone gives you a reasonable price range for a product category.

Option 2: Python with pandas

Install the client and pandas:

pip install apify-client pandas openpyxl
Enter fullscreen mode Exit fullscreen mode

The script below runs the actor, drops ads, and works out what each offer costs at 1,000 units using the tier list.

from apify_client import ApifyClient
import pandas as pd

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("flarewow/1688-scraper").call(run_input={
    "searchQueries": ["蓝牙耳机"],
    "maxItemsPerQuery": 40,
    "translateTitles": True,
})

items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
df = pd.DataFrame(items)

organic = df[df["isAd"] != True]
print(organic["price"].describe())
print(df["city"].value_counts().head())

def price_at(tiers, qty):
    for t in tiers or []:
        upper = t.get("maxQuantity")
        if t["minQuantity"] <= qty and (upper is None or qty <= upper):
            return t["price"]
    return None

df["price_at_1000"] = df["priceTiers"].apply(lambda t: price_at(t, 1000))

cols = ["titleEn", "price", "price_at_1000", "minOrderQuantity",
        "salesCount", "supplierYearsOn1688", "city"]
shortlist = (df.dropna(subset=["price_at_1000"])
               .sort_values("price_at_1000")[cols])
print(shortlist.head(10))

df.to_excel("1688_bluetooth_earphones.xlsx", index=False)
Enter fullscreen mode Exit fullscreen mode

A few notes from running it:

  • price_at_1000 is only filled for offers that publish tiers (18 of 40 in my run). For the rest, price is all you have until you message the supplier.
  • serviceScores is a nested dict. pd.json_normalize(items) flattens it into columns like serviceScores.logistics if you want to filter on it.
  • Prices exclude shipping inside China and international freight. Add those before you compare with your selling price.

Scheduling and integrations

If you track a category, a weekly run per keyword is usually enough. In the Apify Console, open Schedules, pick the actor and your saved input, and set a cron such as every Monday morning.

From there you can push results onward:

  • Google Sheets integration to keep a living price sheet.
  • A webhook to n8n, Make or Zapier when a run finishes.
  • The Apify MCP server if you want an AI agent to query offers for you.

Each run creates a new dataset, so compare offerId between runs to spot new listings and price changes.

Pricing

The actor charges $2 per 1,000 offers saved to the dataset. My 40 offer test cost $0.08. You only pay for results, and if no offers come back the run ends as failed with an explanation instead of an empty success. Set Max cost per run in the run options if you want a hard cap.

Responsible use

The actor reads publicly visible business listings and needs no login. Keep request volumes reasonable, respect 1688's terms and the law where you operate, and do not treat sales counts as audited figures. They are what the supplier card shows, and a 100,000 sold badge on an 8.99 CNY headset deserves a sample order before you believe it.

If you want to try it, the 1688 Scraper is here. Start with one keyword and 40 results, look at the tiers, then scale up.

This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.

Top comments (0)