Tiles use the same keys, plans and errors as the geocoding API. Tile requests count against their own monthly allowance (India tile set today; planet tiles in development), separate from geocoding.
Keys
| Kind | Prefix | Use for tiles |
|---|---|---|
| Publishable | gc_pk_ | Web maps. Answers only the origins listed on the key |
| Secret | gc_sk_ | Servers and scripts, for example a tile cache or a print renderer |
A browser sends the Origin (or Referer) header on tile requests, so a publishable key in a TileJSON or tile URL works with no extra code. A publishable key with no allowed origins answers nothing. Details: API keys.
Monthly allowances
| Plan | Price | Map tiles a month | Geocoding requests a month |
|---|---|---|---|
| Free | $0 | 200,000 | 50,000 |
| Starter | $19/month | 2,000,000 | 500,000 |
| Growth | $99/month | 10,000,000 | 2,500,000 |
| Scale | $299/month | 30,000,000 | 7,500,000 |
Each tile response counts once. TileJSON requests are not counted. Over the allowance, tile requests stop with 429 quota_exceeded and error.product tiles until the month (UTC) ends or you upgrade; there are no overage charges. Every tile answer carries X-Quota-Product: tiles, X-Quota-Limit and X-Quota-Remaining.
The allowance is per account: all projects and keys of the account share it. Free accounts together also share a daily ceiling; when it is used up, free tile requests stop for the rest of the UTC day with quota_exceeded and error.reason free_daily_ceiling.
Rate limits
| Requests | Limit |
|---|---|
| Tiles and TileJSON with a publishable key | 20 a second per visitor (the key and the visitor's IP address) |
| Tiles and TileJSON with a secret key or OAuth token | The plan's rate per key: Free 10, Starter 25, Growth 50, Scale 100 a second |
Every visitor of a web page shares its publishable key, so tile requests from a publishable key are limited per visitor, not per key. A map view asks for about 30 tiles at once; 20 a second holds two of the largest map sessions measured. Over the limit, the answer is 429 rate_limited with Retry-After: 1.
Errors
Errors are JSON with a stable code:
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded (20 tile requests per second per visitor)."
}
}
| Status | Code | When |
|---|---|---|
| 400 | tile_error | x or y is out of range for z |
| 401 | missing_api_key | No key or token |
| 401 | invalid_api_key | Malformed, unknown or revoked key |
| 403 | origin_not_allowed | Publishable key from an origin it does not list |
| 404 | not_found | Unknown tile set |
| 429 | rate_limited | Over the per-second rate |
| 429 | quota_exceeded | The monthly tile allowance is used up (error.product is tiles) |
An empty tile is not an error: it answers 204 No Content.