Choosing and combining backbones

This article shows how taxify decides which backbone resolves each name, how to name the backbones yourself, how to compare their answers for the same names, and how to download and pin backbone versions. It ends with a list of backbone choices for common kinds of name lists. Installation is covered in Get started.

  1. Match with the default fallback chain, or name the backbones in backbone.

  2. Compare the backbones’ answers with mode = "wide" or mode = "agreement".

  3. Check names a backbone does not cover with lookup_genus() and taxify_register_coverage().

  4. Download and pin versions with taxify_download(), and list them with list_backbones().

library(taxify)

The default fallback chain

A backbone is a published taxonomic database stored as a file on your disk. taxify supports 19 backbones of taxa, and two of vegetation units described in Matching vegetation units. list_backbones() reports each one’s scope, version, number of names and whether it is installed:

bb <- list_backbones(verbose = FALSE)
bb[, c("name", "scope", "version", "n_names", "installed")]
#>           name                               scope version n_names installed
#> 1          wfo                     Vascular plants 2026.06 1664014      TRUE
#> 2          col                        All kingdoms 2026.09 5432444      TRUE
#> 3        colxr                        All kingdoms 2026.09 8479599      TRUE
#> 4         gbif                        All kingdoms 2023.08 6404001      TRUE
#> 5         itis         US focus, freshwater/marine 2026.09 1000552      TRUE
#> 6         ncbi                            All life 2026.09 2952424      TRUE
#> 7          ott                All life (synthetic) 2026.09 3690217      TRUE
#> 8        worms                      Marine/aquatic 2026.09 1565652      TRUE
#> 9      euromed       European/Mediterranean plants 2026.08  146922      TRUE
#> 10    fungorum                               Fungi 2026.08  315037      TRUE
#> 11   algaebase                               Algae 2026.09  172351      TRUE
#> 12    fishbase                              Fishes 2026.08  102703      TRUE
#> 13 sealifebase             Non-fish marine/aquatic 2026.08  134031      TRUE
#> 14   reptiledb                            Reptiles 2026.07   50043      TRUE
#> 15        lcvp                     Vascular plants 2026.08 1337891      TRUE
#> 16        wcvp                     Vascular plants 2026.06 1448984      TRUE
#> 17         mdd                             Mammals 2026.08   61862      TRUE
#> 18     avilist                               Birds 2026.08   40572      TRUE
#> 19        lpsn      Prokaryotes (Bacteria/Archaea) 2026.08   44885      TRUE
#> 20         evc European vegetation units (syntaxa)       4    7542      TRUE
#> 21       vegcz    Czech vegetation units (syntaxa) 2026.10    2258      TRUE

Without a backbone argument, taxify() uses every installed backbone of taxa as a fallback chain: each name is matched against the first backbone, the names left unmatched go to the second, and so on. The order is fixed by priority. The Extended Release of the Catalogue of Life (COL XR) comes first, then the Catalogue of Life (COL), then the backbones of one group (marine species, plants, fungi, algae, fishes, reptiles, mammals, birds, prokaryotes), then the broad compilations GBIF, ITIS, NCBI and OTT. On a new setup install_backbones() installs COL, GBIF and the Integrated Taxonomic Information System (ITIS); every backbone downloaded later joins the chain at its place in that order.

The list below mixes a plant, two animals renamed since their description, a fungus, a fish, a bacterium and a brown alga:

mixed <- c(
  "Quercus robur", "Panthera leo", "Amanita muscaria", "Salmo trutta",
  "Escherichia coli", "Macropus rufus", "Fucus vesiculosus",
  "Parus caeruleus"
)
res <- taxify(mixed, verbose = FALSE)
res[, c("input_name", "accepted_name", "backbone")]
#>          input_name       accepted_name backbone
#> 1     Quercus robur       Quercus robur    colxr
#> 2      Panthera leo        Panthera leo    colxr
#> 3  Amanita muscaria    Amanita muscaria    colxr
#> 4      Salmo trutta        Salmo trutta    colxr
#> 5  Escherichia coli    Escherichia coli    colxr
#> 6    Macropus rufus    Osphranter rufus    colxr
#> 7 Fucus vesiculosus   Fucus vesiculosus    colxr
#> 8   Parus caeruleus Cyanistes caeruleus    colxr
#> Sources: COLXR 2026.08 | cite() for full citations

