DEV Community

Cover image for Understanding Map Zoom Levels and XYZ Tile Coordinates
Alfiya Tarasenko
Alfiya Tarasenko

Posted on

Understanding Map Zoom Levels and XYZ Tile Coordinates

When working with interactive maps, two concepts sit at the foundation: zoom levels and tiles. Without them, platforms like Google Maps, Leaflet, or MapLibre GL would be impossible. Instead of loading one massive image, modern maps are composed of tiles — small 256×256 px squares that fit together in a grid. As you zoom in, the number of tiles grows exponentially, providing more detail at higher levels.

At zoom level 0, the entire world fits into a single tile. At zoom 1, the map splits into 2×2 tiles (4 total). At zoom 2, it’s 4×4 (16 total). In general, zoom level z produces a grid of 2^z × 2^z tiles. These tiles are addressed using the XYZ scheme ({z}/{x}/{y}), where z is the zoom, and x and y are the column and row numbers in the grid.

In this article, we’ll explore how zoom levels work, how the XYZ coordinate system addresses map tiles, and how to visualize tile grids directly on a map. If you want to experiment right away, check out the Geoapify Map Tiles overview or jump into this interactive CodePen demo that overlays a grid on map tiles.

Table of Contents

What are zoom levels?

Zoom levels define how detailed a map looks. At the core, they follow a simple rule:

  • At zoom level 0, the entire world fits into 1 tile (256×256 px).
  • Each step increases the number of tiles exponentially:

    • z=1 → 2 × 2 = 4 tiles
    • z=2 → 4 × 4 = 16 tiles
    • z=3 → 8 × 8 = 64 tiles
    • z=4 → 16 × 16 = 256 tiles

In general, zoom level z produces a grid of 2^z × 2^z tiles.

That means every time you zoom in, the map doubles the tiles horizontally and vertically.

How the world looks at zoom level 3 (2^3 × 2^3 = 8 x 8 = 64 tiles):

World map split into 64 tiles at zoom level 3

You can find a detailed table with scale and resolution values on the OpenStreetMap wiki — Zoom levels.

The XYZ tile system

Web map tiles are usually addressed with the XYZ scheme, where each tile is identified by three numbers:

  • z — the zoom level
  • x — the tile’s column index
  • y — the tile’s row index

At zoom level z, the world is split into 2^z columns (x = 0 … 2^z - 1) and 2^z rows (y = 0 … 2^z - 1).

For example, at zoom 2:

  • The grid is 4 × 4 = 16 tiles.
  • Valid x and y values range from 0 to 3.
  • The top-left tile is {z=2}/{x=0}/{y=0}.
  • The bottom-right tile is {z=2}/{x=3}/{y=3}.

Here’s a real tile URL using the Geoapify Map Tiles:

https://maps.geoapify.com/v1/tile/osm-carto/2/1/2.png?apiKey=YOUR_API_KEY
Enter fullscreen mode Exit fullscreen mode

This will return the tile at zoom 2, column 1, row 2, styled with the osm-carto theme.

👉 Try an interactive version on CodePen — Tile Grid Example.

Coordinates, Web Mercator, and map size

Almost all web maps (Leaflet, MapLibre, Google Maps, etc.) use the Web Mercator projection (EPSG:3857). It projects the Earth’s spherical surface onto a square, making it easy to split into tiles.

In this system:

  • The world spans from longitude –180° to +180° and latitude ≈ –85.0511° to +85.0511°.
  • At zoom level z, the world is divided into 2^z tiles horizontally and vertically.
  • Each tile is 256×256 px (by convention).

That means the map size in pixels at zoom z is:

map_size(z) = 256 × 2^z  (both width and height)
Enter fullscreen mode Exit fullscreen mode

Examples:

  • z=0 → 256 px × 256 px
  • z=1 → 512 px × 512 px
  • z=2 → 1024 px × 1024 px
  • z=3 → 2048 px × 2048 px

Projecting and unprojecting coordinates

There are two levels of coordinate conversion to keep in mind:

  • Global formulas (map-wide) These convert latitude/longitude into tile indices or global pixel coordinates across the entire Web Mercator world. They are useful if you want to calculate {z}/{x}/{y} directly.

From the Slippy map tilenames wiki:

Lat/Lon → Tile indices

   x = floor( (lon + 180) / 360 * 2^z )
   y = floor( (1 - ln( tan(lat*pi/180) + sec(lat*pi/180) ) / pi) / 2 * 2^z )
Enter fullscreen mode Exit fullscreen mode

Tile indices → Lat/Lon

   lon = x / 2^z * 360 - 180
   lat = atan(sinh(pi * (1 - 2 * y / 2^z))) * 180/pi
