网站域名 ICP 备案实时查询接口技术解析:接入流程、返回字段与工程实践
本文以「域名 ICP 备案实时查询」接口为样例,讲透 API 网关场景下的通用接入方法(鉴权、参数设计、返回归一化、限流与重试、缓存与合规)。思路与代码可迁移到同类核验类接口。

1. 背景与适用场景
在合作尽调、内容审核、网络安全监测等场景中,经常需要核实一个网站是否完成 ICP 备案、备案主体是谁。手动到工信部备案系统逐条查询效率低、不适合工程化;通过开放接口按域名实时查询,可以把核验动作嵌入业务系统。
典型接入方:
- 金融 / 风控:在合作或放款前核验对方官网备案主体,降低虚假网站带来的欺诈风险。
- 电商 / 平台:对入驻商户的域名做备案合规性初筛。
- 政府与网络安全机构:批量监控辖区内网站的备案状态,发现未备案或备案异常站点。
- 市场研究:将备案主体信息作为企业活跃度与合规度的辅助信号。
接口定位是「按域名查询备案信息」,属于只读查询类服务,不写入、不修改任何外部数据。
2. 接口概览
| 项 | 说明 |
|---|---|
| 功能 | 根据域名查询其 ICP 备案信息(备案号、主体、网站名、备案时间、类型等) |
| 协议 | HTTPS |
| 方法 | GET |
| 路径 | /beian |
| 调用地址 | 由阿里云云市场控制台「调用信息」提供(每个应用独立网关域名) |
| 鉴权 | Authorization: APPCODE <appcode>(请求头携带) |
| 数据格式 | 请求/响应均为 JSON |
鉴权只需在请求头附加 Authorization: APPCODE xxxxxx 即可,无需对请求体做签名,接入成本低于 AppKey + AppSecret 签名模式。
3. 请求参数
请求以 Query 参数传递,仅需一个必填字段:
| 参数名 | 位置 | 类型 | 必填 | 说明 | 示例值 |
|---|---|---|---|---|---|
domain |
Query | string | 是 | 要查询备案的域名(不含协议头与路径) | www.example.com |
补充说明:
- Header 与 Body 均无必填参数,所有信息通过
domain一个 Query 参数表达。 - 域名建议只传主机名(如
www.example.com),不要带http://或末尾斜杠,避免后端解析异常。 - 中文域名需先转换为 punycode(如
例子.中国→xn--fsqu00a.xn--fiqs8s)再传入。
4. 返回结构
返回为统一的网关信封结构,业务数据放在 showapi_res_body 内。
4.1 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
showapi_res_code |
int | 网关层统一返回码,0 表示网关处理成功 |
showapi_res_error |
string | 网关错误信息,成功时为空串 |
showapi_res_body |
object | 业务返回主体 |
showapi_res_body.ret_code |
int | 业务返回码,0 表示查询成功且已备案 |
showapi_res_body.obj |
object | 备案详情对象;未备案或异常时可能为空或缺失 |
showapi_res_body.obj.num |
string | 备案号,如 滇ICP备14007554号-1 |
showapi_res_body.obj.update_time |
string | 备案更新时间,格式 YYYY-MM-DD |
showapi_res_body.obj.address |
string | 备案主体通信地址 |
showapi_res_body.obj.sys_name |
string | 网站名称 |
showapi_res_body.obj.com_name |
string | 备案主体名称(企业或个人) |
showapi_res_body.obj.type |
string | 备案类型,如 企业 / 个人 |
判断是否「已备案」:当 ret_code == 0 且 obj 存在并含 num 时,表示域名已备案,可直接读取 obj 内字段;当 ret_code != 0 或 obj 为空时,表示未查询到备案或参数异常。具体错误语义以控制台实时文档为准。
4.2 成功响应示例
{
"showapi_res_code": 0,
"showapi_res_error": "",
"showapi_res_body": {
"ret_code": 0,
"obj": {
"num": "示例ICP备00000000号-1",
"update_time": "2015-08-19",
"address": "示例省示例市示例区示例路1号",
"sys_name": "示例网站",
"com_name": "示例科技有限公司",
"type": "企业"
}
}
}

