Google Maps API Places Library 的 Quota limits
结论
按照题述规则,通过 Maps JavaScript API 加载 places library,并在浏览器中调用 google.maps.places.PlacesService,不受 Places API Web Service 每日 100,000 次、按 API key 统计的固定总量限制。
当时,这类请求按 end-user 分配额度。即使 JavaScript 应用的所有用户共用一个 API key,搜索请求也不会全部累计到同一个 Web Service quota 中。因此,Google API Console 中的 Places Web Service quota 没有增加,通常是因为两种调用方式采用了不同的计量机制。
不过,不能据此得出下面的计算公式:
应用总额度 = 100,000 × 用户数
100,000 是已验证项目调用 Places API Web Service 时的项目级额度,并非每位 JavaScript end-user 都能获得的额度。end-user 的识别和限流机制也不能简单理解为“每个 unique IP 对应一个 quota”。
还需要注意,题述 FAQ、Text Search 的 10-times multiplier、Radar Search、Place Bumps,以及“信用卡只用于验证、不收费”等内容都属于旧版 Places API 政策。Google Maps Platform 后来改为按 SKU、账单账户和项目配额管理。维护现有系统时,应以当前 Google Cloud Console 显示的 quota 和 billing SKU 为准,不要继续使用这些旧规则预测成本。
为什么两种请求的统计结果不同
下面的 URL 直接调用 Places API Web Service:
https://maps.googleapis.com/maps/api/place/nearbysearch/json
例如:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=XXXX
应用的 API key 会标识该请求,因此请求会计入对应项目的 Places API Web Service quota。
下面的代码则调用 Maps JavaScript API 的 Places library:
<script
src="https://maps.googleapis.com/maps/api/js?key=XXX&libraries=places">
</script>
const service = new google.maps.places.PlacesService(map);
service.textSearch(request, callback);
按照题述时期的政策,这些请求由 Places library 代表浏览器终端用户发起,使用 end-user quota,而不是同一 API key 下的 Web Service 项目级请求池。因此,它们不会以相同方式出现在 Places Web Service 的 quota count 中。
这不代表 Google 没有记录这些请求,也不代表该服务没有任何限制。它们只是没有计入所观察的那项 Web Service quota。
推荐的调用方式
纯浏览器应用可以继续通过 JavaScript library 调用搜索和详情接口:
const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: -33.8670522, lng: 151.1957362 },
zoom: 15
});
const service = new google.maps.places.PlacesService(map);
service.textSearch(
{
query: "food near harbour",
location: map.getCenter(),
radius: 500
},
(results, status) => {
if (status !== google.maps.places.PlacesServiceStatus.OK) {
console.error("Places search failed:", status);
return;
}
console.log(results);
}
);
需要地点详情时,使用搜索结果中的 place ID:
service.getDetails(
{
placeId: selectedPlaceId,
fields: ["name", "formatted_address", "geometry", "photos"]
},
(place, status) => {
if (status !== google.maps.places.PlacesServiceStatus.OK) {
console.error("Place details failed:", status);
return;
}
console.log(place);
}
);
如果详情结果包含照片,可以通过 library 返回的照片对象生成 URL:
const photoUrl = place.photos?.[0]?.getUrl({
maxWidth: 800,
maxHeight: 600
});
只请求实际需要的详情字段。即使旧版额度不是按项目汇总,减少不必要的 getDetails 调用也能降低限流风险。在当前计费模型中,字段选择还可能影响对应的 SKU 和费用。
如何确认生产环境的实际限制
问题引用的是历史政策,因此上线前需要根据当前项目配置重新核对:
- 在 Google Cloud Console 中确认项目启用的是 Maps JavaScript API、Places API,还是 Places API (New)。
- 分别检查相关 API 的 Metrics 和 Quotas 页面,不要只看旧 Places Web Service 的单一 quota counter。
- 在 Billing 报表中按 SKU 查看搜索、详情、照片和 Maps JavaScript API 的实际用量。
- 为浏览器 API key 配置 HTTP referrer restrictions,并且只允许调用需要的 API。
- 设置预算提醒和 quota 告警,不要把“控制台计数未增加”误判为“不会计费或永不限流”。
- 记录
OVER_QUERY_LIMIT、RESOURCE_EXHAUSTED等状态,并做好降级处理。
注意事项
- end-user 并不等同于一个公开承诺的 unique IP。Google 可能结合客户端、会话、项目和反滥用信号进行识别,具体算法通常不会作为可依赖的接口契约公开。
- NAT、代理、企业网络和共享出口都会使“按 IP 计算用户数”的结果失真。
- 不能把 JavaScript library 当作绕过 quota 或 billing 的方式,也不要用它代理服务器端批量查询。
- Web Service 请求和 JavaScript library 请求采用不同的调用路径,配额指标、SKU 和控制台统计可能也不同。
- 在旧规则下,JavaScript Places library 不存在
100,000 × 用户数这样可以直接计算的总额度。在当前规则下,也应根据项目实际使用的 SKU、quota 和账单配置判断,不能套用旧 FAQ 中的 multiplier。
备注:内容仅供参考。
