biotite: a Swiss army knife for computational molecular biology
A comprehensive library for computational molecular biology
At a glance
- What is it?
- biotite bundles the common tasks of a sequence and structure analysis workflow into one Python library, from fetching records out of biological databases to reading files, aligning sequences and plotting results. Internally almost everything is a NumPy array, and the performance sensitive parts of the package live in a Rust extension.
- Who is it for?
- biotite suits a bioinformatician who wants one coherent library for fetching, parsing, analysing and plotting rather than a separate tool per file format, and who is comfortable with the NumPy array conventions it brings. It is a poor fit if your pipelines depend on the exact behaviour of an older release, since the 2.0 line requires Python 3.12, or if you need a feature the library has not implemented and no interface to external tools.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Five workflow stages under one import
The description of the scope is a list of workflow stages, and it is worth reading as a definition of what the library considers a complete bioinformatics job.
Searching and fetching data from biological databases comes first. Then reading and writing popular sequence and structure file formats. Then analysing and editing sequence and structure data. Then visualising that data. And finally interfacing external applications for further analysis.
The framing is a Swiss army knife, and the point of the phrase is that it is one library rather than a collection of unrelated tools. The example given for the range is deliberately wide, from identifying homologous sequence regions in a protein family to finding disulfide bonds in a protein structure, and the stated benefit is that you can focus on what your code makes unique rather than on writing parsers.
That last point is the practical argument. Reading a FASTA file is not interesting work, but every project that needs it writes it again, usually badly, and the two projects then disagree about what a multi-line sequence header means. A library that handles the formats consistently is a real saving, and it is the kind of saving that compounds across a group.
The interfacing external applications point deserves a note, because it is the honest boundary of the library. Biotite covers the parts of a workflow that are data manipulation, and where a task genuinely needs a specialised program, the library provides the interface rather than pretending to reimplement it.
Everything is a NumPy array, and that is the API
The internal data model is the part of the design that makes the library feel coherent, and the readme states it directly: Biotite internally stores most of the data as NumPy ndarray objects.
Three consequences follow, and the readme names all three. You get fast C-accelerated analysis, because the heavy loops are NumPy's rather than Python's. You get intuitive usability through NumPy-like indexing syntax, so a sequence object indexes like an array and slicing a sequence gives you a sequence. And you get extensibility through direct access of the internal NumPy arrays, which means you can drop down to array operations whenever the library does not offer what you need.
That third point is what separates biotite from a library that would hide its data behind an abstraction. Because the underlying array is reachable, the library does not have to anticipate every operation you might want. If you need a statistic that biotite does not compute, you compute it from the array instead of writing around the library or filing a feature request.
It also means the usual performance advice applies. If your script is slow, the profile will point at the places where you left NumPy and started writing Python loops, and the fix is usually to push the work back into array operations.
A worked example: fetch, parse, align
The readme's example is small enough to read in full, and it is the best demonstration of the library's shape, because it crosses three of the five workflow stages in about a dozen lines.
It downloads two protein sequences from the NCBI Entrez database, parses the downloaded file, and aligns the two sequences.
import biotite.sequence.align as align
import biotite.sequence.io.fasta as fasta
import biotite.database.entrez as entrezThe fetch step asks Entrez for a file by identifier, with the database name and the return type, and it is a single call:
file_name = entrez.fetch_single_file(
uids=["CAC34569", "ACL82594"], file_name="sequences.fasta",
db_name="protein", ret_type="fasta"
)The parse step reads the file into a FastaFile object and turns the records into sequence objects:
fasta_file = fasta.FastaFile.read(file_name)
avidin_seq, streptavidin_seq = fasta.get_sequences(fasta_file).values()And the analysis step aligns them using a standard substitution matrix with an affine gap penalty:
matrix = align.SubstitutionMatrix.std_protein_matrix()
alignments = align.align_optimal(
avidin_seq, streptavidin_seq, matrix,
gap_penalty=(-10, -1), terminal_penalty=False
)Three things to notice. The identifiers are real database accessions, so the example is runnable rather than illustrative. The alignment is an optimal one, and the gap penalty is a pair, which is the affine model. And the result prints in the standard alignment block format, so the output of a script is something you can paste into a paper or a terminal.
Version 2.0 moved the hot paths into Rust
The repository tells a story that the readme does not, and it is the story of a 2.0 release.
There is a Cargo.toml at the root, a Rust source directory, a rust-toolchain.toml, and a package named biotite_rust that builds a cdylib through PyO3. The Rust crate depends on the numpy and ndarray crates, plus num-traits, smallvec, itertools and bitflags, and the library is named rust with the path pointing at the source file. The lint configuration denies warnings outright.
The dev profile is set with optimisation level 3 and overflow checks disabled, with a comment explaining that this enables optimisations in dev mode for better performance during development. That is a deliberate choice for a scientific library where you want the interactive session to behave like the installed package.
The build integration is the interesting part. The setup.py file is nearly empty and its docstring says the build is configured in pyproject.toml, and that the file exists only to install a Rust toolchain into a temporary directory if none is available, so that the Rust extension can also be built on platforms without prebuilt wheels. The implementation checks for cargo on the path and, if it is missing, uses a package called puccinialin to set up a Rust toolchain and points the build at it.
That is a lot of machinery to support one library, and it explains the release history. Version 1.8.0 came out on 2026-10-16 and 2.0.0 on 2026-10-18, two days apart, which is the pattern of a major version landing immediately after a final feature release. The Rust core is part of the current codebase, and a change of that size is what justifies a major number.
Version floors and the dependency set
The packaging metadata is unusually specific, and two entries in it deserve attention.
The first is the Python floor. The project requires Python 3.12 or newer, which is aggressive for a scientific library whose audience is not always on the latest interpreter, and it is a consequence of choosing to build a Rust extension with a modern PyO3 and a modern NumPy.
The second is the dependency on a package called biotraj, pinned to at least 1.0 and below 2.0, which appears alongside the NumPy floor of 2.1. The rest of the required set is requests, msgpack, networkx and packaging, and the readme names numpy, requests, msgpack and networkx as the requirements, with matplotlib described as an extra needed for plotting. The msgpack and networkx entries are the ones that hint at the database layer, since a binary serialisation format and a graph library are not obvious dependencies for a sequence analysis package otherwise.
The optional dependency groups are split by purpose rather than lumped together. The test group is pytest plus pytest-codspeed, which is a benchmarking plugin and tells you the project tracks performance changes in continuous integration. The lint group pins ruff, numpydoc, pyright and taplo, so the documentation style, the type checker, the linter and the TOML formatter are all part of the same pinned toolchain. The Ruff configuration selects pyflakes, pycodestyle, isort, tidy imports, pep8 naming and missing return type annotations, and there is a taplo.toml for formatting the TOML files themselves.
The licence is BSD-3-Clause, and the manifest lists the licence files as the licence text and a THIRDPARTY.yml, which is how the Rust dependencies and their licences are accounted for.
Two install routes and a documentation site
Installation is conventional, and the readme gives both routes with the same weight.
conda install -c conda-forge biotitepip install biotiteThe conda route is the one to prefer if you are already in a scientific environment, because the binary wheels and the scientific stack are managed together, while pip is the obvious choice in a virtual environment or a container. The PyPI badge tracks the published version.
The documentation lives on a dedicated site, and the readme points at it for a tutorial, an example gallery and the API reference, plus contribution guidelines and a community chat on Discord. The gallery is the more interesting of the two, because for a library whose selling point is that it covers a whole workflow, a gallery showing a complete analysis is worth more than a list of function signatures.
The repository layout backs this up. There is a doc directory, a benchmarks directory, a tests directory, an environment.yml for the conda environment, and a pixi.lock, which points to the project having moved to the pixi tool for environment management while keeping conda as a user-facing install route. There is also a setup.py for the Rust toolchain fallback described earlier, and a MANIFEST.in for the source distribution.
One housekeeping detail worth copying into your own project: if you use Biotite in a scientific publication, the readme asks you to cite a specific paper by Kunzmann and Hamacher in BMC Bioinformatics from 2018, with a DOI. A library that maintains a citation request is telling you it expects to be used in published work, and it is a small thing that keeps attribution intact.
Editorial conclusion
biotite suits a bioinformatician who wants one coherent library for fetching, parsing, analysing and plotting rather than a separate tool per file format, and who is comfortable with the NumPy array conventions it brings. It is a poor fit if your pipelines depend on the exact behaviour of an older release, since the 2.0 line requires Python 3.12, or if you need a feature the library has not implemented and no interface to external tools. Before you upgrade, read the release notes for 2.0, check that your Python is 3.12 or newer, and confirm that the data types you relied on are still NumPy arrays rather than the new structures.
Frequently asked questions
What does biotite require to install?
It requires Python 3.12 or newer, and depends on numpy 2.1 or later, requests, msgpack, networkx, packaging and the biotraj package at version 1.x. Matplotlib is needed only for plotting. Both conda install -c conda-forge biotite and pip install biotite are supported.
How does biotite store sequence and structure data?
Internally most of the data is stored as NumPy ndarray objects, which gives fast C-accelerated analysis, NumPy-like indexing syntax, and direct access to the underlying arrays for anything the library does not implement itself.
What changed in biotite 2.0?
The repository shows a Rust extension built with PyO3, with a Cargo manifest, a Rust source directory and a rust-toolchain file, and the setup.py exists to install a temporary Rust toolchain when cargo is not present so the extension can be built where no prebuilt wheel exists. Version 1.8.0 was published on 2026-10-16 and 2.0.0 on 2026-10-18.
Can biotite fetch sequences from biological databases?
Yes. The readme example calls the Entrez module to fetch a FASTA file for two protein accessions, then parses it with the FASTA module and aligns the two sequences with an optimal alignment using the BLOSUM62 matrix and an affine gap penalty.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/biotite-dev-biotite)Was this useful?