critwire

Free, open facts about 76 animals, ready for science class, research projects and nature apps.

About

critwire gives every animal one clean record: its common and scientific names, where it sits on the tree of life, the ids other science databases use for it, and the countries where people have shared open records of it. Some records also have a photo with its credit.

Scientists keep information about the same animal in many different databases, and those databases do not always agree. critwire checks the big open ones against each other. When they agree, the answer goes in the record. When they disagree, critwire leaves the value empty until a person has looked at it, so you never get a guess dressed up as a fact.

Everything is a plain file on this website. There is no account, no key and no limit: download a file, open it in a spreadsheet, or read it straight from code. critwire was built for the game Critter Connect, which uses these same files.

The quickest start, in DuckDB:

SELECT * FROM 'https://critwire.com/v1/species.parquet';

The /v1/ in each address is the version. Inside v1 we only add things: fields keep their names and meanings, and an id always means the same animal.

Files

The species files all hold the same 76 records, the countries files the same country rows, and the range-listings files the same listing rows. Pick the format that suits your tool.

/v1/species.json
All records as one JSON array. Best for web pages and apps.
/v1/species.csv
One row per animal, for spreadsheets. It leaves out sources (see Fields).
/v1/species.parquet
All records with the same nested shape as the JSON, for DuckDB, pandas, polars or R. Tools can read just the parts they need straight from the web.
/v1/species/{id}.json and /v1/species/{slug}.json
One record per file, by its number or by its name in the address. Both files hold the same record.
/v1/attribution.json
Every source, license and photo credit, plus the datasets behind the country lists and the range listings. The Credits below are made from it.
/v1/countries.json, /v1/countries.csv and /v1/countries.parquet
One row per country code, with the country's name, continent and region, so you can put a name to the codes in range.countriesWithOpenRecords. See Countries.
/v1/range-listings.json, /v1/range-listings.csv and /v1/range-listings.parquet
What named sources list about where each animal is native or introduced: one row per claim. See Range listings.

Files are served with open CORS and byte ranges, so a web page on any site can fetch them.

critwire Learn is a free course in SQL, database design, GIS in SQL and more, taught on these files. The data its labs read, an open GBIF occurrence sample, map shapes and a PostGIS loader, is at /learn/data/, outside /v1/ because it changes as the course does.

Download with curl

curl -fsSO https://critwire.com/v1/species.json
curl -fsSO https://critwire.com/v1/species.csv
curl -fsSO https://critwire.com/v1/species.parquet
curl -fsSO https://critwire.com/v1/attribution.json
curl -fsSO https://critwire.com/v1/countries.json
curl -fsSO https://critwire.com/v1/countries.csv
curl -fsSO https://critwire.com/v1/countries.parquet
curl -fsSO https://critwire.com/v1/range-listings.json
curl -fsSO https://critwire.com/v1/range-listings.csv
curl -fsSO https://critwire.com/v1/range-listings.parquet
curl -fsS https://critwire.com/v1/species/51.json
curl -fsS https://critwire.com/v1/species/jaguar.json

Ask questions with DuckDB

Which animals have open records in Brazil?

SELECT id, commonName, scientificName
FROM 'https://critwire.com/v1/species.parquet'
WHERE list_contains("range".countriesWithOpenRecords, 'BR')
ORDER BY commonName;

How many animals are in each class, from the CSV?

SELECT taxonomy_class, count(*) AS animals
FROM 'https://critwire.com/v1/species.csv'
GROUP BY taxonomy_class
ORDER BY animals DESC;

How many animals have open records on each continent, joining the countries file:

WITH recorded AS (
  SELECT id, unnest("range".countriesWithOpenRecords) AS code
  FROM 'https://critwire.com/v1/species.parquet'
)
SELECT c.continent, count(DISTINCT r.id) AS animals
FROM recorded AS r
JOIN 'https://critwire.com/v1/countries.parquet' AS c USING (code)
GROUP BY c.continent
ORDER BY animals DESC;

One animal from the JSON, with the ids other databases use:

SELECT commonName, ids.gbif, ids.col, ids.wikidata
FROM read_json('https://critwire.com/v1/species.json')
WHERE slug = 'jaguar';

Fields

Each record has these fields, in this order. A field that is null (an empty cell in the CSV) means critwire does not know the value yet, or the sources disagree and a person has not settled it. critwire never fills a gap with a guess.

