什么时候会用到 Whois 查询
接手一批存量域名时,第一件事往往不是调整解析,而是先把每个域名的准备商、到期时间、域名状态摸清楚。域名的创建时间、准备主体、DNS 服务器这些基础信息,通常被记录在 Whois 数据库中。除此之外,在没有接入准备商接口的情况下,想要判断一个未准备域名是否可准备、或是在批量盘点域名资产时快速筛出 30 天内到期的域名,Whois 查询都是一个直接可用的数据入口。
接口定位:能查什么、不能查什么
Whois 域名查询接口只做一件事:输入一个域名,返回该域名当前的准备信息快照。它支持 .com、.cn、.net、.org、.io、.me、.top、.xyz 等主流 TLD,覆盖范围以 ICANN 认证后缀为准。
接口在进入查询之前会做一次归一化处理:传https://www.baidu.com/abc、http://baidu.com:8080甚至www.baidu.com都会被剥离成baidu.com再查询。这意味着调用方不需要在业务层做 URL 解析,直接把原始输入传过去即可。
值得留意的能力还有三个。第一,未准备域名会返回is_available=true,可用于预准备前的可用性判断;第二,30 天内到期的域名会返回expiring_soon=true,便于前端展示到期高亮;第三,上游对国内域名会返回中文准备主体,例如「极数本源(福州)科技有限公司」这样的名称,省去自行做中文标注的步骤。
接口不提供历史 Whois 变更记录,也不解析域名下的 DNS 记录内容,这些不属于该接口的职责范围。
鉴权与请求地址
接口是标准的 GET 请求:
- 请求地址:
https://v1.apizero.cn/api/whois - 请求方法:GET
- 鉴权方式:请求头携带
X-API-Key,值为调用方自己的 API Key - QPS 限制:5 次/秒,超出后需要等待或做本地限速
domain是唯一必填参数,类型为字符串;with_raw是可选布尔参数,控制是否返回原始 Whois 文本(约 3KB),默认关闭,建议只在调试时开启。
使用 curl 发起第一次查询
在终端中先将 API Key 写入环境变量,再按下面的方式发起请求:
export APIZERO_API_KEY="your_api_key_here" curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/whois?domain=baidu.com"返回结果是一个 JSON 数组,数组中第一个元素携带example字段,里面就是完整的响应体。实际调用时,响应体结构为:
{ "code": 0, "msg": "成功", "data": { "domain": "baidu.com", "is_available": false, "registrar": "MarkMonitor Information Technology (Shanghai) Co., Ltd.", "creation_age_text": "26 年 7 个月", "expiring_soon": false }, "request_id": "abc123def456" }code = 0表示业务成功,request_id可用于排查单次请求的链路问题。
使用 Python 跑通一次查询
在没有 curl 的环境中,用 Python 的requests库也可以快速验证接口:
import requests resp = requests.get( "https://v1.apizero.cn/api/whois", params={"domain": "baidu.com"}, headers={"X-API-Key": "your_api_key_here"}, timeout=10, ) payload = resp.json() if payload["code"] == 0: data = payload["data"] print(data["registrar"]) print(data["expiration_time"]) print(data["expiring_soon"]) else: print(payload.get("error", payload.get("msg")))这里刻意使用了payload.get("error", payload.get("msg"))的写法,原因在后文错误处理部分说明。
返回字段逐一拆解
响应体中的data对象是核心,字段大致分两类。第一类是准备信息:
| 字段 | 类型 | 说明 |
|---|---|---|
domain | string | 归一化后的域名 |
suffix | string | 顶级后缀,如com |
registrar | string | 准备商名称 |
whois_server | string | 该域名的 Whois 服务器 |
creation_time | string | 创建时间(北京时区) |
expiration_time | string | 到期时间 |
registrant | string | 准备主体 |
registrant_email | string | 准备邮箱 |
name_servers | string[] | 当前 DNS 服务器列表 |
registrar_abuse_email | string | 准备商滥用举报邮箱 |
registrar_abuse_phone | string | 准备商滥用举报电话 |
registrar_url | string | 准备商官网地址 |
第二类是状态与辅助字段:
| 字段 | 类型 | 说明 |
|---|---|---|
domain_status | string[] | 域名状态,如clientTransferProhibited |
dnssec | string | DNSSEC 签名状态,常见值为unsigned |
is_available | boolean | 是否未准备 |
is_expired | boolean | 是否已过期 |
expiring_soon | boolean | 是否 30 天内到期 |
creation_age_text | string | 域龄人类可读字符串,如「26 年 7 个月」 |
creation_days | number | 创建至今的天数 |
valid_days | number | 距离到期的剩余天数 |
query_time | string | 本次查询的服务端时间 |
用baidu.com为例,响应中registrar为 MarkMonitor Information Technology (Shanghai) Co., Ltd.,creation_time为 1999-10-11,expiration_time为 2028-10-11,expiring_soon为 false。若查询一个不存在的域名,is_available会变为 true,此时registrar等准备信息字段通常为空。
注意:
registrant和registrant_email在部分 TLD 或隐私保护开启时可能返回空字符串,这不代表接口异常。
高频异常与排查顺序
接入过程中遇到问题,建议按下面的顺序排查。
第一,检查 HTTP 状态码与请求格式。如果返回 4xx,优先确认domain参数是否传了、URL 是否拼接正确、X-API-Key头是否携带。请求地址必须以https://开头,domain的值不需要做 URL 编码之外的额外处理。
第二,检查响应体中的业务错误。该接口的业务错误字段是error而不是message。如果只读取msg,可能拿不到上游真正返回的错误原因。这就是前面 Python 示例中同时尝试error和msg的原因。
第三,确认域名状态本身的含义。is_available=true是查询成功的一种正常结果,不是错误;域名可能处于clientHold或clientTransferProhibited状态,这些会如实反映在domain_status数组中,不影响接口本身的可用性。
如果 QPS 超过 5 次/秒,服务端可能返回限流错误,此时应降低请求频率或增加本地退避,而不是盲目重试。
工程化落地建议
在真实业务中接入该接口,有几点建议。
第一,利用服务端缓存。接口对同一域名全天只调用一次上游并缓存 24 小时,客户端不需要为了获取“最新”数据而反复请求同一个域名。域名准备信息是低频变化数据,日级刷新完全够用。
第二,在本地再做一层应用缓存。结合 QPS 5 次/秒的限制,批量盘点几千个域名时,建议先查本地缓存,再对未命中的域名做限速请求,避免触发限流。
第三,把expiring_soon和valid_days用起来。这两个字段可以直接驱动到期告警逻辑,不必在业务侧自行计算“今天距离到期还有几天”。
第四,生产环境不要开启with_raw。原始 Whois 文本约 3KB,对多数业务场景无用,还会增加响应体积与解析维护复杂度。
参考文档
- 接口文档:https://apizero.cn/aidocs/whois
- 原始文档:https://apizero.cn/aidocs/whois/raw.md