
本文介绍一种利用 HTML <img> 标签的加载机制,在浏览器端无 CORS 阻碍地探测外部域名是否可达的方法,适用于检查被 ISP 屏蔽或网络策略拦截的第三方链接可用性。
本文介绍一种利用 html `` 标签的加载机制,在浏览器端无 cors 阻碍地探测外部域名是否可达的方法,适用于检查被 isp 屏蔽或网络策略拦截的第三方链接可用性。
在前端开发中,常需向用户展示外部参考链接(如文档、工具站点、API 控制台等)。但受限于网络环境——例如某些地区 ISP 层面的屏蔽、企业防火墙策略或本地 DNS 污染——用户实际无法访问这些资源。此时,若仅依赖服务端健康检查或静态链接列表,将导致体验割裂:链接看似正常,点击后却超时或报错。
值得注意的是,浏览器的同源策略(CORS)虽禁止 fetch 或 XMLHttpRequest 跨域读取响应体,但并不阻止对跨域资源发起“连接探测”。关键在于:我们不需要获取内容,只需判断目标域名能否建立 TCP 连接并返回 HTTP 状态(尤其是 2xx/3xx),且该过程不触发 CORS 预检。
一个轻量、可靠、零服务端依赖的方案是:利用 <img> 元素的 onload / onerror 事件进行“伪 ping”。原理如下:
- 浏览器允许跨域加载图片(无需 CORS 头),只要服务器返回有效的图像 MIME 类型(或至少是可解析的响应);
- 若目标域名可解析、TCP 可达、HTTP 服务响应状态码为 2xx/3xx(且返回内容能被浏览器初步识别为图像),则触发 onload;
- 若 DNS 失败、连接超时、服务器拒绝、返回 4xx/5xx(尤其非图像类型如 HTML 错误页),或响应头明确禁止加载(如 X-Content-Type-Options: nosniff + 非图像 content-type),则触发 onerror。
✅ 推荐实践:使用 favicon.ico 作为探测路径(因其普遍存在、体积小、缓存友好):
function checkDomainAvailability(url, timeout = 5000) {
return new Promise((resolve) => {
const img = new Image();
const timer = setTimeout(() => {
img.onload = img.onerror = null;
resolve(false); // 超时视为不可用
}, timeout);
img.onload = () => {
clearTimeout(timer);
resolve(true);
};
img.onerror = () => {
clearTimeout(timer);
resolve(false);
};
// 添加时间戳防止强缓存,确保每次请求真实发往服务器
img.src = `${url.replace(/\/+$/, '')}/favicon.ico?_t=${Date.now()}`;
});
}
// 使用示例
checkDomainAvailability('https://example.com')
.then(available => {
console.log(`https://example.com ${available ? '✓ 可访问' : '✗ 不可用'}`);
});⚠️ 注意事项:
- 并非 100% 精确:若目标站禁用 favicon、返回 404 但配置了 HTML fallback 页面(导致 onerror 不触发)、或强制重定向至非图像资源,可能产生误判;
- 不适用于纯 API 域名(如 api.example.com):若该子域未部署 favicon 且无任何图片资源,探测必然失败,建议优先选择主站域名(example.com);
- 避免高频探测:单页面内应限制并发请求数(如 ≤3),并添加防抖/节流,防止触发目标服务器防护机制;
- 隐私与合规提示:该行为属于客户端主动探测,不涉及用户数据上传,但仍建议在隐私政策中说明用途(如“为提升链接有效性而进行基础连通性检查”)。
总结:<img> 探测法是一种巧妙规避 CORS 限制、低侵入、高兼容(支持所有现代浏览器及 IE11+)的客户端可用性验证手段。它虽不能替代服务端健康检查,但在增强前端用户体验、动态灰度链接、辅助故障诊断等场景中极具实用价值。

