id
critwire's number for the animal. It never changes and is never given to another animal.
slug
A short, readable name for web addresses, like jaguar.
scientificName
The two-part Latin name scientists use, like Panthera onca.
commonName
The everyday English name.
taxonomy
Where the animal sits on the tree of life. It comes from the Catalogue of Life when critwire is sure both name the same animal.
taxonomy.class
The class, like Mammalia (mammals) or Reptilia (reptiles).
taxonomy.order
The order, like Carnivora.
taxonomy.family
The family, like Felidae (cats).
taxonomy.genus
The genus, the first part of the scientific name.
ids
The animal's id in other databases, so you can join critwire with them. null means the match is not settled.
ids.iucn
The IUCN Red List species id. critwire keeps only this number, no Red List data (see Licenses).
ids.gbif
The GBIF Backbone Taxonomy key, for occurrence records on GBIF.
ids.col
The Catalogue of Life id.
ids.wikidata
The Wikidata item, like Q35694.
ids.inaturalist
The iNaturalist taxon id.
ids.ncbi
The NCBI Taxonomy id, used for DNA data.
range
Where the animal has been recorded.
range.countriesWithOpenRecords

Two-letter country codes (ISO 3166-1, like BR for Brazil), sorted. This is not the animal's native range. It lists the countries where GBIF holds open records of it: sightings and museum specimens shared under the CC0 or CC BY licenses. Records in zoos, fossils and records with location problems are left out.

A country with a single record far outside the animal's main region is usually a pet, a zoo animal or a mistake, so it is left out until a person checks it. The list is never empty: when there is no country, it is null, and range.status tells you why.

For what named sources list about where the animal is native or introduced, see Range listings.

range.status

Always present. One of:

  • ok: at least one country is listed (72 animals).
  • no-open-records: critwire knows which GBIF animal this is, but no country is left after the open-license and quality checks, so the countries are null (1).
  • identity-unsettled: critwire could not confirm which GBIF animal this is, so it counted nothing and the countries are null (3).
photo
A photo from Wikimedia Commons, or null. Show its credit and license wherever you show the photo.
photo.url
The image file.
photo.credit
Who took or owns the photo.
photo.license
The photo's license, like CC BY 2.0.
photo.page
The photo's page on Wikimedia Commons, with its full details.
sources
A list saying where each value came from: one entry per source. It is in the JSON and Parquet files, not the CSV. In Parquet, a key an entry leaves out is null.
sources[].source
The source's name, like Catalogue of Life.
sources[].fields
The fields this source filled in.
sources[].license
The license of what came from this source.
sources[].retrieved
The date critwire fetched it (YYYY-MM-DD).
sources[].url
The exact address critwire asked, so you can check the answer yourself.
sources[].doi
The source's DOI, a permanent link for citing it.
sources[].checklistKey
For GBIF: the checklist the id belongs to.
sources[].release
For the Catalogue of Life: the release critwire used.
sources[].release.key
The release's dataset key on ChecklistBank.
sources[].release.alias
Its short name, like COL26.10.
sources[].release.version
Its version.
sources[].release.issued
The date it came out.
replacedBy
Usually null. If critwire ever retires a record (say, two turn out to be the same animal), this lists the ids that replace it. Retired ids are never reused.

CSV column names

The CSV flattens each record: a column is the field's path in snake_case, with dots turned into underscores. So taxonomy.class becomes taxonomy_class and range.countriesWithOpenRecords becomes range_countries_with_open_records. Lists (countries and replaced_by) are joined with ;, and null is an empty cell. The file is UTF-8.

Countries

The countries files turn a two-letter code into a place: one row per code, sorted by code. They cover every code the species files use, and every code GBIF uses, so a code that shows up later still has a row. They hold names only, no maps or borders.

Every column is text and never empty, in this order:

code
The two-letter country code (ISO 3166-1), like BR. The same codes as range.countriesWithOpenRecords, plus XK for Kosovo, the code GBIF uses. Each code has one row.
name
The everyday English name, like Brazil. Each name has one row.
continent
The continent, like South America. Islands far from any continent, such as Mauritius, have Seven seas (open ocean).
region
The United Nations region: Africa, Americas, Asia, Europe, Oceania or Antarctica.
subregion
The United Nations subregion, like Caribbean or Middle Africa.

