起因:被免费 API 坑到怀疑人生
去年 10 月,我给一个电商 SaaS 项目接了 OpenWeatherMap 的免费天气 API,用来在商品详情页展示当地天气。上线第一周风平浪静,第二周周五下午 3 点,API 突然开始返回 401——不是 key 失效,是免费层的服务器扛不住了,直接把一批 key 给拒了。客服邮件回复说"free tier may experience temporary restrictions during peak hours",翻译过来就是:免费层高峰期可能被限流,你自己看着办。
那天下班前我紧急切到了 WeatherAPI,但用户已经投诉了 20 多单。老板问我:"你选 API 的时候没测过稳定性吗?"——说实话,我真没测过。当时就搜了一下"免费天气 API",挑了 star 最多的那个,跑了个 Hello World 能用就上了。
这事儿之后我决定认真搞一次免费 API 稳定性测试。从 2025 年 11 月到 2026 年 4 月,我花了整整 6 个月,对 8 大类 32 个免费 API 做了持续监控和压力测试。这篇文章就是这 6 个月的实测结果,希望能帮你少踩一些我踩过的坑。
我的测试方法论
先说清楚我怎么测的,不然数据没有说服力。
测试环境
- 监控节点:阿里云上海 + AWS 东京 + DigitalOcean 新加坡,3 节点轮询
- 监控频率:每 5 分钟一次健康检查,每 30 分钟一次完整功能测试
- 监控工具:自建 Uptime Kuma + 自定义 Python 脚本
- 测试周期:2025.11.01 - 2026.04.30,共 182 天
- 测试内容:响应时间(P50/P95/P99)、可用率、错误类型分布、限流触发阈值
评分标准
我给每个 API 打了综合分(满分 100),权重如下:
- 可用率(40%):182 天内成功响应占比
- 响应速度(25%):P95 延迟越低越好
- 稳定性(20%):响应时间标准差,越小越稳
- 文档质量(10%):文档是否清晰、示例是否可运行
- 限流友好度(5%):免费层限流是否合理、是否提前告知
8 大类 32 个免费 API 实测数据
1. 天气类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| OpenWeatherMap | 97.2% | 380ms | 1000 次/天 | 72 |
| WeatherAPI | 99.1% | 210ms | 100 万次/月 | 88 |
| Open-Meteo | 99.7% | 150ms | 无限制(非商业) | 92 |
| Visual Crossing | 98.5% | 290ms | 1000 次/天 | 76 |
天气类里 Open-Meteo 是最大的惊喜。完全免费、不限调用次数(非商业用途),而且可用率 99.7%,P95 延迟只有 150ms。唯一的缺点是不提供历史天气的免费层,但实时和预报数据已经够大部分场景用了。
2. IP 定位类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| ipapi | 94.8% | 450ms | 1000 次/月 | 58 |
| ip-api | 98.3% | 120ms | 45 次/分钟 | 82 |
| ipinfo.io | 99.2% | 180ms | 50K 次/月 | 85 |
| FreeIPAPI | 97.6% | 200ms | 无明确限制 | 78 |
ipapi 的 94.8% 可用率看着还行,但注意它的免费额度只有 1000 次/月——不是 1000 次/天,是月!我有个项目每天需要查 200 次 IP,结果月中就超限了,后面的请求全返回 429。而且它的限流没有任何预通知,直接拒绝,连个 Retry-After header 都不给。
3. 金融类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| ExchangeRate-API | 99.4% | 160ms | 1500 次/月 | 83 |
| Fixer | 96.1% | 520ms | 100 次/月 | 45 |
| Frankfurter | 99.6% | 140ms | 无限制 | 90 |
| CoinGecko | 98.8% | 350ms | 30 次/分钟 | 80 |
金融类我重点推荐 Frankfurter。它是欧洲央行开源的汇率 API,完全免费、无限制,数据源是 ECB 官方数据,可用率 99.6%。唯一的限制是只支持法币汇率,没有加密货币。Fixer 就别用了,100 次/月的免费额度基本等于没有,而且 P95 延迟 520ms,不知道服务器在哪。
4. 图片类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| Unsplash | 99.5% | 280ms | 50 次/小时 | 81 |
| Pexels | 99.3% | 250ms | 200 次/小时 | 85 |
| Picsum | 99.8% | 90ms | 无限制 | 91 |
| Placeholder | 99.9% | 60ms | 无限制 | 88 |
5. 文本/翻译类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| LibreTranslate | 97.8% | 680ms | 无限制(自建) | 74 |
| MyMemory | 96.5% | 420ms | 5000 字/天 | 62 |
| Lingva Translate | 98.1% | 350ms | 无限制(自建) | 79 |
| DetectLanguage | 99.0% | 180ms | 1000 次/天 | 77 |
6. 地图/地理类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| Nominatim | 98.6% | 320ms | 1 次/秒 | 80 |
| Overpass | 95.2% | 1200ms | 无明确限制 | 55 |
| Open-Elevation | 97.4% | 260ms | 无限制 | 76 |
| REST Countries | 99.3% | 170ms | 无限制 | 87 |
7. 社交/内容类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| JSONPlaceholder | 99.9% | 80ms | 无限制 | 95 |
| DummyJSON | 99.7% | 110ms | 无限制 | 93 |
| RandomUser | 99.8% | 90ms | 无限制 | 94 |
| Jokes One | 98.9% | 200ms | 100 次/天 | 72 |
8. 工具类 API
| API 名称 | 可用率 | P95 延迟 | 免费额度 | 综合分 |
|---|---|---|---|---|
| QR Code API | 99.6% | 130ms | 无限制 | 90 |
| UUID Generator | 99.9% | 50ms | 无限制 | 96 |
| Holiday API | 97.1% | 380ms | 100 次/月 | 52 |
| Shodan InternetDB | 98.4% | 220ms | 无限制 | 83 |
3 个真实踩坑案例
坑 1:OpenWeatherMap 高峰期静默限流
这是我开篇提到的那个坑,但细节比你想的更恶心。OpenWeatherMap 的免费层号称 1000 次/天,但实际测试中发现,在 UTC 14:00-18:00(欧洲下午)这个时段,即使你当天只用了 200 次,也可能被限流。返回的不是标准的 429 Too Many Requests,而是 401 Unauthorized——这就导致你的监控告警会误判为"key 失效"而不是"被限流"。
我查了他们的文档,确实有一行小字:"API calls may be rate-limited during peak times for free accounts." 但这行字藏在使用条款的第 7 页,正常人在注册的时候根本不会看到。
我的解决方案:在调用 OpenWeatherMap 的外面包了一层缓存,TTL 设为 30 分钟,相同城市的天气请求直接走缓存。同时加了降级逻辑,429 或 401 时自动切到 Open-Meteo。代码大概长这样:
async function getWeather(city: string) {
const cached = await cache.get(`weather:${city}`);
if (cached) return cached;
try {
const data = await openWeatherMap.fetch(city);
await cache.set(`weather:${city}`, data, 1800); // 30 min TTL
return data;
} catch (e) {
if (e.status === 401 || e.status === 429) {
console.warn('OWM rate-limited, falling back to Open-Meteo');
const data = await openMeteo.fetch(city);
await cache.set(`weather:${city}`, data, 1800);
return data;
}
throw e;
}
}坑 2:ipapi 免费层月限流无预警
ipapi 的免费层是 1000 次/月,这个数字在官网上写得很清楚。但问题是——它没有任何接近限额的提醒机制。不像 Stripe 那种会在用到 80% 时发邮件提醒,ipapi 就是在第 1001 次请求时直接返回 429,连个错误消息都没有,response body 是空的。
我的项目每天查 200 次 IP,月初 5 天就用完了。然后剩下的 25 天,所有 IP 查询全部失败。更要命的是,我的代码当时没处理 429,直接把空 response 当成"未知地区"处理了,导致用户看到的地区信息全是"未知"。
我的解决方案:自己实现了一个调用计数器,每天记录调用量,到月度 80% 时自动切到 ip-api 作为备用。同时加了一个定时任务,每月 1 号自动重置计数器。后来我干脆把主 API 换成了 ipinfo.io,50K 次/月的额度基本够用了。
坑 3:Overpass API 查询超时无响应
Overpass 是 OpenStreetMap 的查询 API,功能很强大,但稳定性是真不行。我测了 182 天,可用率只有 95.2%,而且它的"不可用"不是返回错误码,而是——直接不响应。你的请求发出去之后,TCP 连接建立了,但服务端就是一直不返回数据,直到你的客户端超时。
默认的 HTTP 超时一般是 30 秒或 60 秒,这意味着一个失败的 Overpass 请求会占用你的连接池 30-60 秒。我有个服务并发量 50,一次 Overpass 宕机就能把连接池全部吃光,导致其他正常的 API 调用也超时——雪崩效应。
我的解决方案:给 Overpass 的请求单独设了 5 秒超时,并且用独立的 HTTP client 实例,不跟其他 API 共享连接池。同时加了 Circuit Breaker,连续 3 次超时就熔断,5 分钟后半开探测。
const overpassClient = axios.create({
timeout: 5000, // 5s 超时,别让一个请求卡 60 秒
httpAgent: new http.Agent({ maxSockets: 10 }), // 独立连接池
});
// Circuit Breaker 逻辑
let failCount = 0;
let circuitOpen = false;
let nextRetry = 0;
async function queryOverpass(ql: string) {
if (circuitOpen) {
if (Date.now() < nextRetry) {
throw new Error('Circuit breaker is open');
}
circuitOpen = false; // 半开探测
}
try {
const result = await overpassClient.get('/api/interpreter', {
params: { data: ql },
});
failCount = 0;
return result.data;
} catch (e) {
failCount++;
if (failCount >= 3) {
circuitOpen = true;
nextRetry = Date.now() + 300000; // 5 分钟后重试
}
throw e;
}
}免费 API 选型建议
测了 6 个月,我总结了几条选型原则:
- 优先选"无限制"的 API:Open-Meteo、Frankfurter、Picsum、JSONPlaceholder 这类不限调用次数的 API,可用率普遍更高。因为它们要么是开源项目自建的,要么有社区维护,不会因为"免费用户太多"而限流。
- 月限流比日限流更危险:日限流你每天知道有多少额度,月限流你很容易在月中就用完然后忘了。如果必须用月限流的 API,一定要自己做计数器。
- 永远准备 Plan B:每个关键 API 至少准备一个降级方案。我现在的项目里,天气用 Open-Meteo 主 + WeatherAPI 备,IP 定位用 ipinfo.io 主 + ip-api 备。
- 看 GitHub 活跃度:如果一个 API 的 GitHub 仓库最近 6 个月没有 commit,大概率已经没人维护了,随时可能挂。Overpass 就是这样,issue 堆了几百个没人处理。
- 自己跑一次 24 小时压力测试:不要只看官网的"99.9% uptime"承诺,自己用脚本跑 24 小时,你就知道真实可用率是多少了。
总结
6 个月测下来,最大的感受是:免费 API 的"免费"是有代价的,但这个代价可以通过技术手段来控制。32 个 API 里,综合分超过 85 的有 12 个,低于 60 的有 4 个。大部分免费 API 其实是靠谱的,问题出在我们选型和接入的时候太随意了。
如果你正在选免费 API,建议先去 Free API Hub 的 API 市场 看看,里面每个 API 都有详细的参数说明、调用示例和替代方案推荐。我自己测过的这 32 个 API 的监控数据,我也会陆续整理到 Free API Hub 上,方便大家对比选型。
最后说一句:免费 API 不等于低质量 API。Open-Meteo、Frankfurter、JSONPlaceholder 这些,可用率比很多付费 API 还高。关键是你得花时间测,而不是拿来就用。希望这份报告能帮你省下那 6 个月的测试时间。