1688 按图搜索(拍立淘)是 B2B 电商领域极具价值的能力,支持通过上传商品图片检索相似货源。本文将系统性地介绍 Java 环境下接入 1688 图搜接口的完整方案,涵盖官方开放平台 API、跨境/分销场景接口以及第三方聚合服务。
一、接口体系概览
1688 图搜接口根据业务场景分为多条路径,开发者需根据实际需求选择:
| 接入路径 | 接口地址 | 认证方式 | 适用场景 | 图片输入方式 |
|---|---|---|---|---|
| 官方商品图搜 | alibaba.product.image.search | OAuth2 access_token | 通用商品搜索、比价工具 | 本地图片上传(multipart) |
| 跨境图搜 | 跨境采购解决方案内接口 | 方案订购 + access_token | 跨境买家、ERP 服务商 | 图片 URL |
| 分销图搜 | 社交电商采购解决方案内接口 | 方案订购 + access_token | 社交分销、内容电商 | 图片 URL |
| 第三方聚合 API | 各服务商自定义地址 | apiToken | 快速集成、多语言支持 | 图片 URL / Base64 |
二、路径一:官方开放平台商品图搜接口
2.1 接入准备
- 注册企业开发者账号
- 完成实名认证,创建应用获取 App Key 和 App Secret
- 在应用权限管理中申请 alibaba.product.image.search 接口权限
- 通过 OAuth2.0 授权流程获取 access_token(有效期 2 小时,需缓存刷新)
2.2 图片要求
| 要求项 | 规范 | 说明 |
|---|---|---|
| 格式 | JPG / JPEG / PNG | 不支持 GIF、WebP |
| 大小 | 建议 < 1MB | 过大易导致请求超时 |
| 分辨率 | 最小边 ≥ 256 像素 | 过小影响识别精度 |
| 内容 | 清晰商品主体图 | 避免模糊、多主体、纯文字图 |
2.3 核心请求参数
| 参数名 | 类型 | 必选 | 说明 |
|---|---|---|---|
access_token | String | 是 | OAuth2 授权令牌 |
image | File | 是 | 商品图片文件(multipart 上传) |
page | Integer | 否 | 页码,默认 1 |
pageSize | Integer | 否 | 每页条数,默认 20,最大 50 |
similarDegree | Float | 否 | 相似度阈值(0~1),默认无限制 |
2.4 完整 Java 实现代码
import okhttp3.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 1688 官方开放平台 - 按图搜索商品 API Java 客户端
* 接口:alibaba.product.image.search
*/
public class Official1688ImageSearchClient {
// 1688 开放平台网关地址
private static final String GATEWAY_URL =
"https://gw.open.1688.com/openapi/param2/1/com.alibaba.product/alibaba.product.image.search";
private final String accessToken;
private final OkHttpClient httpClient;
public Official1688ImageSearchClient(String accessToken) {
this.accessToken = accessToken;
this.httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
}
/**
* 通过本地图片文件搜索相似商品
*
* @param imageFile 本地图片文件
* @param page 页码
* @param pageSize 每页数量
* @param similarDegree 相似度阈值(0.0~1.0)
* @return 搜索结果
*/
public ImageSearchResult searchByImage(File imageFile, int page, int pageSize, Double similarDegree)
throws IOException {
// 构建 multipart 请求体
MultipartBody.Builder multipartBuilder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("access_token", accessToken)
.addFormDataPart("page", String.valueOf(page))
.addFormDataPart("pageSize", String.valueOf(pageSize));
// 添加图片文件
String mimeType = getMimeType(imageFile.getName());
multipartBuilder.addFormDataPart(
"image",
imageFile.getName(),
RequestBody.create(MediaType.parse(mimeType), imageFile)
);
// 可选:相似度阈值
if (similarDegree != null) {
multipartBuilder.addFormDataPart("similarDegree", String.valueOf(similarDegree));
}
Request request = new Request.Builder()
.url(GATEWAY_URL)
.post(multipartBuilder.build())
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("HTTP 请求失败,状态码: " + response.code());
}
String responseBody = response.body().string();
return parseResponse(responseBody);
}
}
/**
* 通过图片 URL 搜索(部分场景支持,需先上传图片到 1688 图床获取 URL)
*/
public ImageSearchResult searchByImageUrl(String imageUrl, int page, int pageSize)
throws IOException {
// 注意:官方接口主要支持文件上传,URL 方式需先将图片上传至 1688 图床
// 此处演示通过 multipart 的变通方式
FormBody formBody = new FormBody.Builder()
.add("access_token", accessToken)
.add("page", String.valueOf(page))
.add("pageSize", String.valueOf(pageSize))
.add("imageUrl", imageUrl) // 部分版本支持
.build();
Request request = new Request.Builder()
.url(GATEWAY_URL)
.post(formBody)
.build();
try (Response response = httpClient.newCall(request).execute()) {
String responseBody = response.body().string();
return parseResponse(responseBody);
}
}
/**
* 解析 JSON 响应
*/
private ImageSearchResult parseResponse(String jsonResponse) {
JSONObject root = JSON.parseObject(jsonResponse);
// 检查顶层错误
if (root.containsKey("error")) {
JSONObject error = root.getJSONObject("error");
return ImageSearchResult.error(
error.getString("code"),
error.getString("message")
);
}
// 解析 result 结构
JSONObject result = root.getJSONObject("result");
if (result == null) {
return ImageSearchResult.error("NO_RESULT", "响应中无 result 字段");
}
boolean success = result.getBooleanValue("success", true);
if (!success) {
return ImageSearchResult.error(
result.getString("errorCode"),
result.getString("errorMessage")
);
}
// 解析商品列表
JSONArray productList = result.getJSONArray("productList");
List<SearchProduct> products = new ArrayList<>();
if (productList != null) {
for (int i = 0; i < productList.size(); i++) {
JSONObject item = productList.getJSONObject(i);
SearchProduct product = new SearchProduct();
product.setProductId(item.getString("productId"));
product.setTitle(item.getString("title"));
product.setImageUrl(item.getString("imageUrl"));
product.setSimilarity(item.getDoubleValue("similarity"));
product.setPrice(item.getString("price"));
product.setMinOrderQuantity(item.getString("minOrderQuantity"));
product.setSellerId(item.getString("sellerId"));
product.setSellerName(item.getString("sellerName"));
product.setDetailPageUrl(item.getString("detailPageUrl"));
products.add(product);
}
}
ImageSearchResult searchResult = new ImageSearchResult();
searchResult.setSuccess(true);
searchResult.setTotalResults(result.getIntValue("totalResults"));
searchResult.setPage(result.getIntValue("page"));
searchResult.setPageSize(result.getIntValue("pageSize"));
searchResult.setProducts(products);
return searchResult;
}
/**
* 根据文件名推断 MIME 类型
*/
private String getMimeType(String fileName) {
String ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
return switch (ext) {
case "jpg", "jpeg" -> "image/jpeg";
case "png" -> "image/png";
case "gif" -> "image/gif";
default -> "application/octet-stream";
};
}
// ==================== 数据模型 ====================
public static class ImageSearchResult {
private boolean success;
private String errorCode;
private String errorMessage;
private int totalResults;
private int page;
private int pageSize;
private List<SearchProduct> products;
public static ImageSearchResult error(String code, String message) {
ImageSearchResult r = new ImageSearchResult();
r.success = false;
r.errorCode = code;
r.errorMessage = message;
return r;
}
// Getters & Setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getErrorCode() { return errorCode; }
public void setErrorCode(String errorCode) { this.errorCode = errorCode; }
public String getErrorMessage() { return errorMessage; }
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
public int getTotalResults() { return totalResults; }
public void setTotalResults(int totalResults) { this.totalResults = totalResults; }
public int getPage() { return page; }
public void setPage(int page) { this.page = page; }
public int getPageSize() { return pageSize; }
public void setPageSize(int pageSize) { this.pageSize = pageSize; }
public List<SearchProduct> getProducts() { return products; }
public void setProducts(List<SearchProduct> products) { this.products = products; }
}
public static class SearchProduct {
private String productId;
private String title;
private String imageUrl;
private double similarity;
private String price;
private String minOrderQuantity;
private String sellerId;
private String sellerName;
private String detailPageUrl;
// Getters & Setters
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getImageUrl() { return imageUrl; }
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
public double getSimilarity() { return similarity; }
public void setSimilarity(double similarity) { this.similarity = similarity; }
public String getPrice() { return price; }
public void setPrice(String price) { this.price = price; }
public String getMinOrderQuantity() { return minOrderQuantity; }
public void setMinOrderQuantity(String minOrderQuantity) { this.minOrderQuantity = minOrderQuantity; }
public String getSellerId() { return sellerId; }
public void setSellerId(String sellerId) { this.sellerId = sellerId; }
public String getSellerName() { return sellerName; }
public void setSellerName(String sellerName) { this.sellerName = sellerName; }
public String getDetailPageUrl() { return detailPageUrl; }
public void setDetailPageUrl(String detailPageUrl) { this.detailPageUrl = detailPageUrl; }
}
// ==================== 使用示例 ====================
public static void main(String[] args) {
// 替换为通过 OAuth2 获取的有效 access_token
String accessToken = "your_access_token_here";
Official1688ImageSearchClient client = new Official1688ImageSearchClient(accessToken);
try {
File imageFile = new File("/path/to/your/product.jpg");
ImageSearchResult result = client.searchByImage(imageFile, 1, 20, 0.7);
if (result.isSuccess()) {
System.out.println("搜索成功,共找到 " + result.getTotalResults() + " 个商品");
System.out.println("当前页: " + result.getPage() + ", 每页: " + result.getPageSize());
for (SearchProduct product : result.getProducts()) {
System.out.println("------------------------------");
System.out.println("商品ID: " + product.getProductId());
System.out.println("标题: " + product.getTitle());
System.out.println("价格: " + product.getPrice());
System.out.println("相似度: " + product.getSimilarity());
System.out.println("最小起订量: " + product.getMinOrderQuantity());
System.out.println("卖家: " + product.getSellerName());
System.out.println("详情页: " + product.getDetailPageUrl());
}
} else {
System.err.println("搜索失败: [" + result.getErrorCode() + "] " + result.getErrorMessage());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.5 Maven 依赖
<dependencies>
<!-- OkHttp HTTP 客户端 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- FastJSON JSON 解析 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
三、路径二:跨境/分销场景图搜接口
1688 针对不同业务场景提供了专用图搜能力,需先订购对应解决方案。
3.1 跨境图搜商品 API
适用于跨境买家和 ERP 服务商,搜索 1688 跨境商品池中的相似商品。
前置条件:订购《跨境采购解决方案》或《跨境 ERP 对接解决方案》
核心参数:
| 参数 | 类型 | 必选 | 说明 |
|---|---|---|---|
imageUrl | String | 是 | 图片 URL(公网可访问) |
page | Integer | 否 | 页码,默认 1 |
priceMin / priceMax | String | 否 | 价格区间过滤 |
sort | String | 否 | 排序:price_asc, price_desc, sales_desc调用流程: |
- 调用图搜跨境商品 API,获取商品列表(含 offerId)
- 调用 alibaba.cross.productInfo 传入 offerId 获取商品详情
3.2 分销图搜商品 API
适用于社交分销买家,搜索 1688 支持分销的商品池。
前置条件:订购《社交电商采购对接解决方案》
调用流程:
- 调用图搜分销商品 API,获取 offerId 列表
- 调用 alibaba.cpsMedia.productInfo 传入 offerId 获取商品详情
3.3 Java 封装(跨境场景)
import okhttp3.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* 1688 跨境图搜商品 API 客户端
*/
public class CrossBorderImageSearchClient {
// 跨境图搜接口地址(需根据实际文档确认)
private static final String CROSS_BORDER_URL =
"https://gw.open.1688.com/openapi/param2/1/com.alibaba.cross/cross.product.image.search";
private final String accessToken;
private final OkHttpClient httpClient;
public CrossBorderImageSearchClient(String accessToken) {
this.accessToken = accessToken;
this.httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
/**
* 跨境图搜 - 通过图片 URL 搜索
*/
public JSONObject searchCrossBorderByImageUrl(String imageUrl, int page,
String priceMin, String priceMax, String sort) throws IOException {
FormBody.Builder formBuilder = new FormBody.Builder()
.add("access_token", accessToken)
.add("imageUrl", imageUrl)
.add("page", String.valueOf(page));
if (priceMin != null) formBuilder.add("priceMin", priceMin);
if (priceMax != null) formBuilder.add("priceMax", priceMax);
if (sort != null) formBuilder.add("sort", sort);
Request request = new Request.Builder()
.url(CROSS_BORDER_URL)
.post(formBuilder.build())
.build();
try (Response response = httpClient.newCall(request).execute()) {
String body = response.body().string();
return JSON.parseObject(body);
}
}
/**
* 获取跨境商品详情
*/
public JSONObject getCrossProductDetail(String offerId) throws IOException {
String url = "https://gw.open.1688.com/openapi/param2/1/com.alibaba.cross/alibaba.cross.productInfo";
FormBody formBody = new FormBody.Builder()
.add("access_token", accessToken)
.add("offerId", offerId)
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
try (Response response = httpClient.newCall(request).execute()) {
return JSON.parseObject(response.body().string());
}
}
}
四、路径三:第三方聚合 API 接入
对于需要快速集成、支持多语言或高并发场景,可使用第三方聚合 API 服务。
4.1 接口特点
- 支持图片 URL 直接搜索(无需上传文件)
- 提供多语言返回(en, zh, ru, th, pt, es 等)
- 丰富的筛选条件:价格区间、一件代发、工厂认证、包邮等
- 统一返回格式,降低接入成本
4.2 请求参数
| 参数 | 类型 | 必选 | 说明 |
|---|---|---|---|
img_url | String | 是 | 图片 URL(阿里系平台图片可直接识别) |
page | Integer | 否 | 页码,默认 1 |
page_size | Integer | 否 | 每页数量,默认 20,最大 20 |
sort | String | 否 | default / sales / price_up / price_down |
price_start / price_end | String | 否 | 价格区间 |
support_dropshipping | Boolean | 否 | 筛选支持一件代发 |
is_factory | Boolean | 否 | 筛选工厂店 |
verified_supplier | Boolean | 否 | 筛选实力商家 |
language | String | 否 | 返回语言,默认 en |
4.3 Java 实现
import okhttp3.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* 第三方聚合 API - 1688 图搜客户端
*/
public class ThirdPartyImageSearchClient {
private final String apiToken;
private final String baseUrl;
private final OkHttpClient httpClient;
public ThirdPartyImageSearchClient(String apiToken, String baseUrl) {
this.apiToken = apiToken;
this.baseUrl = baseUrl; // 如 https://api.xxx.com
this.httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
/**
* 通过图片 URL 搜索 1688 商品
*/
public JSONObject searchByImageUrl(String imageUrl, int page, int pageSize,
String sort, String priceStart, String priceEnd,
Boolean supportDropshipping, Boolean isFactory,
Boolean verifiedSupplier, String language) throws IOException {
HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/search-items-by-image-url").newBuilder();
urlBuilder.addQueryParameter("apiToken", apiToken);
urlBuilder.addQueryParameter("img_url", imageUrl);
urlBuilder.addQueryParameter("page", String.valueOf(page));
urlBuilder.addQueryParameter("page_size", String.valueOf(pageSize));
if (sort != null) urlBuilder.addQueryParameter("sort", sort);
if (priceStart != null) urlBuilder.addQueryParameter("price_start", priceStart);
if (priceEnd != null) urlBuilder.addQueryParameter("price_end", priceEnd);
if (supportDropshipping != null) urlBuilder.addQueryParameter("support_dropshipping", String.valueOf(supportDropshipping));
if (isFactory != null) urlBuilder.addQueryParameter("is_factory", String.valueOf(isFactory));
if (verifiedSupplier != null) urlBuilder.addQueryParameter("verified_supplier", String.valueOf(verifiedSupplier));
if (language != null) urlBuilder.addQueryParameter("language", language);
Request request = new Request.Builder()
.url(urlBuilder.build())
.get()
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("请求失败,状态码: " + response.code());
}
return JSON.parseObject(response.body().string());
}
}
/**
* 简化调用 - 仅传必要参数
*/
public JSONObject searchByImageUrlSimple(String imageUrl, int page) throws IOException {
return searchByImageUrl(imageUrl, page, 20, "default", null, null, null, null, null, "zh");
}
}
五、图片上传与 URL 转换
官方接口要求本地图片上传,而跨境/第三方接口需要图片 URL。实际开发中常需先将图片上传至图床获取 URL。
5.1 图片上传至 1688 图床
import okhttp3.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.io.File;
import java.io.IOException;
/**
* 1688 图片上传工具 - 获取图片 URL
*/
public class ImageUploadUtil {
private static final String UPLOAD_URL =
"https://gw.open.1688.com/openapi/param2/1/com.alibaba.product/alibaba.product.image.upload";
private final String accessToken;
private final OkHttpClient httpClient;
public ImageUploadUtil(String accessToken) {
this.accessToken = accessToken;
this.httpClient = new OkHttpClient();
}
/**
* 上传图片到 1688 图床,返回图片 URL
*/
public String uploadImage(File imageFile) throws IOException {
RequestBody fileBody = RequestBody.create(
MediaType.parse("image/jpeg"),
imageFile
);
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("access_token", accessToken)
.addFormDataPart("image", imageFile.getName(), fileBody)
.build();
Request request = new Request.Builder()
.url(UPLOAD_URL)
.post(requestBody)
.build();
try (Response response = httpClient.newCall(request).execute()) {
JSONObject result = JSON.parseObject(response.body().string());
if (result.getBooleanValue("success")) {
return result.getString("imageUrl"); // 返回公网可访问的图片 URL
} else {
throw new IOException("上传失败: " + result.getString("errorMessage"));
}
}
}
}
六、返回结果解析
6.1 官方接口响应结构
{
"result": {
"success": true,
"productList": [
{
"productId": "610947785104",
"title": "2026夏季新款纯棉T恤",
"imageUrl": "https://cbu01.alicdn.com/xxx.jpg",
"similarity": 0.92,
"price": "15.00",
"minOrderQuantity": "50",
"sellerId": "b2b-123456789",
"sellerName": "XX服装厂",
"detailPageUrl": "https://detail.1688.com/offer/610947785104.html"
}
],
"totalResults": 156,
"page": 1,
"pageSize": 20
},
"errorCode": "0",
"errorMessage": "success"
}
6.2 核心返回字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
productId | String | 商品 ID(offerId) |
title | String | 商品标题 |
imageUrl | String | 商品主图 URL |
similarity | Double | 与查询图片的相似度(0~1) |
price | String | 商品价格 |
minOrderQuantity | String | 最小起订量 |
sellerId | String | 卖家 ID |
sellerName | String | 卖家名称 |
detailPageUrl | String | 商品详情页链接 |
totalResults | Integer | 匹配商品总数 |
七、常见问题与解决方案
| 问题现象 | 错误码 | 可能原因 | 解决方案 |
|---|---|---|---|
| 认证失败 | 401 | access_token 过期或无效 | 刷新 OAuth2 令牌,检查授权范围 |
| 参数错误 | 400 / 4003 | 图片格式不支持、参数缺失 | 确认图片为 JPG/PNG,检查必填参数 |
| 图片无法识别 | 400 | 图片 URL 非阿里系域名 | 先上传至 1688 图床获取内部 URL |
| 权限不足 | 403 | 未申请接口权限或未订购解决方案 | 在开放平台申请对应权限 |
| 调用频率超限 | 429 | QPS 超过限制 | 实现限流、增加请求间隔、申请提升额度 |
| 服务端错误 | 500 | 1688 服务端异常 | 重试请求,联系平台技术支持 |
| 无搜索结果 | - | 图片质量差或商品库无匹配 | 更换清晰商品主图,调整相似度阈值 |
八、最佳实践建议
- Token 管理:access_token 有效期 2 小时,建议实现自动刷新机制,使用 Redis 缓存
- 图片预处理:上传前压缩图片至 1MB 以内,提高响应速度
- 相似度阈值:根据业务场景调整 similarDegree,一般 0.7~0.9 效果较好
- 分页策略:搜索结果多时合理分页,避免一次性拉取过多数据
- 缓存机制:相同图片的搜索结果缓存 5-15 分钟,减少 API 调用
- 降级方案:接口异常时提供关键词搜索兜底
- 合规注意:遵守 1688 开放平台使用协议,仅用于合法业务场景
九、扩展应用场景
基于 1688 图搜接口可构建以下应用:
- 货源查找工具:上传竞品图片,快速找到源头工厂
- 供应链比价系统:同款商品多供应商价格对比
- 侵权检测:监控自家产品图片是否被他人盗用
- 智能选品:通过图片分析市场趋势,辅助采购决策
- ERP 集成:为跨境电商 ERP 提供以图搜货能力
如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。

