Plus Codes Grid Service

Plus codes are based on a multi-level grid. Being able to see the grid can make the codes easier to discover and use.

This service allows you to to add the plus codes grid to online maps and GIS applications.

The grid is served from grid.plus.codes, and supports multiple formats:

This page provides instructions and examples of using this service with JavaScript libraries from Google, OpenLayers and Leaflet, as well as Google Earth.

If you have any questions, please contact the public mailing group, and if you notice bugs in the tile generation, please raise an issue on our GitHub project.

This service uses rate limiting to control abuse. If you make a lot of requests in a short time, they may be rejected with status code 429 (too many requests). If you wait a few seconds, you should get valid responses.

Using the GeoJSON and image grid

The service that serves GeoJSON and images is a partial Tile Map Service implementation. That is, it uses zoom, x and y values to identify map tiles. The returned tile data is either a GeoJSON object containing the grid squares that overlap the tile, or a PNG image with the grid drawn on it.

Here is an example of adding an image grid to a map using the Leaflet library (more examples are in the tabbed section below):

L.tileLayer(
  'https://grid.plus.codes/grid/tms/{z}/{x}/{y}.png',
  {
    tms: true,
    attribution: 'grid by plus codes'
  }
).addTo(map);

This is based on the tile_server library from the Open Location Code project. See the documentation for the format of the tile requests, but note that grid.plus.codes only provides three colour options:

If you need to generate a large number of GeoJSON or image tiles, you can use the free tile server package to generate your tiles locally.

Using the KML grid

Google Earth does not make tile based requests, so it cannot use the GeoJSON or image grid. Instead, it fetches the grid in KML format.

Google Earth uses a small file to tell it how to fetch the grid. Download the file using this link and then open the file (see instructions). If you are using Google Earth Pro, you can load the file using the menu (File > Open).

Whenever you pan or zoom the map, Google Earth will make a request for the grid. The grid precision will automatically adjust to show more or less detail as you zoom in and out. The colour of the grid indicates the precision.

Clicking on a grid square will display an information box with the plus code.

Manual KML requests

If you want the KML grid for a specific area, you can make a request to:

https://grid.plus.codes/grid?BBOX=longitude_lo,latitude_lo,longitude_hi,latitude_hi

That will calculate the appropriate grid level, and generate the KML for the area.

Increasing the grid level is not possible, since that would increase the data generated by 400 times. But it is possible to reduce the grid level from the automatically determined value by specifying it in the request:


Google Maps
Leaflet
OpenLayers
OpenLayers (vector)

Image tiles with Google Maps API

This uses two overlays in different colours, using a black grid over road maps, and a white grid over satellite maps. The overlays are defined, and an event listener selects the appropriate overly when the map type is changed.

// Create the map.
var googleImageMap = new google.maps.Map(
  document.getElementById('g_image_wms'),
  {
    center: {lat: 47.5, lng: 8.54},
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    zoom: 4,
  }
);
// Define an image map overlay in black.
var roadmapOverlay = new google.maps.ImageMapType({
  getTileUrl: function(coord, zoom) {
    // Using WMS tile numbering.
    return ['https://grid.plus.codes/grid/wms/', zoom, '/', coord.x, '/', coord.y, '.png'].join('');
  },
  tileSize: new google.maps.Size(256, 256)
});
// Define an image map overlay in white.
var satelliteOverlay = new google.maps.ImageMapType({
  getTileUrl: function(coord, zoom) {
    // Using WMS tile numbering.
    return ['https://grid.plus.codes/grid/wms/', zoom, '/', coord.x, '/', coord.y, '.png?col=white'].join('');
  },
  tileSize: new google.maps.Size(256, 256)
});
// Add the overlay to the map.
googleImageMap.overlayMapTypes.push(roadmapOverlay);
// Change the overlay when the map type changes.
googleImageMap.addListener('maptypeid_changed', () => {
  console.log(googleImageMap.getMapTypeId());
  googleImageMap.overlayMapTypes.pop();
  if (googleImageMap.getMapTypeId() == google.maps.MapTypeId.SATELLITE ||
      googleImageMap.getMapTypeId() == google.maps.MapTypeId.HYBRID) {
    googleImageMap.overlayMapTypes.push(satelliteOverlay);
  } else {
    googleImageMap.overlayMapTypes.push(roadmapOverlay);
  }
});

GeoJSON vector tiles with OpenLayers

This fetches the grid using GeoJSON and draws it over the map as an overlay. It uses the option zoomadjust=2 to fetch a more detailed grid level than the default. Clicking on a cell will display the code.

OpenLayers also allows you to use {a-c}-grid.plus.codes as the hostname. This will distribute the tile requests across three hostnames, which may improve performance by avoiding the browser limit on simultaneous connections.

Click cell, get plus code
// Create the map with a vector layer.
var olVectorMap = new ol.Map({
  target: 'ol_vector_xyz',
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    new ol.layer.VectorTile({
      source: new ol.source.VectorTile({
        maxZoom: 25,
        attributions: [
          new ol.Attribution({
            html: 'grid by <a href="https://plus.codes">plus codes</a>'
          })
        ],
        format: new ol.format.GeoJSON(),
        // OpenLayers VectorTiles use WMS tile numbering by default.
        url: 'https://grid.plus.codes/grid/wms/{z}/{x}/{y}.json?zoomadjust=2'
      }),
    }),
  ],
  view: new ol.View({
    center: ol.proj.fromLonLat([8.54, 47.5]),
    zoom: 4
  })
});
// Define an action so that clicking on the map will display the global code.
var selectPointerMove = new ol.interaction.Select({
  condition: ol.events.condition.click
});
selectPointerMove.on('select', (e) => {
  document.getElementById("ol_vector_pluscode").innerHTML =
    e.target.getFeatures().getArray()[0].get("global_code");
});
olVectorMap.addInteraction(selectPointerMove);

Image tiles with OpenLayers

This fetches the grid as image tiles and uses the option col=red to set the lines to red and the labels to a non-opaque red.

OpenLayers also allows you to use {a-c}-grid.plus.codes as the hostname. This will distribute the tile requests across three hostnames, which may improve performance by avoiding the browser limit on simultaneous connections.

// Create the map with an image tile layer.
var olImageMap = new ol.Map({
  target: 'ol_image_tms',
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    new ol.layer.Tile({
      source: new ol.source.XYZ({
        attributions: [
          new ol.Attribution({
            html: 'grid by <a href="https://plus.codes">plus codes</a>'
          })
        ],
        // OpenLayers XYZ layers use WMS tile numbering by default.
        url: 'https://grid.plus.codes/grid/wms/{z}/{x}/{y}.png?col=red'
      }),
    }),
  ],
  view: new ol.View({
    center: ol.proj.fromLonLat([8.54, 47.5]),
    zoom: 4
  })
});

Image tiles with Leaflet

This uses default black image tiles as an overlay over the map.

Leaflet also allows you to use {s}-grid.plus.codes as the hostname. This will distribute the tile requests across three hostnames, which may improve performance by avoiding the browser limit on simultaneous connections.

// Create the map with an image tile layer.
var llImageMap = L.map('ll_image_tms', {maxZoom: 21}).setView([47.5, 8.54], 4);
L.tileLayer(
  'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
  {attribution: 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'}
).addTo(llImageMap);
L.tileLayer(
  'https://grid.plus.codes/grid/tms/{z}/{x}/{y}.png',
  {
    tms: true,
    attribution: 'grid by <a href="https://plus.codes">plus codes</a>'
  }
).addTo(llImageMap);