iNaturalist API
api.inaturalist.org · Science
Community-powered nature observations — 200M+ wildlife sightings, species IDs, photos, and location data contributed by citizen scientists worldwide. Free API key available.
Authentication
API Key
Many endpoints work without auth. Create an iNaturalist account at inaturalist.org and generate an API token for write/private access.
Sample Requests
GET
Search observations
Search research-grade monarch butterfly observations.
https://api.inaturalist.org/v1/observations?per_page=5&taxon_name=Monarch Butterfly&quality_grade=research
Hover any highlighted part to learn what it does
curl -X GET "https://api.inaturalist.org/v1/observations?per_page=5&taxon_name=Monarch%20Butterfly&quality_grade=research"
import requests
params = {
"per_page": "5",
"taxon_name": "Monarch Butterfly",
"quality_grade": "research"
}
response = requests.get(
"https://api.inaturalist.org/v1/observations",
params=params,
)
print(response.json())const url = new URL('https://api.inaturalist.org/v1/observations');
url.searchParams.set('per_page', '5');
url.searchParams.set('taxon_name', 'Monarch Butterfly');
url.searchParams.set('quality_grade', 'research');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.inaturalist.org/v1/observations")
q := baseURL.Query()
q.Set("per_page", "5")
q.Set("taxon_name", "Monarch Butterfly")
q.Set("quality_grade", "research")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.inaturalist.org/v1/observations")
uri.query = URI.encode_www_form({
"per_page" => "5",
"taxon_name" => "Monarch Butterfly",
"quality_grade" => "research"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.inaturalist.org/v1/observations?" . http_build_query([
"per_page" => "5",
"taxon_name" => "Monarch Butterfly",
"quality_grade" => "research"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));
GET
Get species info
Search for species information by name.
https://api.inaturalist.org/v1/taxa?q=red fox&per_page=3
Hover any highlighted part to learn what it does
curl -X GET "https://api.inaturalist.org/v1/taxa?q=red%20fox&per_page=3"
import requests
params = {
"q": "red fox",
"per_page": "3"
}
response = requests.get(
"https://api.inaturalist.org/v1/taxa",
params=params,
)
print(response.json())const url = new URL('https://api.inaturalist.org/v1/taxa');
url.searchParams.set('q', 'red fox');
url.searchParams.set('per_page', '3');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.inaturalist.org/v1/taxa")
q := baseURL.Query()
q.Set("q", "red fox")
q.Set("per_page", "3")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.inaturalist.org/v1/taxa")
uri.query = URI.encode_www_form({
"q" => "red fox",
"per_page" => "3"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.inaturalist.org/v1/taxa?" . http_build_query([
"q" => "red fox",
"per_page" => "3"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Postman Setup Guide
- Most read endpoints need no API key
- Try GET https://api.inaturalist.org/v1/observations?taxon_name=bald+eagle&quality_grade=research&per_page=5
- Filter by place: add &place_id=1 for US
- Get nearby species: GET /observations/species_counts?lat=37.77&lng=-122.42&radius=10