Skip to contents


Large datasets of millions of lat-lon points can be difficult to plot using ggplot2 or base graphics. In these cases, using the GBIF maps API with rgbif::map_fetch() can be a good option.

However, if you would like to make a complex graphic with different colors, shapes, and legends, using ggplot2::geom_sf() is a better option. Below I will give examples using both methods.

Using map_fetch()

requires >= rgbif 3.7.8

map_fetch() will return the default GBIF pixel map of all occurrences map as a magick::magick-image. To save this png you can use magick::write_image().

It is also possible to make static maps that look like default occurrence search maps. See the maps api page for available styles.


For “poly” styles it is also possible to plot set the hexPerTile parameter, so that the binned occurrence data is essentially shown at a higher resolution. A tile is an individual png image that is fetch from the API in order to make a map. The default settings of map_fetch() will fetch two images, so the image below has 400 hexagons across the width of map.


There is also the option to plot with polar or artic projections. For example, penguin records.

map_fetch(srs='EPSG:3031',taxonKey=7190978,style='glacier.point', base_style="gbif-dark")

It is also possible to get views other than just the global map, by zooming in and selecting only certain map tiles with z, x, y.

Seleting tiles can be tricky to get right, but with a little trial-and-error, you can usually get close to the map you want to have. One trick for getting the right tiles, is to look at this demo page, where the z,x,y values are printed on the center of each tile.

For example, you can see what the tile values for a zoomed in map of Australia would be here.


Be aware that selecting many tiles will create a large image, and might crash your R session. You can control the resolution of your final image with format, with format="@4x.png" being the highest possible value.

Below are some areas to give you an idea of how z,x,y it are working.

# Europe
# Africa
# Hawaii
# South Africa 
# Ukraine 
# Iceland
# Capri Is. 

I suggest using this interactive page for getting the tile numbers.

Keep in mind that the the GBIF maps API wasn’t designed to make high quality static maps, like it is being used for in map_fetch(). It was designed for interactive use on the GBIF website, so the API design reflects this reality.

When making maps, the named paramters, taxonKey, datasetKey, country, publishingOrg, publishingCountry, year, and basisOfRecord are going to be the easiest to use. However, It is also possible to make “any” map (any search filter) using source=adhoc.

# all occurrences with iucn status critically endangered 

map_fetch() can also tell when you have used a parameter that is no a default parameter and automatically switch to source="adhoc" for you. I have found that point style don’t work well with source="adhoc", so map_fetch() will give a warning if you try to use a point style with source="adhoc".

Here are some examples of maps with different parameters and styles.

adhoc is needed here because recordedBy isn’t one of the named paramters. map_fetch() automatically detects this and switches source to “adhoc”.

map_fetch(recordedBy="John Waller")

Occurrences in the OBIS network. Note that squareSize only works with bin="square".


Map of Texas using the gadm filter.


map_fetch() is generally forgiving and will give you back at least some map with warnings or blank images when the parameters don’t work.

map_fetch(x=1:5) # no tiles exist past 2, so blank images are returned

All specimen bird records from the year 2000.

map_fetch(taxonKey=212, basisOfRecord="PRESERVED_SPECIMEN", year=2000,style="classic-noborder.poly")  

Map of all country centroid locations.


In general, adhoc maps are harder to make look nice, but usually picking a non-point style and tuning hexPerTile and perhaps also squareSize, will make a nice map.


A tip for getting the un-named adhoc parameters is to pull them from the occurrence search URL after looking them up via the web interface.


Using geom_sf()

The GBIF maps API is powerful and useful, but can be frustrating if your plot needs a some custom styling or legends. If you don’t have a large dataset, then using ggplot::geom_sf() can be a good option.


# occ_download(pred_default(),pred(taxonKey,"1427067"),format="SIMPLE_CSV")

worldmap <- ne_countries(scale = 'medium', type = 'map_units',returnclass = 'sf')

# a download I made of all Calopteryx splendens occurrences 
d <- occ_download_get('0001707-230810091245214') %>%

d_sf <- sf::st_as_sf(d, coords = c("decimalLongitude", "decimalLatitude"),
        crs = "+proj=longlat +datum=WGS84")

# color occurrences by basisOfRecord
ggplot() + 
  geom_sf(data = worldmap) + 
  geom_sf(data = d_sf,aes(color=basisOfRecord))

See ggplot2 docs for more.

Using leaflet

Since the GBIF maps API was designed to work as an interactive map, it can be used with leaflet.


leaflet() %>% 
  addTiles() %>%

See leaflet docs for more.