The names follow Natural Earth, a free public-domain world map, exactly as it has them, and so do the continents and regions. Some read differently from other lists: CN is "People's Republic of China" and TW is "Taiwan".

Reading the CSV: Namibia's code is NA, which some tools read as a missing value. In pandas, pass keep_default_na=False to read_csv; in R, pass na.strings = character(0) to read.csv. DuckDB, the Parquet file and the JSON file keep it as the text NA.

Range listings

Where is an animal native, and where did people bring it? These files collect what named open sources say about that, country by country: one row per claim, with who made it and a link to check it. critwire doesn't judge the claims. When two sources disagree, both rows are here.

Read each row as what its source lists, nothing more. A row saying introduced doesn't say the animal lives wild in that country. A row saying absent doesn't say it once lived there. And no row means critwire holds no open listing, never that the animal isn't there.

The rows come from three kinds of source, all credited under Credits:

All three files hold the same rows, sorted by animal, country, area, origin, presence and source key. The columns, in this order:

speciesId
The animal's id in the species files.
country
The country the source lists the animal in: a two-letter code from the countries files.
area
A narrower place the source names inside the country, like Hawaii or Azores. null means none is recorded, which doesn't claim the whole country.
origin

How the source says the animal came to be there. One of:

  • native-or-pre-1500: native, or brought by people before 1500 CE. The source doesn't separate the two.
  • native: the source says native, without that blur.
  • introduced: the source says introduced, or has the animal on a register of non-native species. This doesn't say it lives wild there.
  • uncertain: the source marks its origin as uncertain.
presence

What the source says about the animal being there. One of:

  • present: the source says present. On a native list, that can include an animal put back into its native range.
  • uncertain: the source marks it as doubtful, uncertainly present or possibly extinct.
  • absent: the source says absent. This doesn't say it once lived there, or why it's gone, or since when.
  • unstated: the source gives no status. This doesn't say it lives there now.
source
The source's name, as attribution.json credits it.
sourceKey
The source's stable id: a GBIF dataset key, or a short name (mdd, curated). A GBIF key matches gbifChecklists[].key in attribution.json.
license
The license of this row's values, as its source grants it: CC0 1.0 or CC BY 4.0.
doi
A DOI to cite the source by, without https://doi.org/. It is null only on a curated row, whose url is its reference.
url
The page to check this row against: the source's page for the animal, or a curated row's reference.
sourceTerm
What the source said. On a source's row it is word for word: a place as listed, with its question mark if it has one (Cambodia?), or the source's terms for how the animal arrived and its status, joined by a slash (INTRODUCED/PRESENT, with - for a blank). On a curated row it is our own short summary of the reference.

Reading the CSV: column names are in snake_case (species_id, source_key, source_term) and null is an empty cell. Namibia's code is NA: see the note under Countries.

What sources list for one animal

SELECT c.name, l.area, l.origin, l.presence, l.source
FROM 'https://critwire.com/v1/range-listings.parquet' AS l
JOIN 'https://critwire.com/v1/species.parquet' AS s ON s.id = l.speciesId
JOIN 'https://critwire.com/v1/countries.parquet' AS c ON c.code = l.country
WHERE s.slug = 'jaguar'
ORDER BY c.name;

Where sources disagree

A conflict is a claim against its opposite, for one animal and country, on rows with no narrower area: native against introduced, or present against absent. uncertain and unstated contradict nothing. Every row stays in the files, and this query lists each such place. An empty result would only mean no conflict today.

SELECT speciesId, country
FROM 'https://critwire.com/v1/range-listings.parquet'
WHERE area IS NULL
GROUP BY 1, 2
HAVING (COUNT(*) FILTER (origin LIKE 'native%') > 0 AND COUNT(*) FILTER (origin = 'introduced') > 0)
    OR (COUNT(*) FILTER (presence = 'present') > 0 AND COUNT(*) FILTER (presence = 'absent') > 0)
ORDER BY 1, 2;

Next to open records

range.countriesWithOpenRecords says where open records exist; these files say what sources list. The two answer different questions, and either can hold countries the other lacks. This query puts them side by side: every country with open records of each animal, with any listing for it. An empty source means critwire holds no listing for that pair.

