Download grid file for Google Earth
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.
Google Earth uses a small file to tell it how to fetch the grid.
Download grid file for Google Earth
Open the file with Google Earth (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.
If you want the KML grid for a specific area, you can make a request to:
https://grid.plus.codes/kml?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:
level=0
will force the grid precision to be two digit OLC codes
(20° x 20°);
level=1
will force the grid precision to be four digit OLC codes
(1° x 1°);
level=2
will force the grid precision to be six digit OLC codes
(.05° x .05°);
level=3
will force the grid precision to be eight digit OLC codes
(.0025° x .0025°);
level=4
will force the grid precision to be ten digit OLC codes
(.000125° x .000125°).
This is the default house level precision;
level=5
will force the grid precision to be eleven digit OLC codes
(.000025° x .00003125°);
level=6
will force the grid precision to be twelve digit OLC codes
(.000005° x 0.0000078125°);
GeoJSON and grid tiles are served from 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:
col=white
col=red
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.
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);
}
});
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.
// 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);
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
})
});
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);