← Back to the map
Developers and researchers
Everything on the map comes from an open API. No key is needed to read it. The full description is an OpenAPI file: openapi.json (import it into Postman, Insomnia or a client generator).
API or releases?
- Use the API to explore and to show current figures: live detections, effort-corrected measures, arrival weeks, coverage.
- Use the open data releases for analysis, papers and anything you redistribute. They are versioned, cite with a DOI, carry GBIF species keys, and are licensed CC BY 4.0.
- API responses include BirdWeather detections, shown with BirdWeather's agreement for display only. Do not bulk download them or republish them; they are not in the releases for that reason.
Python
import requests, pandas as pd
BASE = "https://wlnw.org/api/v1"
# Arrival weeks for one species, every 5 degree cell
arr = requests.get(f"{BASE}/arrivals", params={"species": "Hirundo rustica"}).json()["arrivals"]
df = pd.DataFrame(arr)
print(df.groupby("region")["arrivalWeek"].min())
# A year of weekly frames: range centre per continent
mv = requests.get(f"{BASE}/species/Hirundo%20rustica/movement").json()
centres = pd.DataFrame([{"week": f["week"], **c} for f in mv["frames"] for c in f["centroids"]])
print(centres[centres.region == "Europe"][["week", "lat"]].tail())R
library(httr2)
library(dplyr)
base <- "https://wlnw.org/api/v1"
# Arrival weeks for one species, every 5 degree cell (CSV straight into a data frame)
arr <- read.csv(paste0(base, "/arrivals?species=Hirundo%20rustica&format=csv"), comment.char = "#")
arr |> group_by(region) |> summarise(first = min(arrivalWeek))
# Which cells are watched well enough to use
cov <- request(paste0(base, "/coverage")) |> req_perform() |> resp_body_json()
table(sapply(cov$cells, \(x) x$status))Main endpoints
| /api/v1/arrivals?species=…&format=csv | Arrival, peak and departure week per species and 5 degree cell |
| /api/v1/species/{name}/movement | A year of weekly frames: share per cell, range centre per continent |
| /api/v1/species/{name} | Last 30 days: daily index, range centre, weather, text summary |
| /api/v1/species/{name}/sources | Recordings against human sightings in the same cells and weeks |
| /api/v1/insights?group=… | What is changing now: moving, surging and fading, arrivals |
| /api/v1/coverage | Which cells are watched, and by which source |
| /api/v1/events?bbox=…&species=… | Live detections (a sample of the newest) as GeoJSON |
Every response carries the methods version that produced it; definitions and limits are on the methods page. Please keep to about one request per second and cache what you can.
Pushing detections
Devices send WDX events (schema) to POST /api/v1/events with a bearer key from POST /api/v1/register: a single event, an array or NDJSON, up to 5,000 per request. The free wdx-agent does this for BirdNET-Pi, BirdNET-Go, bat detectors and camera traps.
Bulk files
# Latest analysis-ready, citable release (GBIF-derived, CC BY 4.0)
curl -LO https://github.com/wlnw-org/wildnetwork/releases/download/data-2026-10-07/wildnetwork-open-2026-10-07.zipFound something wrong? Open an issue or email arunrajiah@gmail.com.