KosherFish offers a free, public, read-only API so developers can use kosher-fish data in their own apps and sites. It answers the same question the website does, in JSON: is this fish kosher?
The basics
- Base URL:
https://api.kosherfish.co - Cost: free. No API key is needed for any read request.
- Method: read-only. Every data endpoint is a GET request.
- Format: JSON, shaped
{ "success": true, "data": ... }. - Coverage: hundreds of fish species, cross-referenced with the Orthodox Union and Chabad.
Interactive docs
Two built-in references make it easy to explore:
- Swagger UI at
https://api.kosherfish.co/docslets you try each endpoint in the browser. - OpenAPI spec at
https://api.kosherfish.co/openapi.jsonis the machine-readable definition for code generators.
Caching and ETags
Responses are cached and ETag-aware. If you send an If-None-Match header with the ETag from a prior response, you get a fast 304 Not Modified when nothing has changed. Watch the Cache-Control header to see how long a response stays fresh.
Endpoints
Here is the full list of endpoints, all under the base URL https://api.kosherfish.co. Every data response is shaped { "success": true, "data": ... }.
Fish
GET /api/v1/fish· list or filter fish. Query parameters:q(search common name, scientific name, or alias),kosher(trueorfalse),category,limit(default 100, max 500), andoffset. The response includes ametablock withtotal,limit, andoffset.GET /api/v1/fish/all· every fish in one cached list.GET /api/v1/fish/{id}· one fish by its numeric id. Returns404if the id does not exist.GET /api/v1/search?q=· ranked search with a fuzzy fallback, so close spellings still match. Returns amatch_scoreand amodeofexactorfuzzy.GET /api/v1/suggest?q=· lightweight autocomplete, capped at 8 results, for typeahead UIs.
Meta
GET /health· liveness check. Returns{ "status": "ok", "timestamp": ... }.GET /api/v1/categories· the list of categories with a count for each.GET /api/v1/stats· dataset counts:total,kosher,notKosher,withImages, andwithAttribution.
Images and docs
GET /images/{key}· a fish illustration, served WebP-negotiated with a long cache.GET /docs· the interactive Swagger UI.GET /openapi.json· the OpenAPI 3.0 spec.
What a fish record contains
A fish object includes id, name, scientific_name, hebrew_name, aliases, is_kosher, kosher_notes, has_fins, has_scales, description, category, image_key, and a built image_url.
Example calls
Here are copy-paste examples to get you started. They use curl, but any HTTP client works the same way. No API key is needed.
Is salmon kosher?
curl "https://api.kosherfish.co/api/v1/search?q=salmon"
This runs a ranked search and returns the matching fish with their kosher status.
List non-kosher fish
curl "https://api.kosherfish.co/api/v1/fish?kosher=false&limit=10"
This filters to species that fail the fins-and-scales test, ten at a time.
Get one fish by id
curl "https://api.kosherfish.co/api/v1/fish/42"
This returns the full record for the fish with id 42, or a 404 if there is none.
Autocomplete suggestions
curl "https://api.kosherfish.co/api/v1/suggest?q=tun"
This returns up to eight quick suggestions, handy for a search-as-you-type box.
Dataset stats
curl "https://api.kosherfish.co/api/v1/stats"
This returns the counts of total, kosher, and non-kosher fish, plus how many have images.
A polite cached request
curl -H 'If-None-Match: "the-etag-from-last-time"' "https://api.kosherfish.co/api/v1/fish/all"
If nothing changed, you get a fast 304 Not Modified and save the bandwidth.
Rate limits and fair use
The API is free, and a few hundred requests a minute is fine for normal use. There is one limit to keep the service healthy for everyone.
Each IP address can make up to 240 requests per minute. Go past that and you get a 429 Too Many Requests response with a Retry-After header telling you how many seconds to wait.
X-RateLimit-Limit· the cap, 240.X-RateLimit-Remaining· how many requests you have left this minute.Retry-After· on a 429, the seconds to wait before trying again.
Cache responses on your end and use ETags with If-None-Match to get cheap 304 responses. If you need the full dataset, call /api/v1/fish/all once and cache it rather than looping through individual fish. That keeps you well under the limit and keeps the API fast for everyone.
