最简单可靠的方式是调用 http://httpbin.org/ip,它返回固定格式 JSON {"origin": "x.x.x.x"},无重定向、无 Cookie、无 UA 检查;实操需加超时、异常处理及字段安全提取。

用 http://httpbin.org/ip 获取公网 IP 最简单可靠
公网 IP 查询本质是让服务端告诉你“它看到的客户端地址是什么”,所以最稳妥的方式是调用一个已知行为明确、不带登录/限流/埋点的公开接口。http://httpbin.org/ip 就是这类接口的典型代表——它只返回 JSON,字段固定为 {"origin": "x.x.x.x"},无重定向、无 Cookie、无 UA 检查。
常见错误是误用国内所谓“免费 IP 接口”,比如返回 HTML 页面、带广告跳转、或突然加 Referer 校验;还有人试图解析 ifconfig 或 ipconfig 输出来获取本机 IP,但这只能拿到局域网地址(如 192.168.x.x),不是公网出口 IP。
实操建议:
- 直接发 GET 请求,响应体解析 JSON 即可提取
origin字段值 - 注意:该接口不支持 HTTPS 重定向(
https://httpbin.org/ip可用,但 HTTP 版本在某些内网环境更稳定) - 别依赖响应头里的
X-Real-IP或X-Forwarded-For,httpbin不设这些头
Python 中用 requests 调用要处理超时和异常
看似一行代码就能搞定:requests.get("http://httpbin.org/ip").json()["origin"],但生产环境必须加防护。网络抖动、DNS 失败、连接被防火墙拦截都会导致程序卡死或抛出未捕获异常。
实操建议:
- 显式设置
timeout=(3, 5):3 秒连通,5 秒读取,避免 hang 住 - 捕获
requests.exceptions.RequestException,而非只抓ConnectionError - 对空响应、非 200 状态码、JSON 解析失败做 fallback,比如返回
None或打日志后重试一次
示例片段:
import requests
try:
resp = requests.get("http://httpbin.org/ip", timeout=(3, 5))
resp.raise_for_status()
ip = resp.json().get("origin", "").split(",")[0].strip() # 防多 IP(逗号分隔)
except Exception as e:
ip = None浏览器前端用 fetch 会遇到跨域限制
直接在网页 JS 里写 fetch("http://httpbin.org/ip") 会失败,因为浏览器默认禁止跨域请求,而 httpbin.org 没有配 Access-Control-Allow-Origin: *(它只对 POST /anything 等少数路径开 CORS)。
这不是你代码写错了,是浏览器策略使然。想在前端安全获取公网 IP,只有两个可行路径:
- 走自己后端中转:前端请求自己的 API(如
/api/public-ip),由后端调httpbin并透传结果 - 换支持 CORS 的接口:例如
https://api.ipify.org?format=json(返回纯文本)或https://icanhazip.com(返回纯 IP 字符串),它们允许前端直连
注意:api.ipify.org 的 JSON 格式接口实际返回的是 {"ip":"x.x.x.x"},但它的响应头含 CORS,可直接 fetch;而 icanhazip.com 返回纯文本,需用 .text() 而非 .json() 解析。
curl 命令调试时别漏掉 -s 和 -f
用 curl http://httpbin.org/ip 看结果很直观,但脚本里直接调可能出问题:默认会输出进度条、重定向信息,还可能静默返回 4xx/5xx 状态码而不报错。
实操建议:
- 加
-s(silent)屏蔽进度和错误信息,只留响应体 - 加
-f(fail)让非 2xx 响应直接返回非 0 状态码,方便 shell 判断成败 - 加
-m 5设置总超时(比--max-time更常用) - 用
jq -r ".origin" 2>/dev/null提取字段,失败时不会报错干扰判断
完整命令示例:
curl -sfm 5 http://httpbin.org/ip | jq -r ".origin" 2>/dev/null
真正麻烦的不是调不通,而是调通了却拿到错误的 IP —— 比如代理没关、公司出口做了 SNAT、或者用了 CDN 回源地址。查 IP 的目的如果是风控或日志归因,得确认这个 IP 是真实用户出口,而不是中间节点的地址。

