SELECT s.id, s.code, l.origin, l.presence, l.source
FROM (
  SELECT id, unnest("range".countriesWithOpenRecords) AS code
  FROM 'https://critwire.com/v1/species.parquet'
) AS s
LEFT JOIN 'https://critwire.com/v1/range-listings.parquet' AS l
  ON l.speciesId = s.id AND l.country = s.code;

Licenses

You may use critwire's data for anything, including school work and apps you sell, as long as you give credit (see Cite).

Credits

critwire is built on the work of these open projects. The same list, ready for code, is in attribution.json.

Catalogue of Life
Bánki, O., Roskov, Y., Döring, M., Ower, G., Hernández Robles, D. R., Plata Corredor, C. A., Stjernegaard Jeppesen, T., Örn, A., Pape, T., Hobern, D., Garnett, S., Little, H., DeWalt, R. E., Miller, J., Orrell, T., Aalbu, R., Abbott, J., Aedo, C., Aescht, E., et al. (2026). Catalogue of Life (Version 2026-10-14). Catalogue of Life Foundation, Amsterdam, Netherlands. https://doi.org/10.48580/dgzh4
License: CC BY 4.0, retrieved 2026-10-20. Used for 69 records: ids.col, taxonomy.
GBIF Backbone Taxonomy
GBIF Secretariat (2023). GBIF Backbone Taxonomy. Checklist dataset https://doi.org/10.15468/39omei accessed via GBIF.org on 2026-10-21.
License: CC BY 4.0, retrieved 2026-10-21. Used for 73 records: ids.gbif.
GBIF checklists
Each dataset has its own citation and DOI: see gbifChecklists in https://critwire.com/v1/attribution.json
License: CC0 1.0 or CC BY 4.0, per dataset, retrieved 2026-11-01. Used for 32 rows: range-listings.country, range-listings.area, range-listings.origin, range-listings.presence, range-listings.sourceTerm.
GBIF.org occurrence search
Derived dataset GBIF.org (21 October 2026) Filtered export of GBIF occurrence data https://doi.org/10.15468/dd.ky9cyt
License: CC BY 4.0, retrieved 2026-10-21. Used for 72 records: range.countriesWithOpenRecords.
Mammal Diversity Database
Mammal Diversity Database. (2026). Mammal Diversity Database (Version 2.5) [Data set]. Zenodo. https://doi.org/10.5281/zenodo.21654811
License: CC BY 4.0, retrieved 2026-11-01. Used for 400 rows: range-listings.country, range-listings.area, range-listings.origin, range-listings.presence, range-listings.sourceTerm.
Natural Earth
Made with Natural Earth. Free vector and raster map data @ naturalearthdata.com.
License: Public domain, retrieved 2026-10-28. Used for 250 countries: countries.name, countries.continent, countries.region, countries.subregion.
Wikidata
Wikidata, https://www.wikidata.org/ (CC0 1.0)
License: CC0 1.0, retrieved 2026-10-20. Used for 76 records: ids.wikidata, ids.inaturalist, ids.ncbi.
critwire base
critwire (https://critwire.com), CC BY 4.0
License: CC BY 4.0. Used for 76 records: ids.iucn, taxonomy.
critwire curated
critwire (https://critwire.com), CC BY 4.0
License: CC BY 4.0. Used for 86 rows: range-listings.country, range-listings.area, range-listings.origin, range-listings.presence, range-listings.sourceTerm.

GBIF occurrence data

The country lists count 396,627 open occurrence records from 454 datasets shared through GBIF. GBIF registered them as a derived dataset with its own DOI, so every dataset gets credit: 10.15468/dd.ky9cyt.

Derived dataset GBIF.org (21 October 2026) Filtered export of GBIF occurrence data https://doi.org/10.15468/dd.ky9cyt

The full list of datasets and their record counts is in attribution.json.

GBIF checklists

17 checklists shared through GBIF

Photos

74 photos from Wikimedia Commons

Cite

When you use critwire's data, credit it like this:

critwire (https://critwire.com), CC BY 4.0

In a school report, a footnote or the sources list is enough. In an app, put it on an about or credits screen. If you show photos, show each photo's credit and license too. In research, also cite the sources you rely on: their citations are in Credits, the GBIF DOI covers the country lists, and each range-listings row names its own source.