5. 错误码与排查
错误来自两层:网关层(HTTP 状态码 + X-Ca-Error-Code 头)与业务层(showapi_res_body.ret_code)。下面列出高频网关错误码。
| 错误码 | HTTP | 含义 | 排查与处理 |
|---|---|---|---|
A400MA |
400 | 缺少鉴权 | 请求头未携带 Authorization: APPCODE ...,补上即可 |
A401AC |
401 | AppCode 无效 | 检查 AppCode 是否正确、对应应用是否已授权 |
I400PA |
400 | 必填参数缺失 | domain 未传或为空,补齐参数 |
I400IP |
400 | 参数值非法 | domain 格式错误(含协议头/路径或非法字符) |
B403ME |
403 | 订购关系过期 | 云市场资源包已过期,需重新订购 |
B403MQ |
403 | 调用配额耗尽 | 资源包次数用尽,续费或升级资源包 |
B403MI |
403 | 订购关系非法 | 当前账号未正确订购该接口 |
T429xx |
429 | 触发流控 | 请求频率超过限制,降低频率并启用退避重试 |
D504TO |
504 | 后端超时 | 后端处理慢,启用重试;持续出现需联系服务商 |
X500ER / X503BZ |
500/503 | 服务内部错误/繁忙 | 服务端瞬时异常,按指数退避重试 |
失败响应通常为网关信封 + 非空 showapi_res_error:
{
"showapi_res_code": 0,
"showapi_res_error": "",
"showapi_res_body": {
"ret_code": 1,
"obj": null
}
}
注:
ret_code非 0 时obj可能为空,业务侧应显式判空,避免空指针。
6. 频控与合规
6.1 频控
- 单次调用消耗一次配额额度;具体 QPS 上限、每日配额、并发限制以控制台实时配置为准。
- 触发流控会返回
429系列错误码,客户端应做限流与退避,避免雪崩式重试放大压力。 - 对批量域名核验,建议用令牌桶在客户端统一节流,并错峰执行。
6.2 数据合规
备案信息属于公开政务数据,但工程上使用仍需注意边界:
- 最小必要:只查询业务真正需要的域名,不扩大采集范围。
- 用途受限:仅用于备案合规性核验,不用于用户画像、骚扰营销等越界用途。
- 不长期存储:核验结果建议按业务需要短期缓存(见 8.4),不落库长期留存 PII 类信息。
- 用户告知:在面向终端用户的功能中,对「核验第三方网站备案」的行为做适当告知。
- 传输加密:全程 HTTPS,AppCode 仅存于服务端配置,不进入前端代码或日志明文。
7. 多语言接入示例
以下示例统一在请求头携带 Authorization: APPCODE <appcode>,host 取自控制台「调用信息」。
7.1 curl
curl -X GET \
"https://<你的网关域名>/beian?domain=www.example.com" \
-H "Authorization: APPCODE <appcode>"
7.2 Python
import requests
HOST = "https://<你的网关域名>"
PATH = "/beian"
APPCODE = "<appcode>" # 仅服务端持有,不要硬编码进前端
resp = requests.get(
f"{HOST}{PATH}",
params={
"domain": "www.example.com"},
headers={
"Authorization": f"APPCODE {APPCODE}"},
timeout=10,
)
data = resp.json()
body = data.get("showapi_res_body", {
})
if body.get("ret_code") == 0 and body.get("obj"):
obj = body["obj"]
print("备案号:", obj.get("num"))
print("主体:", obj.get("com_name"))
else:
print("未查询到备案:", body.get("ret_code"))
7.3 Java
public static void main(String[] args) {
String host = "https://<你的网关域名>";
String path = "/beian";
String method = "GET";
String appcode = "<appcode>";
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "APPCODE " + appcode);
Map<String, String> querys = new HashMap<>();
querys.put("domain", "www.example.com");
try {
HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
System.out.println(EntityUtils.toString(response.getEntity()));
} catch (Exception e) {
e.printStackTrace();
}
}
7.4 PHP
<?php
$host = "https://<你的网关域名>";
$path = "/beian";
$appcode = "<appcode>";
$url = $host . $path . "?domain=" . urlencode("www.example.com");
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: APPCODE " . $appcode]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$body = curl_exec($ch);
curl_close($ch);
echo $body;
7.5 Node.js
const https = require("https");
const options = {
hostname: "<你的网关域名>",
path: "/beian?domain=" + encodeURIComponent("www.example.com"),
method: "GET",
headers: {
Authorization: "APPCODE <appcode>" },
};
https.get(options, (res) => {
let raw = "";
res.on("data", (c) => (raw += c));
res.on("end", () => console.log(raw));
});

