Find an API

Search public APIs with auth details & Postman guides

← All APIs

iNaturalist API

api.inaturalist.org · Science

Science API Key Free & Open Biodiversity Nature Biology

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 authentication 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

Get Postman ↗
  1. Most read endpoints need no API key
  2. Try GET https://api.inaturalist.org/v1/observations?taxon_name=bald+eagle&quality_grade=research&per_page=5
  3. Filter by place: add &place_id=1 for US
  4. Get nearby species: GET /observations/species_counts?lat=37.77&lng=-122.42&radius=10

What can you build with iNaturalist API?

iNaturalist API is a Science API. Developers commonly use science APIs for:

  • accessing research datasets and scientific literature
  • powering academic and R&D applications
  • running scientific calculations and simulations
  • visualising experimental and observational data
  • integrating with research and reference databases

API Key authentication. You'll receive a key after signing up. Send it with every request — in a header or query parameter. Keep it out of client-side code and never commit it to version control. iNaturalist API is free to use, making it a low-risk choice to experiment with.

New to APIs? Read our beginner's guide

Open documentation ↗