A DSL purpose-built for genomics and bioinformatics — native DNA/RNA/protein types, 1000+ built-in functions, streaming I/O, 21 bio API clients, and Rust performance with a clean, pipe-first syntax.
# Stream FASTQ — constant memory
read_fastq("data/reads.fastq")
|> filter(|r| mean_phred(r.quality) >= 30)
|> map(|r| r.id)
|> each(|id| println(id))
# Native DNA literal + operations
let seq = dna"ATCGATCGATCG"
println(gc_content(seq)) # 0.5
println(reverse_complement(seq)) # DNA(CGATCGATCGAT)
# Query NCBI for gene info
println("Fetching BRCA1 from NCBI...")
ncbi_gene("BRCA1") |> println()
General-purpose languages like Python and R require stitching together dozens of packages to do bioinformatics. BioLang is a DSL — every design decision, from the type system to the syntax, is made for genomics workflows. Here's what that means in practice:
pip install, no import boilerplate.
dna"ATCG", Interval, Variant, AlignedRead, Quality are first-class values with built-in methods, not strings pretending to be sequences.
reads |> filter |> map |> summarize. Data flows through a pipeline, just like the biological workflow it models.
BioLang is not a general-purpose language, and that's the point. It does one thing — bioinformatics scripting — and does it well.
Analyze sequences, variants, and expression data without learning a programming language first.
The fastest on-ramp to bioinformatics. Write your first analysis in minutes, not days of environment setup.
Quick one-off analyses without spinning up a Jupyter notebook. One command, instant results.
No conda environments, no dependency conflicts, no wheel compilation failures. Single binary, works everywhere.
BioLang isn't here to replace your existing tools — it's the fastest path from raw data to first result. Start here, then grow into Python or R when your analysis demands it.
Everything you need from read to result — batteries included.
Chain operations naturally with |>. No nested function calls, no temp variables. Data flows left to right.
First-class dna"...", rna"...", protein"..." literals with built-in methods for complement, translate, GC content.
Statistics, tables, matrices, file I/O (FASTA/FASTQ/VCF/BAM/BED/GFF), plotting, k-mers, alignment, motifs — all built in.
Process multi-GB FASTQ/BAM files without loading into memory. Lazy streams + pipes = constant memory usage.
NCBI, Ensembl, UniProt, UCSC, KEGG, STRING, PDB, Reactome, GO, COSMIC, BioMart, nf-core, BioContainers, Galaxy ToolShed, NCBI Datasets — query any database in one line.
Native Rust I/O via noodles, and sequence work that runs in compiled code rather than a loop: 16x faster than BioPython on translation, 3.6x on GC content. It loses elsewhere — k-mer counting is 3.9x slower than a Python dict, and anything written as an interpreted loop is slower still. See benchmarks →
Rosalind is the bioinformatics problem set used in teaching worldwide. These problems are not mine to choose, and the answers are not mine to mark: each solution is asserted against the official answer, and every one is re-run on each commit — natively, and again through the same WebAssembly build this site serves.
All four tracks are complete — every problem in each, asserted against its published answer.
Solutions are MIT. Problem statements belong to rosalind.info — each example paraphrases Given/Return in a line or two and links to the original rather than reproducing it.
Rosalind answers “does this match a published answer”. This answers the other half: does it agree with the tools people already use. Each task is written three times — once in BioLang, once in Python with BioPython, once in R with Bioconductor — and a comparator checks the values they produce: floats to 1e-6, integers and strings exactly.
Every run records the tool versions, the data source, the tolerance, and a SHA-256 over each side’s output, so “identical” is something you can check rather than something we assert.
Compare BioLang, Python and R →
Agreement is strong evidence, not proof: it adopts BioPython’s and Bioconductor’s conventions as the reference, and a shared misreading of a file format would be invisible to it. Where the languages genuinely disagree — BioLang rounds halves away from zero, Python and R round to even — that is recorded rather than hidden.
BioLang runs right here via WebAssembly. Click Run on any example below — no install needed.
First click downloads the runtime (~4 MB), then it's cached for the session. Every code block across the docs is interactive too.
let seq = dna"ATCGATCGATCG"
println(f"GC content: {gc_content(seq)}")
println(f"Complement: {complement(seq)}")
println(f"Rev-comp: {reverse_complement(seq)}")
println(f"Transcribe: {transcribe(seq)}")
println(f"Length: {seq_len(seq)} bp")
let coding = dna"ATGAAAGCTTTTGACTGA"
let prot = translate(coding)
println(f"Protein: {prot}")
let seq = dna"ATCGATCGATCG"
let kmer_list = kmers(seq, 4)
println(f"4-mers: {kmer_list}")
let normal = [5.2, 4.8, 5.1, 4.9, 5.3]
let tumor = [8.1, 7.9, 8.5, 7.6, 8.3]
let result = ttest(normal, tumor)
println(f"t = {round(result.statistic, 3)}")
println(f"p = {result.p_value}")
println(f"Significant: {result.p_value < 0.05}")
# Pipe-first: data flows left to right
let genes = ["BRCA1", "TP53", "EGFR", "KRAS"]
genes
|> filter(|g| len(g) <= 4)
|> map(|g| f"{g} ({len(g)} chars)")
|> each(|g| println(g))
Same task, less code, more clarity.
from Bio import SeqIO
import pandas as pd
records = []
for rec in SeqIO.parse("reads.fq", "fastq"):
quals = rec.letter_annotations[
"phred_quality"
]
if sum(quals)/len(quals) >= 30:
gc = (rec.seq.count("G")
+ rec.seq.count("C")) \
/ len(rec.seq)
records.append({"id": rec.id,
"gc": gc})
df = pd.DataFrame(records)
print(df.describe())
read_fastq("data/reads.fastq")
|> filter(|r| mean_phred(r.quality) >= 30)
|> each(|r| println(f"{r.id}: len={r.length}"))
32 bioinformatics tasks on real-world data (NCBI, UniProt, ClinVar, ENCODE).
These are whole-script times: interpreter startup and library imports included, which is what a one-off analysis actually costs — import Bio alone takes 400 ms or more. That framing flatters BioLang on small inputs, so read the large ones. Parsing a 30 kB FASTA comes out 76× faster, which is mostly startup; counting k-mers across 51 MB of chr22 comes out 2.8×, and that is the figure that reflects the work rather than the launch. Re-measured on bl 1.1.0 in August 2026 — the previous set was bl 0.2.1 from March, and understated current performance.
| Task | BioLang | Python | R | Speedup |
|---|---|---|---|---|
| ENCODE Peak Overlap | 0.154s | 2.614s | — | 17.0x |
| Protein K-mers | 0.011s | 0.154s | 1.071s | 14.0x |
| FASTA Parse (30 KB) | 0.002s | 0.153s | 1.040s | 76.5x |
| E. coli Genome | 0.010s | 0.164s | 1.079s | 16.4x |
| GC Content (51 MB) | 0.125s | 0.721s | 1.409s | 5.8x |
| K-mer Counting (21-mers) | 9.960s | 28.262s | — | 2.8x |
Linux (WSL2) — Intel i9-12900K, 16 GB RAM. Python wins on VCF/CSV text parsing where C extensions dominate. K-mer counting uses canonical (strand-agnostic) 21-mers — BioLang does strictly more work.
Take the startup out and the picture changes, so here it is too. Timed per operation on a 1 Mb genome, every implementation checked to return the same answer before any timing is believed. BioLang wins where a Rust builtin does the work — translation 16× faster than BioPython, GC content 3.6×, Viterbi decoding 4.7× faster than pure Python. It loses wherever the work happens in interpreted BioLang: k-mer counting 3.9× slower than a Python dict, FASTA parsing 3.3× slower, a plain loop 9× slower than CPython. Against C it still loses, by less than it did — edit distance runs Myers’ bit-parallel algorithm now, the same one edlib uses, which took it from 4.0× slower to 1.9×. Suffix arrays are still 6.8× behind pydivsufsort, because they use prefix doubling where it uses SA-IS. The harness is bench/harness.py, and bench/Dockerfile pins all three toolchains so you can reproduce it.
No installation, no server, no uploads. BioLang compiles to WebAssembly so you can analyze bioinformatics data entirely client-side. All tools work offline as installable PWAs.
Write and execute BioLang code blocks with persistent state, inline SVG charts, and syntax highlighting. Great for experimenting and learning.
Open local or public notebooks, edit Markdown and code cells, attach data, and render tables and plots. Later cells automatically run required earlier code.
Drop FASTA, FASTQ, VCF, BED, GFF, CSV files for instant parsing, statistics (N50, GC%, Q30, Ti/Tv), sortable tables, column filters, multi-format export, URL loading, and BioLang analysis. Data never leaves your machine.
Auto-detects genes, variants, accessions, and species on any webpage. Click any entity for instant details from NCBI, UniProt, gnomAD, and ClinVar. Chrome sidebar extension + PWA.
Personal literature monitor. Watch genes, drugs, and variants across PubMed and bioRxiv. Signal scoring ranks papers by relevance. Background checks, co-mention detection, and weekly digest. Chrome sidebar extension + PWA.
A complete reference for the language, free to read online.
Editor, file tree, console, and plots — the same interpreter as the CLI, compiled to WebAssembly. Open it in a browser with nothing installed, or run the desktop build when you need the things a browser cannot do.
Write and run BioLang in a tab. Every example pack installs into the workspace on a single link, with the sample data the documentation reads. Work is kept locally between visits.
The same workbench as a native app: your own filesystem, the bl
CLI, remote execution over SSH, and the APIs a browser cannot reach because they send no
CORS headers.
Single binary, no runtime dependencies.