主题
GET /api/keepa/bestseller
获取某品类的 Best Seller 榜单,结果是该品类下按销量排名的 ASIN 列表(最多 10000 条)。
对应 Keepa 官方接口:Request Best Sellers
接口
GET https://mcp.keepamore.com/api/keepa/bestseller也支持 别名 GET /api/keepa/bestsellers(与 Keepa 官方端点同名,复数),计费 / 缓存与主路径完全共享。
计费
| 项目 | units |
|---|---|
| 任意一次成功调用 | 10 |
任何参数都不会改变本接口的计费金额;分页切片在服务端完成,不影响 units。
参数(Query String)
| 名称 | 类型 | 必填 | 默认 | 约束 | 说明 |
|---|---|---|---|---|---|
domain | integer | ✅ | — | 1–12 | 站点 ID,参见 domain 映射。也可用 domainId / country 别名 |
category | integer | ✅ | — | ≥ 0 | 品类节点 ID;不知道 ID 时先用 categorysearch 反查 |
range | integer | 0 | 0/30/90/180 | 排名统计窗口(天):0 = 当前排名;30/90/180 = 对应天数均值排名 | |
variations | boolean | false | — | true 时仅返回每个父 ASIN 下月销最高的变体(去除同款 SKU 重复) | |
sublist | boolean | false | — | true 时使用子品类排名代替主排名 | |
page | integer | — | ≥ 0 | 分页页码;不传则返回全部 | |
perPage | integer | — | 1–10000 | 每页 ASIN 数量;不传则返回全部 |
分页行为:与 Keepa 原生行为一致——
page/perPage都不传时返回 asinList 全量;任一传了就启用分页(默认page=0/perPage=1000)。
响应
json
{
"code": "0000",
"msg": "ok",
"data": {
"bestSellersList": {
"asinList": ["B0...", "B0..."],
"_pagination": {
"page": 0,
"perPage": 100,
"total": 1234,
"totalPages": 13
}
},
"fromCache": false
}
}不启用分页时无 _pagination 字段。bestSellersList 完整字段(domainId / lastUpdate / categoryId / asinList)与 Keepamore 分页元信息见 Best Sellers Object。
示例
bash
# 请将 km_xxx 替换为你的 API Key
# 美国站电子产品类 Best Seller 前 100
curl "https://mcp.keepamore.com/api/keepa/bestseller?domain=1&category=172282&page=0&perPage=100" \
-H "X-API-Key: km_xxx"
# 近 30 天均值排名(返回全量 asinList)
curl "https://mcp.keepamore.com/api/keepa/bestseller?domain=1&category=172282&range=30" \
-H "X-API-Key: km_xxx"js
// 请将 km_xxx 替换为你的 API Key
const params = new URLSearchParams({
domain: "1",
category: "172282",
page: "0",
perPage: "100",
});
const r = await fetch(
`https://mcp.keepamore.com/api/keepa/bestseller?${params}`,
{ headers: { "X-API-Key": "km_xxx" } },
);
console.log(await r.json());python
# 请将 km_xxx 替换为你的 API Key
import requests
resp = requests.get(
"https://mcp.keepamore.com/api/keepa/bestseller",
params={"domain": 1, "category": 172282, "page": 0, "perPage": 100},
headers={"X-API-Key": "km_xxx"},
timeout=180,
)
print(resp.json())php
<?php
// 请将 km_xxx 替换为你的 API Key
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();
$resp = $client->get('https://mcp.keepamore.com/api/keepa/bestseller', [
'headers' => ['X-API-Key' => 'km_xxx'],
'query' => ['domain' => 1, 'category' => 172282, 'page' => 0, 'perPage' => 100],
'timeout' => 180,
]);
echo $resp->getBody();java
// 请将 km_xxx 替换为你的 API Key(Java 11+ 标准库,无需第三方依赖)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://mcp.keepamore.com/api/keepa/bestseller?domain=1&category=172282&page=0&perPage=100"))
.header("X-API-Key", "km_xxx")
.timeout(Duration.ofSeconds(180))
.GET()
.build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());go
// 请将 km_xxx 替换为你的 API Key(Go 标准库 net/http)
package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
url := "https://mcp.keepamore.com/api/keepa/bestseller?domain=1&category=172282&page=0&perPage=100"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("X-API-Key", "km_xxx")
client := &http.Client{Timeout: 180 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}典型配方
| 场景 | 建议参数 |
|---|---|
| 取前 100 当前畅销 ASIN | category=<id>&page=0&perPage=100 |
| 抓 30 天均值榜(更稳定的爆款) | category=<id>&range=30 |
| 父子去重(一个款只保留一个变体) | category=<id>&variations=1 |
| 用子品类排名替代主排名 | category=<id>&sublist=1 |
错误处理
通用错误码、metadata 字段定义见 错误码总览。常见情况:
- 缺少
category/domain,或range不在 0/30/90/180 → HTTP400,code以VALIDATION开头 - 上游 Keepa 拒绝或不可达 → HTTP
502,code = UPSTREAM_ERROR,可携带metadata.errorId联系支持