Command-line tool for Alibaba 1688.com wholesale: product search, supplier company search, supplier scraper/research, image search, supplier inquiry, cart, checkout, order tracking, and seller chat. Outputs JSON when piped (for Codex / Claude Code / other AI agents) and pretty TTY text for humans.
The 6 things you can do from the terminal:
- Sourcing — product scraper/research + supplier scraper/research
- Pre-sale inquiry — ask the supplier, watch replies live
- Cart — collect SKUs (with diff-based add confirmation)
- Checkout — preview + place the order
- Order tracking — list / detail / logistics / overdue detection
- Post-sale chat — chase shipment, read replies as JSON stream
npm i -g 1688-cli
1688 login # scan QR with the 1688 app
# Product scraper / product research
1688 search "佛龛柜" --max 10 # keyword search
1688 search "手机壳" --sort best-selling --price-max 50 # sorted/filtered sourcing
1688 research 手机壳 数据线 --max-per-query 50 --jsonl # multi-keyword research dataset
1688 image-search ./sample.jpg # search by image
1688 offer 628196518518 # product detail
1688 compare 628196518518 1234567890 # compare offer details
# Supplier scraper / supplier research
1688 supplier search 键盘 --factory-only --json # supplier discovery from company search
1688 supplier research 键盘 --enrich top:5 --csv # supplier scoring + inspect enrichment
1688 supplier inspect 628196518518 # inspect supplier/factory trust signals
# Pre-sale inquiry (with live watch for AI agents)
1688 seller inquire 628196518518 "支持定制 logo 吗?" # ask seller
1688 seller messages --offer 628196518518 # one-shot read
1688 seller messages --offer 628196518518 --watch # live-tail new replies (JSON when piped)
# Order tracking & post-sale chat
1688 order list --status waitsellersend # list orders
1688 order get <orderId> # one order detail
1688 order logistics <orderId> # tracking + trace
1688 seller chat <orderId> "麻烦尽快发货谢谢" # chase shipment
1688 seller messages <orderId> # read seller's replyExisting 1688 automation options are heavy: Selenium glue you maintain, browser
extensions you can't pipe into a shell, MCP servers that fight with your
agent's tooling. 1688-cli is a single command:
- Real Chrome under the hood (
channel:'chrome'). Same browser you'd use manually — your session is real, not a synthetic Chromium. - Persistent profiles under
~/.1688/. One login lasts for weeks, and multiple buyer profiles can stay isolated. - Profile-scoped daemon — each profile can keep its own warm browser context, so subsequent commands reuse it without relaunching Chrome.
- JSON-or-text dual mode —
1688 order list | jqworks;1688 order listin your terminal pretty-prints. - Designed for AI agents. See AGENTS.md for the contract.
This is not a marketing / scraping tool for bulk-listing the whole site, and
not a checkout automation farm. It mirrors what a buyer does manually: pick
a product, ask the seller a question, place an order, track shipping. Place
order (checkout confirm) is gated behind TTY prompts or an explicit
--agent flag so agents can't move money silently.
Requires Node 20+ and (recommended) Google Chrome installed. Without Chrome, postinstall downloads Playwright's bundled Chromium (~150 MB; China users get the npmmirror automatically).
npm i -g 1688-cli
1688 doctor # verify environment
1688 login # one-time, scan QR on phoneOrganized by the buyer journey: discover → ask → decide → buy → track → follow up.
Sourcing has two separate paths. Use Product Scraper / Product Research when you start from products or offers. Use Supplier Scraper / Supplier Research when you start from companies, factories, or supplier qualification.
1688 search 机械键盘 --max 20 # keyword search
1688 search 手机壳 --sort best-selling --price-max 50 --exclude-ads
1688 research 手机壳 数据线 --max-per-query 50 --enrich top:5 --csv
1688 image-search ./shoe.jpg # search by local image
1688 image-search https://.../img.png # search by http(s) URL
1688 offer 628196518518 # product detail (priceTiers, attributes, packageInfo, SKUs)
1688 compare 628196518518 1234567890 # compare price/MOQ/SKU/sales signals1688 search and 1688 research are offer-first. They search product offers,
score offer results, export datasets, and can enrich top offers through detail
pages. Use this path when price, MOQ, SKU depth, sales signals, images, and
offer-level comparison are the first decision points.
1688 similar <offerId> is retained for compatibility with the official
1688 "找同款" entry point, but that entry point currently returns an empty
image-search shell for tested offers. The command does not fall back to
keyword or image search because those results are not strict same-product
matches.
1688 supplier search 键盘 --factory-only # company-search supplier discovery, not offer aggregation
1688 supplier search 键盘 --max 20 --province 广东 --city 深圳
1688 supplier research 键盘 --enrich top:5 --csv # supplier scoring + optional supplier inspect enrichment
1688 supplier inspect 628196518518 # supplier identity, factory card, trust/service signals
1688 supplier inspect b2b-22066467246504ba0d # inspect by supplier memberId1688 supplier search is the read-only 1688 Supplier Scraper. It pulls
supplier/company records directly from 1688 company search
(companySearchBusinessService) for a keyword and filters. It does not build
suppliers by grouping product-offer results.
1688 supplier research is the scored/export workflow on top of that supplier
scraper, with optional supplier inspect enrichment for the top companies.
Use this path when factory identity, service years, repeat/response rates,
location, company profile, and supplier qualification are the first decision
points.
| Need | Command |
|---|---|
| Find product offers | 1688 search <keyword...> |
| Build a scored product dataset | 1688 research <keyword...> |
| Official same-product matching | 1688 similar <offerId> (currently unavailable when the official endpoint returns empty) |
| Inspect one product offer | 1688 offer <offerId> |
| Compare product offers | 1688 compare <offerId...> |
| Find companies or factories directly | 1688 supplier search <keyword...> |
| Build a scored supplier dataset | 1688 supplier research <keyword...> |
| Inspect one supplier/factory | `1688 supplier inspect <offerId |
Supplier company-search flags:
1688 supplier search 键盘 --max 20 --factory-only --province 广东 --city 深圳
1688 supplier search 键盘 --min-years 3 --min-repeat-rate 0.4 --min-response-rate 0.6
1688 supplier research 键盘 --enrich top:10 --jsonl
1688 supplier research 键盘 --enrich top:5 --csv --output suppliers.csvsupplier search defaults to no enrichment (--enrich 0). supplier research
defaults to --enrich top:10, which calls supplier inspect for the top
company-search suppliers when a memberId is available. The supplier result
includes company name, memberId, shop URL, location, service years, factory
signals, repeat/response rates, 3-month order/amount signals, score breakdown,
and product previews from the company-search payload.
Uses the same
seller messages/seller chattooling as §6, scoped by--offer <offerId>instead of an orderId.
1688 seller inquire 628196518518 "支持定制 logo 吗?" # send a product link + question
1688 seller messages --offer 628196518518 # read replies (one-shot)
1688 seller messages --offer 628196518518 --since 2026-05-13T10:00:00+08:00
1688 seller messages --offer 628196518518 --watch --interval 30 # live-tail new repliesWatch mode prints only newly-arrived messages as line-delimited JSON
when stdout is piped — pipe into any agent. Dedup is by server-side
messageId. Min interval 10 s.
1688 cart list
1688 cart add <offerId> --sku <skuId> --qty 2
1688 cart remove <cartId>cart add returns {added: CartItem, isNewRow, addedQuantity} so pipelines
can pick up the new cartId reliably even when the same SKU is already in cart
(server merges into the existing row in that case):
id=$(1688 cart add 628196518518 --sku 6070845665229 --qty 1 | jq -r '.added.cartId')
1688 cart remove "$id"PowerShell equivalent:
$added = 1688 cart add 628196518518 --sku 6070845665229 --qty 1 --json | ConvertFrom-Json
1688 cart remove $added.added.cartId1688 checkout prepare <cartIds...> # preview total/address/items — safe, read-only
1688 checkout confirm <cartIds...> # default: TTY prompt y/N
1688 checkout confirm <cartIds...> -y # skip prompt (TTY still required)
1688 checkout confirm <cartIds...> --agent # AI-agent mode: no prompts (explicit autonomy opt-in)1688 order list # all statuses (with actions, services, badges)
1688 order list --status waitsellersend # paid, awaiting shipment
1688 order list --status waitbuyerreceive # shipped, awaiting delivery
1688 order get <orderId> # one order detail
1688 order logistics <orderId> # tracking number + trace
1688 order get <orderId> --status waitbuyerreceive # narrow the scan on heavy accounts
# Convenience views
1688 shipped <orderId> # order detail + logistics merged
1688 stuck --days 3 # paid but not shipped > N days
1688 fake-shipped --days 1 # marked shipped but courier never collected (虚假发货)
1688 fake-shipped --debug # show each candidate's status + remark
1688 seller-history <sellerName> # all orders + avg ship days + on-time rateSame tooling as §2, scoped by
<orderId>so messages auto-attach the order card and replies thread under the right conversation.
1688 seller chat <orderId> "麻烦尽快发货谢谢" # send (auto-attaches order card)
1688 seller chat <orderId> "请问什么时候发货" --no-card # follow-up, no card
1688 seller messages <orderId> # read replies
1688 seller messages <orderId> --limit 50 --since 2026-05-01T00:00:00+08:00
1688 seller messages <orderId> --watch # live-tail1688 login # scan QR; auto-starts daemon
1688 login --headed # open real window (fallback for risk control)
1688 login --force # re-login even if cached
1688 logout # clear cookies
1688 whoami # current nick + memberId
1688 doctor # environment check
1688 daemon start | stop | status | reloadEvery command uses the default profile unless you pass --profile <name>.
Default behavior is backwards-compatible: 1688 search 雨伞 uses the default
profile, default daemon, default lock, and default cached identity.
Use profiles when you operate more than one buyer account or want isolated cookie/session state:
1688 login --profile acc-a --headed
1688 login --profile acc-b --headed
1688 daemon start --profile acc-a
1688 daemon start --profile acc-b
1688 daemon status --profile acc-a
1688 daemon status --profile acc-b
1688 search "实木床头柜" --profile acc-a
1688 search "实木床头柜" --profile acc-b
1688 profile list
1688 profile status acc-a
1688 doctor --profile acc-aEach profile has its own persistent browser directory, daemon process, socket/named pipe, pid/version/log files, state file, and lock. Different profiles can run in parallel; commands for one profile do not wait on another profile's lock. Within one profile, daemon work remains serialized and paced.
1688-cli runs as a regular shell command, not an MCP server. Agents call it
via child_process or shell pipes instead of the MCP protocol — easier to
compose with jq, xargs, and CI scripts. Compared to writing low-level
browser automation directly, 1688-cli ships with structured JSON output,
session persistence, and a daemon for warm context, so you don't reinvent
that per project.
Alibaba offers a 1688 Open API at open.1688.com, but it's gated to
enterprise ISV partners with a sales contract and per-app authorization.
Individual buyers, small businesses, and AI agents typically can't get
access. 1688-cli uses your normal logged-in buyer account via a one-time
QR scan, mirroring what you can do manually in a browser — no developer
keys required.
No. Login is a one-time QR scan with your normal 1688 mobile app — the
same flow as logging into 1688 on a fresh browser. The default session is
stored in your local profile (~/.1688/profiles/default/) and reused across
commands, so you only re-scan when 1688 invalidates it. Named profiles use
their own directories under ~/.1688/profiles/<name>/.
1688 occasionally shows a slider verification on unfamiliar sessions or
after long inactivity — the same one you'd see when logging in from a new
device manually. If a command fails because of this, run it once with
--headed (e.g. 1688 search 雨伞 --headed); a real window opens, you
drag the slider yourself, and the verified session is reused for
subsequent commands. There is no automated solver — it's the same manual
step a person would take.
The tool drives your own logged-in browser session and only performs
actions you'd do manually — search, read order details, send chat
messages, place an order you confirmed. Use it at human pace (the default
--watch interval is 30 seconds, minimum 10) for one of your own
accounts. Aggressive automation, high-frequency scraping, or running it
across many accounts is outside the tool's design and increases the
chance of triggering 1688's risk controls.
Every command auto-switches to JSON when stdout is piped:
1688 order list --status waitsellersend | jq '.orders[] | {id: .orderId, paid: .paidAt}'
1688 fake-shipped --debug | jq '.orders[].orderId'
1688 search 雨伞 | jq '.offers[0:5]'
1688 supplier search 键盘 | jq '.items[0] | {company: .supplier.companyName, memberId: .supplier.memberId, score}'
1688 supplier research 键盘 --enrich top:1 | jq '{source,total,enrichedCount,first: .items[0].supplier.companyName}'Supplier-search JSON explicitly carries source provenance:
{
"source": {
"kind": "company-search",
"endpoint": "companySearchBusinessService",
"offerAggregation": false
}
}Every command supports four output-shaping flags. Useful on Windows or any
environment where jq isn't installed — and for agents that want concise
output without parsing the full payload.
1688 offer <id> --json # force JSON even in a TTY
1688 offer <id> --json --pretty # JSON with 2-space indent
1688 offer <id> --get supplier.name # one scalar field, raw line
1688 offer <id> --get supplier # sub-object as JSON
1688 offer <id> --get 'skus[0].skuId' # array index
1688 offer <id> --get 'skus[*].price' # wildcard — one line per element
1688 offer <id> --pick price,supplier.name,'skus[0].skuId'
# {"price":1.25,"supplier.name":"...","skus[0].skuId":"..."}Path syntax: field.sub, arr[N].field, arr[*].field. Wildcards stream
one line per element; scalars print as a raw line (no quotes), objects and
arrays as JSON. The full payload still goes through when no --get/--pick
is given, so existing | jq pipelines keep working unchanged.
Force JSON in a TTY (alternative to --json):
BB1688_JSON=1 1688 doctorPowerShell:
$env:BB1688_JSON = "1"
1688 doctor
Remove-Item Env:\BB1688_JSONThe npm 1688 shim works from PowerShell and cmd.exe. Prefer built-in
--get / --pick when jq is not installed:
1688 offer 628196518518 --get supplier.name
1688 supplier search 键盘 --pick total,source.kind,'items[0].supplier.companyName'
1688 supplier research 键盘 --csv --output "$env:TEMP\suppliers.csv"Daemon management is the same command surface:
1688 daemon start
1688 daemon status --json
1688 daemon stop
1688 daemon start --profile acc-a
1688 daemon status --profile acc-a --json
1688 daemon stop --profile acc-aIf 1688 shows a slider verification (滑块), solve it once with --headed:
1688 search 雨伞 --headed # window opens; drag the slider yourself
1688 supplier search 键盘 --headed
1688 search 雨伞 # subsequent calls reuse the verified sessionSee also the FAQ entry on verification challenges.
~/.1688/profiles/default/ Chromium profile (macOS/Linux)
~/.1688/state.json cached identity (macOS/Linux)
~/.1688/daemon.sock daemon Unix socket (macOS/Linux)
~/.1688/daemon.pid daemon PID
~/.1688/.lock proper-lockfile (one process at a time)
~/.1688/profiles/<name>/state.json named-profile cached identity
~/.1688/profiles/<name>/daemon.sock named-profile daemon Unix socket
~/.1688/profiles/<name>/daemon.pid named-profile daemon PID
~/.1688/profiles/<name>/.lock named-profile lock
%USERPROFILE%\.1688\profiles\default\ Chromium profile (Windows)
%USERPROFILE%\.1688\state.json cached identity (Windows)
\\.\pipe\1688-cli-daemon-<hash> daemon named pipe (Windows)
\\.\pipe\1688-cli-daemon-<hash>-<hash> named-profile daemon pipe (Windows)
BB1688_NO_DAEMON=1 disable daemon, always run inline
BB1688_JSON=1 force JSON output on TTY
BB1688_DEBUG=1 verbose internal logs to stderr
BB1688_FORCE_CHROMIUM=1 skip system Chrome, use bundled Chromium
BB1688_HOME=<path> override ~/.1688 or %USERPROFILE%\.1688
BB1688_SKIP_POSTINSTALL=1 skip Chromium download during npm install
PLAYWRIGHT_DOWNLOAD_HOST custom Playwright mirror
Pre-1.0 — the surface is shaped but minor breaks are possible between minor versions until 1.0. See CHANGELOG.md. Not affiliated with Alibaba / 1688.
If you're driving 1688-cli from Codex, Claude Code, or another autonomous
agent, read AGENTS.md — it documents JSON shapes, exit codes,
and the rules around the write commands.