All 19 backbones are installed on the machine that built this page, so the chain starts with COL XR. It resolves all eight names, and the other 18 backbones are skipped. The backbone column records which backbone matched each row, and the line under the table names the backbones to cite for this result: only those that matched a row. Macropus rufus and Parus caeruleus are synonyms in COL XR, and their rows carry its accepted names Osphranter rufus and Cyanistes caeruleus.

The first backbone that matches a name decides its accepted name. taxify does not take a vote across backbones: several backbones copy their treatment from one another, so a majority can follow the oldest treatment. Comparing backbones shows how to see where they disagree.

options(taxify.backbone_priority = ) changes the order for a session, and options(taxify.default_backbones = ) the set install_backbones() installs when called without arguments.

Naming the backbones

When most names of a list belong to one group, that group’s backbone can come first. A backbone vector replaces the default chain with your own; here the mixed list is resolved against World Flora Online (WFO) first, with COL for the rest. Before a name moves on, taxify checks the genus register, an index of the genera of every backbone, and does not send a name to a backbone that holds none of its genus:

res <- taxify(mixed, backbone = c("wfo", "col"))
#> Matching 8 names against 2 backbones: wfo -> col
#>   [wfo] Matching 8 names...
#>   [col] Matching 6 remaining names...
res[, c("input_name", "accepted_name", "match_type", "backbone")]
#>          input_name       accepted_name   match_type backbone
#> 1     Quercus robur       Quercus robur        exact      wfo
#> 2      Panthera leo        Panthera leo        exact      col
#> 3  Amanita muscaria    Amanita muscaria        exact      col
#> 4      Salmo trutta        Salmo trutta        exact      col
#> 5  Escherichia coli    Escherichia coli        exact      col
#> 6    Macropus rufus    Osphranter rufus        exact      col
#> 7 Fucus vesiculosus                <NA> out_of_scope     <NA>
#> 8   Parus caeruleus Cyanistes caeruleus        exact      col
#> Sources: WFO + COL | cite() for full citations

The progress lines show the chain: WFO matched Quercus robur, and COL received six of the seven remaining names. A name present in both backbones takes the treatment of the one listed first, including its accepted name, family and synonym resolution. Fuzzy matching runs inside each backbone before the name moves on, so a misspelt plant name is compared with WFO’s names before it reaches COL.

Fucus vesiculosus was not sent to COL, because the register records that neither WFO nor COL holds its genus; the row has match_type = "out_of_scope". The register is described in How names are matched. Adding AlgaeBase, the backbone for algae, resolves it:

res <- taxify(mixed, backbone = c("wfo", "algaebase", "col"),
              verbose = FALSE)
res[res$input_name == "Fucus vesiculosus",
    c("input_name", "accepted_name", "match_type", "backbone")]
#>          input_name     accepted_name match_type  backbone
#> 7 Fucus vesiculosus Fucus vesiculosus      exact algaebase
#> Sources: ALGAEBASE 2026.09 | cite() for full citations

Checking names outside a backbone

A row that comes back out_of_scope needs a backbone that holds its genus. lookup_genus() returns the genus register’s entry for a genus, and taxify_register_coverage() lists the backbones that hold it:

lookup_genus("Fucus")[, c("genus", "kingdom", "family", "life_form")]
#>        genus   kingdom   family  life_form
#> 176828 Fucus Chromista Fucaceae brown alga
taxify_register_coverage("Fucus")
#>   genus    backbone version date_added
#> 1 Fucus       worms 2026.09 2026-09-14
#> 2 Fucus sealifebase 2026.08 2026-08-27
#> 3 Fucus         ott 2026.09 2026-09-14
#> 4 Fucus        ncbi 2026.09 2026-09-14
#> 5 Fucus        itis 2026.09 2026-09-14
#> 6 Fucus        gbif 2023.08 2026-09-22
#> 7 Fucus       colxr 2026.08 2026-09-23
#> 8 Fucus   algaebase 2026.09 2026-09-14

The COL release used here is not among them, while COL XR, which adds names from further sources, is. An out_of_scope row therefore points to a backbone to add to the chain, where match_type = "none" leaves open whether the name is misspelt or exists in no backbone.

Comparing backbones

Backbones can treat the same name differently, and the fallback chain shows only the first one’s answer. mode = "wide" matches every name against every backbone in backbone and adds one accepted_<backbone> column per backbone, plus all_agree:

names3 <- c("Macropus rufus", "Parus caeruleus", "Quercus robur")
wide <- taxify(names3, backbone = c("col", "gbif", "itis"),
               mode = "wide", verbose = FALSE)
wide[, c("input_name", "accepted_col", "accepted_gbif", "accepted_itis",
         "all_agree")]
#>        input_name        accepted_col       accepted_gbif       accepted_itis
#> 1  Macropus rufus    Osphranter rufus      Macropus rufus    Osphranter rufus
#> 2 Parus caeruleus Cyanistes caeruleus Cyanistes caeruleus Cyanistes caeruleus
#> 3   Quercus robur       Quercus robur       Quercus robur       Quercus robur
#>   all_agree
#> 1     FALSE
#> 2      TRUE
#> 3      TRUE
#> Sources: COL + GBIF + ITIS | cite() for full citations

COL and ITIS place the red kangaroo in Osphranter; the GBIF Backbone Taxonomy keeps it in Macropus. accepted_name is still the pick of the fallback chain, here COL’s, so the result passes to the add_*() functions unchanged.

mode = "agreement" reports the same comparison as counts:

agr <- taxify(names3, backbone = c("col", "gbif", "itis"),
              mode = "agreement", verbose = FALSE)
agr[, c("input_name", "n_backbones_matched", "n_distinct_accepted",
        "all_agree")]
#>        input_name n_backbones_matched n_distinct_accepted all_agree
#> 1  Macropus rufus                   3                   2     FALSE
#> 2 Parus caeruleus                   3                   1      TRUE
#> 3   Quercus robur                   3                   1      TRUE
#> Sources: COL + GBIF + ITIS | cite() for full citations

all_agree is NA when fewer than two backbones matched a name.

Columns from one backbone

The output columns are the same for every backbone. Three functions add the columns that only one backbone carries, and fill them on the rows that backbone matched; other rows get NA:

crab <- taxify(c("Carcinus maenas", "Quercus robur"), backbone = "col",
               verbose = FALSE)
crab <- add_col_info(crab)
crab[, c("input_name", "kingdom", "is_marine", "is_terrestrial")]
#>        input_name  kingdom is_marine is_terrestrial
#> 1 Carcinus maenas Animalia      TRUE          FALSE
#> 2   Quercus robur  Plantae        NA             NA
#> Sources: COL 2026.09 | cite() for full citations

COL matched the oak as well but records no habitat for it, so NA there means not recorded, not unmatched.

How the backbones differ in output

The columns hold the same kind of value for every backbone, with these differences:

An ID is meaningful only within its backbone. When a backbone is built, its synonyms are converted to is_synonym, accepted_name and accepted_id, and a synonym that points to another synonym is followed to the accepted name.

The source, licence and citation of each backbone are listed in The backbones and datasets.

Downloading and pinning versions

Each backbone is downloaded once into taxify_data_dir() and read from disk after that. install_backbones() and taxify_download() fetch backbones ahead of time, for a server or a session without network access. A function that needs a backbone that is not on disk asks before downloading it in an interactive session; in a script it stops with an error naming the install_backbones() call, unless options(taxify.auto_download = TRUE) or the environment variable TAXIFY_AUTO_DOWNLOAD allows the download:

taxify_download(c("wfo", "worms"))

The download goes into a latest folder that is replaced when a newer version is released. taxify compares the local versions with the published ones once per session, at the first call, and updates latest then; the version never changes during a session. The replaced version is deleted. Without network access, or with options(taxify.offline = TRUE) or the environment variable TAXIFY_OFFLINE set, it uses the files on disk.

taxify_store() lists the builds on disk with their sizes. taxify_clean() removes builds taxify no longer reads and files left by an interrupted download; taxify_clean("gbif") removes one backbone, and taxify_clean("all") the whole data directory.

A version string downloads into a folder of its own that is never replaced:

taxify_download("wfo", version = "2024.01")

Every row records the backbone version that matched it:

unique(res$backbone_version)
#> [1] "wfo:2026.06 (2026-09-15)"       "col:2026.09 (2026-09-14)"      
#> [3] "algaebase:2026.09 (2026-09-14)"

taxify_lock() writes these versions with a checksum of each file to a JSON file, and taxify_restore(install = TRUE) reinstalls the same builds on another machine, as shown in Get started. taxify_build() builds a backbone from its source files instead of downloading it, which needs the taxifydb package.

Choosing backbones for a list

The first backbone in the vector sets the treatment for most names, and broader backbones after it resolve the rest:

Where next