Quick start
Read a season for one species in one place: two requests with any HTTP client, or a few lines with the package.
1. Find the current release
Every file sits inside a dated release that never changes. current.json names the current one. Read it once, then read everything else from that release.
curl https://api.openphenology.com/current.json{
"id": "current.json",
"kind": "current",
"format": "current/1.0",
"provenance": { "release": "2026-11-13", … },
"data": { "release": "2026-11-13", "published_at": "2026-11-13T09:14:00Z" }
}2. Read a result
A county result lives at results/<state>/<county>/<species_key>.json. States use lowercase ISO 3166-2 codes (us-oh) and counties their Census GEOID (39049 is Franklin County). Species keys come from the catalogue.
curl https://api.openphenology.com/releases/2026-11-13/results/us-oh/39153/32NKH.json3. Or use the package
@openphenology/api reads the files for you, in Node.js and in browsers, with types for every format. It pins one release per client, retries network errors and can check each file against the manifest.
npm install @openphenology/apiimport { createClient } from "@openphenology/api";
const release = await createClient().release();
const result = await release.countyResult("us-oh", "39153", "32NKH");
if (result) console.log(result.data.season); // [early, middle, late] weeks, or []The package's source on GitHub (opens in a new tab)
4. Or explore in Postman
A Postman collection has a request for every published file, each with a description, an example response and tests. No keys are needed. In Postman, choose Import and paste this link:
https://raw.githubusercontent.com/openphenology/openphenology-api/main/postman/openphenology.postman_collection.jsonSend Start here › Current release first. It fills in the current release, so the rest of the collection runs without typing anything. The collection's guide (opens in a new tab) explains its variables and tests.
When a file is missing
A result with too few records, or one withheld to protect a sensitive species, is never written. It looks exactly like a result that does not exist: the request returns 404, and the package returns null. Missing does not mean absent.
Good to know
- OpenPhenology is in beta: the site and the
@openphenology/apipackage may change before 1.0.0. File formats change only by version. - Results pool complete years, from
pooled_frominmethods.jsonthrough the last year before the release. Records from the release's own year are stored but not yet counted.pooled_frommoves forward one year each new year. Records before it are kept but not counted. - Only
GET, from any site: CORS is open and there are no keys. - The data files have no fixed rate limit. They are cached at the edge, and a client that abuses them may be blocked. To fetch a whole release, download its
archive.tar.gzonce instead. The sites allow 100 page requests per IP address in any 10 seconds; over that, pages get HTTP429for 10 seconds. - Release files are cached for a year;
current.jsonfor about 5 minutes. - Responses are compressed when your client accepts it. No file is over 500 KB compressed; larger lists are split into numbered shards.
- No analytics or request logs are kept beyond Cloudflare's aggregate traffic figures.