开发者文档
开放接口文档
阳28开放平台提供免费、只读的开奖数据面(加拿大28)。覆盖开奖与倒计时、Keno 源数据、已开 / 遗漏 / 长龙、四维人工智能预测,以及公开算法大厅与详情。HTTPS only,需 API Key;数据面读 Redis 缓存。个人 Key 无账号配额、不限流;门户 Demo Key 按 IP 软限流。短路径与旧开放面对齐。
提供
- 最近 N 期 / 按期号单期,含下期倒计时(加拿大28)
- Keno 二十码源数据
- 当日已开统计(带 date)、遗漏与长龙(期号版本)
- 单双 / 大小 / 双组 / 杀组预测
- 公开算法列表与命中摘要(展示序号
id)
不提供
- 算法公式
steps/ 私密说明 - 投注、资金、会员账本
- 站内会话接口
/bff/* - 探活
/api/health(公网不开放)
接口一览
12 个端点与 开放接口门户 一一对应。路径为短码(兼容旧开放面),不是 REST 资源名。所有数据接口均为 GET。
开奖数据最近 N 期开奖与下期倒计时/api/kj · nbr = 条数 1–100
按期号查开奖按期号取单期;倒计时仍相对最新期/api/qh · nbr = 期号(必填)
Keno 开奖源数据最近 N 期 Keno 二十码/api/keno · nbr = 条数 1–100
已开统计当日各玩法已开次数;响应带北京日历日 date/api/yk
遗漏各玩法未开期数,含常规与球类/api/yl
长龙连开形态(进行中 / 已断开),含起止期号/api/cl
人工智能·单双单双预测与开奖对照/api/ds · nbr = 条数 1–100
人工智能·大小大小预测与开奖对照/api/dx · nbr = 条数 1–100
人工智能·双组双组预测与开奖对照/api/sz · nbr = 条数 1–100
人工智能·杀组杀组预测与开奖对照/api/sha · nbr = 条数 1–100
算法大厅公开算法列表;近 20/100 期胜率,id 为展示序号/api/dt · sort / window / page
算法详情下期预测与近窗记录(不含公式)/api/sf · id = 展示序号(必填)接入约定
下列语义已与现网对齐。对接时按此实现,不要按字段名猜测。
| 约定 | 说明 |
|---|---|
nbr 两种含义 | /api/kj、/api/keno、四维预测:条数,1–100,省略为 1。/api/qh:期号,必填正整数。两种含义不要混用。 |
game | 不传、传 pc28、或任何未知值,一律按加拿大28;未知值不返回 400。例外:game=hx28(大小写不限)→ 400 VALIDATION(哈希28已下线)。Keno 为加拿大28 二十码。 |
| 参数对错 | 非法条数、非法期号、缺失/非法算法 id、未知 category → 400 VALIDATION,不会改成默认值。未知 sort 回落到近 20 或近 100 期胜率降序(看 window)。非法 page / pageSize 回落为 1 / 20;pageSize 上限 50。 |
| 开奖串 | /api/kj 的 number 是三位和式,如 1+8+3=12。预测接口把式子与和值拆开:number 为 1+8+3,num 为 12。 |
| 待开空值 | 预测接口待开用 JSON null。算法详情 records 待开行用空串 "",hit 仍为 null。两套不要混判。 |
| 期号类型 | 开奖 / 预测 / 长龙起止期号均为字符串。大厅算法 id 为数字(展示序号,不是 UUID)。 |
长龙 status | 中文文案,现网为「进行中」「已断开」。按字符串比较,不要当稳定枚举码。 |
| 时间 | 开奖 time 为北京时间字符串,如 2026-07-31 11:25:00,不是 ISO 8601 UTC。 |
| 路径后缀 | .json、无后缀(JSON)或 .xml。其它后缀 404 NOT_FOUND。成功才按后缀返回 XML;出错 body 始终是 JSON。XML 里 JSON null 写成空标签(如 <number/>)。 |
AI 读版
AI 对接请直接读 Markdown 契约,不要爬本页 HTML。
- AI 读版:
/developers/open-api.llms.md - 可对助手说:「按 https://yu28.top/developers/open-api.llms.md 接入开放接口」
一键提示词
请阅读 https://yu28.top/developers/open-api.llms.md
按其中的白名单路径、鉴权,以及「推荐连接与读取」,用我的 YU28_API_KEY 写对接代码。
跟开奖复用同一个 HTTP 客户端,只读 /api/kj.json?nbr=1,期号变化才算新开奖。
不要依赖 /bff/*;算法 id 用展示序号而非 UUID。
nbr 在 kj/keno/预测是条数,在 qh 是期号。
用 PHP 时:命令行 + curl 扩展,一个句柄复用;不要 file_get_contents,不要 Composer,不要 curl_close,不要放进网页请求。快速开始
- 1在
/app?tab=api生成 Key(明文只显示一次,请立刻保存) - 2请求头携带
X-Api-Key: yu28_…,不要把个人 Key 放进 URL - 3拉取
/api/kj.json?nbr=1验证连通
cURL
curl -sS -H "X-Api-Key: $YU28_API_KEY" \
"https://yu28.top/api/kj.json?nbr=1"JavaScript
const res = await fetch("https://yu28.top/api/kj.json?nbr=1", {
headers: { "X-Api-Key": process.env.YU28_API_KEY },
});
const body = await res.json();
if (!res.ok) throw new Error(body?.error?.message ?? res.statusText);Python
import os, requests
r = requests.get(
"https://yu28.top/api/kj.json",
params={"nbr": 1},
headers={"X-Api-Key": os.environ["YU28_API_KEY"]},
timeout=15,
)
r.raise_for_status()
print(r.json())PHP
命令行即可,用系统自带的 curl 扩展,不必安装 Composer。不要用 file_get_contents:很多主机 allow_url_fopen 是关的。已开 / 遗漏里的数字键(JSON "10")用 $row["10"] 或 $row[10] 都能读到。不要调用 curl_close:PHP 8.5 起会报弃用,句柄离开作用域会自己释放。
<?php
// YU28_API_KEY=yu28_… php kj.php
// 不要用 file_get_contents:很多主机 allow_url_fopen 是关的,也带不上稳定请求头。
$key = getenv("YU28_API_KEY");
$ch = curl_init("https://yu28.top/api/kj.json?nbr=1");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["X-Api-Key: " . $key, "Accept: application/json"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_USERAGENT => "yu28-php",
]);
$raw = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($raw === false) {
fwrite(STDERR, "网络失败\n");
exit(1);
}
$body = json_decode($raw, true);
if ($status !== 200) {
$message = (is_array($body) && isset($body["error"]["message"]))
? $body["error"]["message"]
: $raw;
fwrite(STDERR, $message . "\n");
exit(1);
}
print_r($body);/api/dt 拿展示序号 id,再调 /api/sf?id=。已知期号用 /api/qh?nbr=,不要用 /api/kj 的条数参数去查期号。连接与读取
加拿大28大约每 3.5 分钟一期。跟开奖时复用同一个 HTTPS 客户端,平时只读 /api/kj.json?nbr=1,用期号判断有没有新开奖。
推荐连接
- 只发
GET https://yu28.top/api/…。整个进程共用一个客户端(Python 用requests.Session;PHP 在命令行里curl_init一次,循环中只改 URL、不要curl_close)。不要每次新建客户端。PHP 跟开奖不要放进网页请求,请求结束连接就断了。 - 请求头
X-Api-Key(Authorization: Bearer也可以)。个人 Key 放环境变量,不要放进 URL,也不要写进前端仓库。 - 路径用
.json,不写后缀同样是 JSON。超时大约 10 秒。 400/401是参数或 Key 有误,改完再调。503或网络失败隔几秒再试。不需要 Cookie,也不要调用/bff/*。
推荐读取
data[0]是最新一期。nbr是字符串期号,和本地记下的不同才是新开奖;比较大小时先转成整数。number是三位和式(如1+8+3=12),time是北京时间。countdown是距下一次理论开奖的剩余时间(mm:ss或hh:mm:ss)。还剩超过 15 秒时,睡到大约还剩 10 秒再读,单次最多睡 20 秒,用来对齐时钟,不必每秒请求。- 最后 15 秒大约每秒读一次,直到
nbr变化。countdown变成00:00时,新期号通常还要几秒才出现,这几秒里期号仍是上一期。 - 到点后紧跟大约 20 秒,期号仍没变,就改成每 15 秒读一次。每日维护空档会停在
00:00较久,不要一直每秒打。 - 期号前进之后,再按需拉
/api/yk、/api/yl、/api/cl。已经知道期号时用/api/qh.json?nbr=期号(这里的nbr是期号)。补历史用nbr=条数(最多 100),不要用nbr=1连打。 - 算法先
/api/dt取展示序号,再/api/sf?id=,不必每期都拉大厅。
跟开奖(Python)
import os, time, requests
s = requests.Session()
s.headers["X-Api-Key"] = os.environ["YU28_API_KEY"]
last = None
unchanged = 0
def seconds(text):
parts = text.split(":") if text else []
if not parts or any(not p.isdigit() for p in parts):
return None
nums = [int(p) for p in parts]
if len(nums) == 2:
return nums[0] * 60 + nums[1]
if len(nums) == 3:
return nums[0] * 3600 + nums[1] * 60 + nums[2]
return None
while True:
try:
r = s.get(
"https://yu28.top/api/kj.json",
params={"nbr": 1},
timeout=10,
)
except requests.RequestException:
time.sleep(5)
continue
if r.status_code in (400, 401):
raise SystemExit(r.text)
if r.status_code != 200:
time.sleep(5)
continue
body = r.json()
row = body["data"][0]
if row["nbr"] != last:
print(row["nbr"], row["time"], row["number"], row["combination"])
last = row["nbr"]
unchanged = 0
# 新期到了再按需请求 /api/yk /api/yl /api/cl
else:
unchanged += 1
left = seconds(body.get("countdown") or "")
if left is not None and left > 15:
time.sleep(min(20, left - 10))
elif unchanged < 20:
time.sleep(1)
else:
time.sleep(15)
跟开奖(PHP,命令行)
保存为 follow.php 后执行 php follow.php。网页里每次请求都会结束,不能用来跟开奖。
<?php
// YU28_API_KEY=yu28_… php follow.php
// 不要放进网页请求:执行时间有上限,结束即断开。
$key = getenv("YU28_API_KEY");
if ($key === false || $key === "") {
fwrite(STDERR, "请设置环境变量 YU28_API_KEY\n");
exit(1);
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["X-Api-Key: " . $key, "Accept: application/json"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_TCP_KEEPALIVE => 1,
CURLOPT_USERAGENT => "yu28-php",
]);
$last = null;
$unchanged = 0;
function yu28_seconds($text) {
if (!is_string($text) || $text === "") {
return null;
}
$parts = explode(":", $text);
foreach ($parts as $part) {
if ($part === "" || !ctype_digit($part)) {
return null;
}
}
$nums = array_map("intval", $parts);
if (count($nums) === 2) {
return $nums[0] * 60 + $nums[1];
}
if (count($nums) === 3) {
return $nums[0] * 3600 + $nums[1] * 60 + $nums[2];
}
return null;
}
while (true) {
curl_setopt($ch, CURLOPT_URL, "https://yu28.top/api/kj.json?nbr=1");
$raw = curl_exec($ch);
if ($raw === false) {
sleep(5);
continue;
}
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status === 400 || $status === 401) {
fwrite(STDERR, $raw . "\n");
exit(1);
}
if ($status !== 200) {
sleep(5);
continue;
}
$body = json_decode($raw, true);
if (!is_array($body) || !isset($body["data"][0])) {
sleep(5);
continue;
}
$row = $body["data"][0];
if ($row["nbr"] !== $last) {
echo $row["nbr"], " ", $row["time"], " ", $row["number"], " ", $row["combination"], "\n";
$last = $row["nbr"];
$unchanged = 0;
// 新期到了再按需请求 /api/yk /api/yl /api/cl(继续用 $ch,只改 URL)
} else {
$unchanged += 1;
}
$left = yu28_seconds($body["countdown"] ?? "");
if ($left !== null && $left > 15) {
sleep(min(20, $left - 10));
} elseif ($unchanged < 20) {
sleep(1);
} else {
sleep(15);
}
}
鉴权与 Key
Key 形态为 yu28_ + 16 位十六进制;每账号最多 5 个有效 Key。生产环境请放在请求头,勿写入前端公开仓库。
GET /api/kj.json?nbr=1 HTTP/1.1
Host: yu28.top
X-Api-Key: yu28_你的密钥
# 等价
Authorization: Bearer yu28_你的密钥- 个人 Key 禁止放在 URL
?key=或?api_key=(二者同等;仅门户 Demo Key 可用 query)。误传个人 Key 会401 - 个人 Key 数据面不限流、不配额计费。Demo Key 按 IP 每分钟最多 60 次,超出
429 RATE_LIMIT - 管理入口:用户中心 / 接口管理
响应格式
本文示例一律 JSON。成功 HTTP 200;路径加 .json 或省略后缀(默认 JSON)。字段为驼峰 / 短英文键。
.xml(如 /api/kj.xml)。字段语义与 JSON 相同,仅序列化不同:根节点 <response>,数组元素多为 <item>;已开/遗漏里纯数字键写成 <k_10>(JSON 仍为 "10")。出错时 body 仍是 JSON,与后缀无关。错误处理
失败时 HTTP 为 4xx / 5xx,body 始终为 JSON(含请求 .xml 时):
{
"error": {
"code": "UNAUTHORIZED",
"message": "无效的 API Key"
}
}| HTTP | code | 含义 |
|---|---|---|
| 400 | VALIDATION | 参数无效:非法条数 / 期号、缺失或非法算法 id、未知 category、game=hx28(哈希28已下线) |
| 401 | UNAUTHORIZED | 缺少或错误的 Key,或把个人 Key 放进了 URL |
| 404 | NOT_FOUND | 期号不存在、算法不存在或未公开、路径后缀不是 json/xml |
| 429 | RATE_LIMIT | 仅 Demo Key:同一 IP 每分钟超过 60 次 |
| 503 | UNAVAILABLE / OPENAPI_UNAVAILABLE | 对应数据面未就绪,或开放 Key 服务未启用 |
开奖数据
/api/kj最近 N 期开奖(最新在前)。此处 nbr 是条数,不是期号。省略为 1;写出则须为 1–100 的正整数,否则 400。未知 game 按加拿大28;game=hx28 → 400 VALIDATION(哈希28已下线)。
GET /api/kj.json?nbr=3
{
"countdown": "02:40",
"data": [
{
"nbr": "3463701",
"time": "2026-07-31 11:25:00",
"number": "4+8+2=14",
"combination": "小双"
}
]
}| 字段 | 说明 |
|---|---|
countdown | 相对最新一期的下期倒计时,形如 02:40;未知可能为空串 |
data[].nbr | 期号(字符串) |
data[].time | 开奖时间,北京时间 |
data[].number | 三位和式,如 4+8+2=14 |
data[].combination | 大小单双组合文案,如 小双 |
按期号查开奖
/api/qh按期号取单期;字段与 /api/kj 单条一致。此处 nbr 是期号,必填正整数;缺参 400,查无 404。countdown 始终相对当前最新一期,不是所查那一期。
GET /api/qh.json?nbr=3463701
{
"countdown": "02:40",
"data": [
{
"nbr": "3463701",
"time": "2026-07-31 11:25:00",
"number": "4+8+2=14",
"combination": "小双"
}
]
}Keno 开奖源数据
/api/keno最近 N 期 Keno 二十码(加拿大28)。nbr 与 /api/kj 相同,表示条数。game=hx28 → 400 VALIDATION(哈希28已下线)。
GET /api/keno.json?nbr=1
{
"data": [
{
"nbr": "3463701",
"time": "2026-07-31 11:25:00",
"nbrs": "1,4,7,9,20,23,25,26,27,31,38,39,49,52,54,56,58,62,72,74"
}
]
}nbrs:20 个号码,逗号分隔、无空格。time 为源日期与时刻拼接(如 2026-07-31 11:25:00),不是 ISO。
已开统计
/api/yk当日已开次数(北京日历日)。date 为该份次数所属日;data 为扁平 map(数字键 / 玩法文案键)。大+小约等于该日已开期数。客户端须核 date,隔日包勿当今日。
GET /api/yk.json
{ "date": "2026-08-30", "data": { "10": 8, "大": 102, "小单": 48 } }遗漏
/api/yldata 扁平 map,值为遗漏期数;没有 date(以期号为版本)。
GET /api/yl.json长龙
/api/cl当前长龙列表。现网含进行中与已断开;status 为中文文案(「进行中」「已断开」),不要当机器枚举码。
GET /api/cl.json
{
"data": [
{
"type": "周期",
"content": "单双",
"status": "进行中",
"count": 8,
"start": "3463693",
"current": "3463700"
}
]
}| 字段 | 说明 |
|---|---|
type / content | 长龙类型与玩法内容(中文) |
status | 状态文案 |
count | 连续期数 |
start / current | 起始 / 当前期号(字符串) |
人工智能·单双
/api/ds四维路径:/api/ds(单双)· /api/dx(大小)· /api/sz(双组)· /api/sha(杀组)。nbr 为条数(最近 N 条,含待开期),规则同 /api/kj。
GET /api/ds.json?nbr=10
{
"data": [
{
"nbr": "3466878",
"predict": "双",
"number": null,
"num": null,
"result": null,
"hit": null
},
{
"nbr": "3466877",
"predict": "单",
"number": "1+2+3",
"num": "6",
"result": "单",
"hit": true
}
]
}| 字段 | 说明 |
|---|---|
predict | 预测文案(杀组为组合名,不含「杀」前缀) |
number / num | 已开:开奖串(无和值)/ 和值字符串;待开:均为 null |
result | 开奖维度结果:单双取组合第二字,大小取第一字,双组/杀组为完整组合;待开 null |
hit | true / false / null(待开) |
人工智能·大小
/api/dx字段与 /api/ds 相同;predict / result 为大小维度。
GET /api/dx.json?nbr=10人工智能·双组
/api/sz字段与 /api/ds 相同;predict / result 为双组组合文案。
GET /api/sz.json?nbr=10人工智能·杀组
/api/sha字段与 /api/ds 相同;predict 为组合名(不含「杀」前缀)。
GET /api/sha.json?nbr=10算法大厅
/api/dt公开算法排序列表。返回的 id 是主站展示序号(如 #909),不是 UUID。未知 category 返回 400;未知 sort 回落到近 20 期胜率降序,响应里的 sort 是服务端实际键。
| 参数 | 说明 |
|---|---|
sort | 别名 rate_desc / rate_asc 配合 window;或直接 rate20_desc / rate20_asc / rate100_desc / rate100_asc / streak_desc / miss_desc / created_desc / favorites_desc / max_streak_desc / max_miss_desc。未知值回落到近窗胜率降序。主序相同时按大厅复合次序(连挂再按近20胜率升序,胜率再按近100/连中/收藏/#no) |
window / nbr | 胜率窗口只认 20 或 100(默认 20)。大厅的 nbr 是窗口别名,不是条数 |
page / pageSize | 页码从 1;pageSize 默认 20、上限 50。非法值回落默认,不 400 |
category | 可选:big_small / odd_even / combo_predict / kill_group / double_group;未知 → 400 |
q | 可选关键词(名称等) |
game | 未知值忽略(加拿大28);hx28 → 400 VALIDATION(哈希28已下线) |
GET /api/dt.json?sort=rate_desc&window=20&pageSize=5
{
"items": [
{
"id": 909,
"name": "组合440",
"category": "combo_predict",
"author": "昵称",
"hit20": "20/20",
"hit100": "86/100",
"streak": 24,
"miss": 0,
"maxStreak": 24,
"maxMiss": 2
}
],
"page": 1,
"pageSize": 5,
"total": 8222,
"category": null,
"sort": "rate20_desc"
}hit20 / hit100 为命中比(命中率 = 分子÷分母);author 为昵称,可能为 null。响应 sort 是服务端实际键。
算法详情
/api/sfid 必填(该彩展示序号,可带 #)。不存在或未公开 → 404。在大厅字段上增加预测与近窗记录,不含公式。predict / predictNbr 在尚无下期预测时为 null。
records:最多 100 条已开 + 可选待开一行(插在最前)- 已开
number为三位和式(与/api/kj相同,如1+8+3=12);待开行time/number为空串,hit为null
GET /api/sf.json?id=909/api/dt 取 id,再调本接口。