# How to find the bounding box for a web map tile in Python

Today I learnt …

When you’re working with tiled web maps you’ll often use a z/y/x coordinate system instead of geographic coordinate system like longitude and latitude. Map tiles use a grid system so, for example, you might talk about tile 14/8046/5106 — the 8,046th row and the 5,106rd column at the 14th zoom level. That particular tile corresponds to part of the Southside of Edinburgh.

Sometimes you’ll want to convert a tile’s z/y/x into a bounding box in longitude and latitude. In my particular case I needed to debug which features should appear in a tile, and I wanted the tile’s bounding box so I could pass it to PostGIS’s `ST_MakeEnvelope` function.

Using the Python script below (save it to a file named `bbox.py`) you can find the answer:

``````\$ python3 bbox.py 14/8046/5106
ST_MakeEnvelope(-3.2080078125, 55.936894769039434, -3.18603515625, 55.94919982336745, 4326)
``````
``````import math
import sys
from dataclasses import dataclass

@dataclass
class BoundingBox:
north: float
south: float
east: float
west: float

def tile_bbox(zoom: int, x: int, y: int) -> BoundingBox:
return BoundingBox(
north=tile_lat(y, zoom),
south=tile_lat(y + 1, zoom),
west=tile_lon(x, zoom),
east=tile_lon(x + 1, zoom),
)

def tile_lon(x: int, z: int) -> float:
return x / math.pow(2.0, z) * 360.0 - 180

def tile_lat(y: int, z: int) -> float:
return math.degrees(
math.atan(math.sinh(math.pi - (2.0 * math.pi * y) / math.pow(2.0, z)))
)

if __name__ == "__main__":
bbox = tile_bbox(*map(int, sys.argv.split("/")))
print(
f"ST_MakeEnvelope({bbox.west}, {bbox.south}, {bbox.east}, {bbox.north}, 4326)"
)
``````

The script requires Python 3.7 or higher. Consider the code available under the MIT licence.