Enter fullscreen mode Exit fullscreen mode

These formulas treat the map as a single square image of size 256 × 2^z pixels.

  • Library methods (map view)
    When you use a map library, project and unproject don’t operate on the entire global map but on the visible map view (the map container in your app). They translate between:

    • Geographic coordinates (lat/lon)
    • Screen pixel coordinates (x, y) relative to the current viewport

Examples in popular map libraries:

Leaflet

// Convert geographic coordinate (lat, lon) → pixel position in map container
const pixelPoint = map.project([48.857, 2.351], 10);

// Convert pixel position (in current map view) → geographic coordinate
const geoPoint = map.unproject(pixelPoint, 10);
Enter fullscreen mode Exit fullscreen mode

MapLibre GL

// Convert geographic coordinate (lng, lat) → screen pixel in map container
const pixelPoint = map.project([2.351, 48.857]);

// Convert screen pixel → geographic coordinate (lng, lat)
const geoPoint = map.unproject([pixelPoint.x, pixelPoint.y]);
Enter fullscreen mode Exit fullscreen mode

👉 Try it live:

OpenLayers

import {fromLonLat, toLonLat} from 'ol/proj';

// Project geographic coordinate (lon, lat in WGS84) → Web Mercator (EPSG:3857)
const mercatorPoint = fromLonLat([2.351, 48.857]);

// Convert Web Mercator coordinate → geographic coordinate (lon, lat in WGS84)
const geoPoint = toLonLat(mercatorPoint);
Enter fullscreen mode Exit fullscreen mode

Key takeaway

  • The global formulas let you compute tile indices and positions for the entire map at any zoom.
  • The map library methods handle projection relative to your map container and view, which is what you’ll use in most applications.

Real-world use cases

Once you understand zoom levels and the XYZ tile grid, you can get creative. Developers use this knowledge to go beyond “just showing a map” and build unique experiences:

  • Custom or fantasy maps
    Want a game world, a fantasy realm, or a historical reconstruction on a map? Slice your artwork into {z}/{x}/{y} tiles and serve it like standard map tiles. Suddenly, your D&D campaign world behaves like Google Maps.

  • Themed basemaps
    Replace the default tiles at specific zoom levels with your own design. For example, highlight landmarks at z=14+ or make a minimal “night mode” tile set for city maps.

  • Overlay images on real maps
    Place old city plans, drone imagery, or floorplans as tiled overlays. Because they align to the XYZ grid, they zoom and pan smoothly with the basemap.

  • Hybrid maps
    Mix data with visuals — e.g., show a heatmap layer at low zoom levels and switch to detailed markers when zoomed in. All of this relies on understanding how tiles scale with zoom.

👉 With just a little control over tiles, maps turn from static backgrounds into canvases for storytelling, visualization, or even gameplay.

FAQ

What is the maximum zoom level in web maps?
Most map providers support up to zoom level 19–20 for street-level detail. Some satellite imagery layers go beyond that (21–22), but availability depends on the data source. You can check supported zoom ranges in the Geoapify Map Tiles documentation.

Are map tiles always 256×256 pixels?
Traditionally, raster tiles are 256×256 px, but many providers (including Geoapify) also support 512×512 px tiles — especially for vector tiles. Using 512 px reduces the number of requests and works well with high-resolution screens.

How do retina (high-DPI) screens affect map tiles?
On retina displays, a 256 px tile can look blurry because the screen packs more pixels per inch. The common solution is to request @2x tiles (512 px) but render them at 256 px in CSS, giving sharp details on high-DPI devices. Geoapify Map Tiles support retina requests out of the box.

What’s the difference between XYZ and TMS tiles?
Both use {z}/{x}/{y} indexing, but TMS (Tile Map Service) counts the Y-axis from the bottom, while XYZ counts from the top. Many libraries support both, but XYZ is the de facto standard today. Geoapify’s services follow the XYZ scheme for simplicity and broad compatibility.

Wrapping up

Zoom levels and the XYZ tile grid are the building blocks of every modern web map.

  • At zoom level z, the world is split into 2^z × 2^z tiles.
  • The XYZ scheme ({z}/{x}/{y}) makes tile URLs predictable and easy to work with.
  • Libraries like Leaflet, MapLibre, and OpenLayers handle projection for you — but knowing what happens under the hood lets you customize, debug, and even replace tiles with your own.

Whether you’re overlaying weather data, building offline maps, or even designing a fantasy world map, once you understand zoom levels, you can bend maps to your needs.

👉 Explore further:

Top comments (0)