8. 接入实践要点
8.1 参数前置校验
调用前在客户端校验 domain 非空、不含 http(s):// 与路径;中文域名转为 punycode。把非法请求拦在本地,省去一次无效的配额消耗。
8.2 重试与指数退避
对 429 / 5xx / 超时等可恢复错误启用重试,采用指数退避 + 抖动,设置上限(如最多 3 次,间隔 0.5s→1s→2s),并对 4xx 业务错误(如 A401AC、I400PA)直接失败不重试。
8.3 超时与异常兜底
设置连接/读取超时(建议 5–10s);任何解析失败都应走兜底分支,避免线程阻塞或空指针。网络异常时返回「暂不可查」而非崩溃。
8.4 结果缓存(TTL 依据)
备案信息变更频率很低,同一域名短期内结果几乎不变。可对成功结果做本地缓存(如 24 小时 TTL),既降低配额消耗又提升响应速度。缓存键用归一化后的域名,并约定过期后回源刷新。
8.5 密钥安全
AppCode 是服务端凭证,只能存放在后端配置/环境变量,禁止出现在前端代码、公开仓库或日志明文。定期轮换,发现泄露立即在控制台重置。
8.6 幂等与批量
查询接口天然幂等(相同 domain 多次调用结果一致)。批量核验用并发上限受控的线程池 + 令牌桶,错峰调用,避免触发流控。
9. 技术 FAQ
Q1:domain 传 https://www.example.com 为何报错?
A:参数只接受主机名,去掉协议头与路径后重试。
Q2:中文域名查不到怎么办?
A:先把中文域名转为 punycode(xn--...)再传入;直接传 UTF-8 中文可能被后端判为非法参数。
Q3:A401AC 一直出现?
A:AppCode 不正确或对应应用未授权该接口。到控制台核对 AppCode 与应用授权关系。
Q4:返回 obj 为空代表没备案吗?
A:大概率是未查询到备案或参数问题,以 ret_code 与 showapi_res_error 综合判断;业务侧务必对 obj 判空。
Q5:频繁调用被限流怎么处理?
A:出现 429 系列时降低频率、启用指数退避重试,并对稳定结果做 TTL 缓存减少重复调用。
Q6:返回结构与文档不一致?
A:以控制台「调用信息 / 接口文档」实时返回为准;网关信封字段(showapi_res_*)稳定,业务字段随后端版本演进。
10. 小结
域名 ICP 备案实时查询是一个典型的「单参数只读核验」接口:一个 domain 参数 + APPCODE 鉴权即可拿到备案号、主体、网站名、备案时间与类型。工程接入的关键不在「能调通」,而在:参数前置校验减少无效的配额消耗、对 429/5xx 做指数退避重试、对 obj 判空避免空指针、用 TTL 缓存降低配额消耗、把 AppCode 严格收敛在服务端。
本文的接入模式(信封结构解析、限流重试、缓存与合规边界)同样适用于其他核验类、查询类开放接口,可按需替换 domain 参数与返回字段即可迁移。


