osmdata (R): use another Overpass server
The R package osmdata turns Overpass answers into sf objects and data frames. It picks one of the public Overpass servers when it loads. You can point it at another server and keep your API key out of your scripts.
library(osmdata), call set_overpass_url() with the full URL, including /interpreter:
library(osmdata)
set_overpass_url("https://api.overpass.ch/v1/YOUR_API_KEY/interpreter")
A complete example
library(osmdata)
key <- Sys.getenv("OVERPASS_CH_KEY")
set_overpass_url(paste0("https://api.overpass.ch/v1/", key, "/interpreter"))
q <- opq(bbox = c(6.60, 46.50, 6.66, 46.54), timeout = 60) |>
add_osm_feature(key = "amenity", value = "fountain")
fountains <- osmdata_sf(q) # sf objects: osm_points, osm_lines, osm_polygons, …
nrow(fountains$osm_points)
df <- osmdata_data_frame(q) # or a plain data frame of tags
We tested this with osmdata 0.4.1 in R: about 1,160 fountain points in Lausanne arrive in under half a second.
Details that matter
- The URL must contain
interpreter.set_overpass_url()refuses anything else with “overpass_url not valid - must end with /interpreter”. - It checks the server. osmdata derives the status URL by replacing
interpreterwithstatusand reads it. If the server can't be reached, the call fails and the previous server stays selected. A typo in the key shows up right there. - Set it in every session. osmdata chooses a server when it loads (the start-up message says which), so put
set_overpass_url()right afterlibrary(osmdata).get_overpass_url()shows the current one. - Place names in
opq("Lausanne")are looked up with Nominatim, as before. For reproducible scripts, give the bounding box as numbers, in the order west, south, east, north. - Timeouts:
opq(timeout = …)sets the time limit of the query, 25 seconds by default. On overpass.ch, values above the plan maximum are lowered to it. - Retries: osmdata retries failed requests itself, up to 10 times. Before each query it also reads the status page, which does not count as an Overpass request.
Keep the key out of your scripts
Put the key into the .Renviron file in your home directory, for example with usethis::edit_r_environ(), and restart R:
OVERPASS_CH_KEY=YOUR_API_KEY
Sys.getenv("OVERPASS_CH_KEY") then returns it, and the script can be shared or committed without the key. On CI servers, set the same variable as a secret.
Heights for your results
osmdata builds its queries for you, so the simplest way to add heights is a second call with the coordinates. The elevation API takes up to 10'000 locations per request on paid plans and 1,000 on the free plan:
library(httr2)
library(sf)
elevation <- function(xy) { # xy: a matrix with columns X (lon) and Y (lat)
locations <- paste(sprintf("%.6f,%.6f", xy[, "Y"], xy[, "X"]), collapse = "|")
resp <- request(paste0("https://api.overpass.ch/v1/", key, "/elevation")) |>
req_body_json(list(locations = locations)) |>
req_perform() |>
resp_body_json()
vapply(resp$results, \(r) if (is.null(r$elevation)) NA_real_ else r$elevation, numeric(1))
}
xy <- st_coordinates(fountains$osm_points)
chunks <- split(seq_len(nrow(xy)), ceiling(seq_len(nrow(xy)) / 1000))
fountains$osm_points$elevation <- unlist(lapply(chunks, \(i) elevation(xy[i, , drop = FALSE])))