适用场景
ICP (Internet Content Provider) 备案是中国大陆境内网站运营的法定要求。开发者在以下场景中需要实时或批量查询域名备案状态:
- 合规审查:在用户准备、广告投放、友链交换前,验证目标域名是否已备案。
- 内容聚合平台:过滤未备案的第三方链接,降低法律风险。
- 运维监控:定期扫描自有域名的备案状态,防止因主体信息变更或注销导致的备案失效。
- 前端展示:在页面底部动态展示备案号,需要根据备案状态决定显示内容。
接口能力边界
本接口(slu:icp)提供基于域名的 ICP 备案信息查询,其核心能力与约束如下:
| 能力 | 说明 |
|---|---|
| 域名清洗 | 自动剥离https://、http://、路径、端口、www.,例如https://www.baidu.com/abc与baidu.com等价 |
| 备案判断 | is_filed布尔字段区分是否已备案;未备案/境外/已注销均返回false,不会报错 |
| 缓存策略 | 已备案域名缓存 24 小时(备案信息变更极少);未备案缓存 1 小时(避免新备案被长期误判) |
| QPS 限制 | 5 次/秒,超过限制返回 429 状态码 |
接口不承诺以下能力:
- 实时性不受缓存策略外的保证;
- 仅支持中国大陆工信部备案数据,境外域名(如
.com但未在大陆备案)返回is_filed=false; - 不返回 ICP 备案号的详细历史变更记录。
请求参数与鉴权
Query 参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
domain | string | 是 | 要查询的域名,支持完整 URL 输入(自动清洗)。推荐直接传入二级域名(如example.com) | baidu.com |
domain参数会自动执行以下清洗:
- 去除
https://或http://协议前缀; - 去除路径部分(如
/abc); - 去除端口(如
:8080); - 去除
www.前缀。
因此,传入https://www.baidu.com/abc、baidu.com:443、m.baidu.com均等价于查询baidu.com。
Header 参数(鉴权)
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
Authorization | string | 否 | API Key 鉴权头,格式Bearer sk_live_xxx。匿名调用时可省略(每日 30 次额度) | Bearer sk_live_xxxxxxxxxxxxxx |
注意:文档中提及的
X-API-Key是早期版本,当前推荐使用Authorization: Bearer方式。如果同时传入两种,以Authorization为准。
curl 接入示例
以下 curl 命令演示携带鉴权的完整请求(请将$APIZERO_API_KEY替换为实际密钥):
curl -sS \ -X GET \ -H "Authorization: Bearer $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/icp?domain=baidu.com"若不需鉴权(每日 30 次匿名额度),可省略-H头:
curl -sS -X GET "https://v1.apizero.cn/api/icp?domain=baidu.com"代码封装(Python)
对于需要工程集成的场景,可使用以下 Python 模板:
import requests def query_icp(domain: str, api_key: str = None) -> dict: url = "https://v1.apizero.cn/api/icp" params = {"domain": domain} headers = {} if api_key: headers["Authorization"] = f"Bearer {api_key}" resp = requests.get(url, params=params, headers=headers, timeout=10) resp.raise_for_status() return resp.json()返回值解读
成功响应(HTTP 200)的 JSON 结构如下:
{ "code": 0, "data": { "is_filed": true, "domain": "baidu.com", "icp_code": "京ICP证030173号-1", "site_name": "百度一下,你就知道", "company_name": "北京百度网讯科技有限公司", "company_type": "企业", "audit_time": "2019-05-16 16:06:21" }, "msg": "成功", "request_id": "abc123def456" }字段详解
| 字段 | 类型 | 含义 | 备注 |
|---|---|---|---|
code | int | 业务状态码 | 0表示成功;非0表示错误 |
msg | string | 状态描述 | 可据此判断错误类型 |
request_id | string | 请求唯一标识 | 用于排查问题时提供给平台 |
data | object | 备案数据 | 核心负载对象 |
├──is_filed | boolean | 是否已备案 | true表示已备案;false表示未备案或境外 |
├──domain | string | 清洗后的域名 | 始终返回标准二级域名(如baidu.com) |
├──icp_code | string | 备案许可证号 | 仅当is_filed=true时有效,否则为空字符串 |
├──site_name | string | 网站名称 | 同上 |
├──company_name | string | 主办单位名称 | 个人备案时为主体名称,企业备案为公司名 |
├──company_type | string | 单位性质 | 取值:企业、个人、事业单位、政府机关、社会团体等 |
└──audit_time | string | 审核通过时间 | 格式YYYY-MM-DD HH:mm:ss |
未备案时的响应
{ "code": 0, "data": { "is_filed": false, "domain": "example-notexist.com", "icp_code": "", "site_name": "", "company_name": "", "company_type": "", "audit_time": "" }, "msg": "成功", "request_id": "xyz789abc" }注意:未备案不会返回错误码,而是通过is_filed=false与空字段表达。前端可以直接根据is_filed做条件渲染,无需额外判断code。
常见错误处理
| HTTP 状态码 | business code | msg 含义 | 原因与解决方案 |
|---|---|---|---|
| 400 | -1 | 参数错误 | domain为空或格式完全非法(如纯数字串)。检查输入参数 |
| 401 | -2 | 鉴权失败 | Authorization头格式错误或密钥无效。检查是否以Bearer开头且密钥正确 |
| 429 | -3 | 请求过于频繁 | 超过 5 QPS 限制。可增加退避逻辑(指数退避)或降低并发 |
| 500 | -5 | 内部错误 | 服务端瞬时故障。间隔数秒后重试 |
最佳实践:建议将code和 HTTP 状态码结合判断。例如:
- 若 HTTP 200 但
code != 0,仍视为业务错误;
工程化注意事项
1. 缓存策略的自适应
由于接口自身已对已备案域名缓存 24 小时,未备案缓存 1 小时,客户端无需再增加过长缓存层。但若需要秒级更新(例如刚下单的域名备案通过),可绕过缓存:在domain后拼接随机参数(需注意是否被清洗掉)。实际上接口不提供强制刷新,建议采用“先查、缓存、隔段时间再查”的轮询策略,间隔至少 30 分钟避免被限流。
2. 并发控制
QPS 上限为 5,若需批量查询(例如一次检查 100 个域名),应:
- 使用
asyncio或线程池,但限制每秒请求数 ≤ 4; - 使用重试库(如
tenacity)处理429错误。
3. 域名清洗的双重保险
尽管服务端会清洗domain,但客户端最好也做一次基础校验:去除空格、转小写、剔除非法字符。避免因 URL 中的#片段导致请求被截断。
4. 错误日志与告警
- 记录每次请求的
request_id和返回的msg到日志; - 对于连续 3 次
500错误,触发告警; - 定期检查
is_filed从true变false的域名,可能是备案注销或信息变更。
5. 国际化与境外域名处理
该接口仅适合大陆备案查询。对于.com或.net等境外域名,只要未在大陆备案,is_filed均为false。若需区分“域名是否真实存在”与“备案情况”,建议结合 DNS 查询或 WHOIS 接口。
参考文档
- 接口原始文档 — 包含最新参数变更和响应示例
- 在线调试页面 — 可直接在浏览器中测试参数效果