Genome Coordinate System Converter — BED (0-based) ↔ GFF/VCF/SAM (1-based)
BED coordinates and GFF/VCF coordinates differ by 1 — this is the most classic source of off-by-one errors in bioinformatics. This tool converts an interval between the two coordinate systems and gives you ready-to-paste BED and GFF lines.
The Two Coordinate Systems
Both systems are explicitly defined in the specification (see sources at the end):
| First base number | Interval notation | Formats using this system | |
|---|---|---|---|
| 1-based | 1 | Closed interval [start, end] |
SAM, VCF, GFF/GTF, Wiggle |
| 0-based | 0 | Half-open interval [start, end) |
BAM, BCFv2, BED, PSL |
The canonical example from the spec itself: bases 3 through 7, inclusive,
written as [3, 7] in 1-based notation, and [2, 7) in 0-based notation.
Only the Start Differs by 1 — the End Is the Same
This is the single most important thing to remember. Using the example above:
GFF start = 3 end = 7
BED start = 2 end = 7
↑ identical
BED’s end and GFF’s end are numerically identical. The only difference is in start. The reason: the 0-based half-open interval shifts the start one position to the left, while the end is exclusive — the two offsets cancel out exactly.
The most common mistake is adding 1 to end as well, which silently extends every interval by one base. This produces no error message — it just skews your statistics quietly. One extra base per interval, tens of thousands of intervals, and the cumulative error becomes substantial.
The Length Formula Differs Accordingly
BED length = end − start (no +1)
GFF length = end − start + 1 (add 1)
Both formulas give the same result. The example above is 5 bp either way: 7 − 2 = 5, 7 − 3 + 1 = 5.
The classic symptom of mixing them up is that all interval lengths are off by 1 — if your calculated exon lengths are consistently 1 less or 1 more than database values, you have almost certainly applied the wrong formula.
Single-Base Sites
A SNP at VCF POS = 1000 becomes, in BED:
chr1 999 1000
It looks like it spans two positions, but the length is exactly 1000 − 999 = 1 — one base.
When converting a SNP list to BED, subtract 1 from start; leave end unchanged.
BED Can Represent Zero-Length Intervals; GFF Cannot
In BED, start == end (e.g., chr1 100 100) is valid and represents a zero-length insertion point — an insertion occurring between base 100 and base 101.
A 1-based closed interval cannot represent zero length: [101, 100] (start > end) is illegal in GFF (the spec explicitly requires start ≤ end). Such intervals cannot be directly converted; the insertion site can only be described in text.
This tool will tell you explicitly when a conversion is not possible, rather than returning a plausible-looking but incorrect result.
A Further Pitfall: Strand Orientation
Coordinate systems are just the first layer. BED column 6 and GFF column 7 both record strand, but coordinates are always given relative to the forward (plus) strand — a gene on the minus strand still has start < end; the two values are not swapped. When you need the “5′ end of the gene itself,” you must use strand to decide whether to take start or end.
Data Sources
The definitions of both coordinate systems and the format assignments come from the terminology section of the SAM specification in the official htslib spec repository (Samtools/hts-specs, SAMv1 §1), which explicitly states that “SAM, VCF, GFF and Wiggle use 1-based coordinates” and “BAM, BCFv2, BED and PSL use 0-based coordinates,” and gives the [3,7] / [2,7) example.
Two independent corroborations: the VCF specification (VCFv4.3) states “POS is the reference position, with the first base having position 1”; the GFF3 specification (Sequence Ontology) states coordinates are “positive 1-based integer coordinates” and “start must be less than or equal to end.”
Related Tools
For sequence composition statistics, see Basic Sequence Statistics; for sequencing depth and data volume, see Sequencing Coverage Calculator.
FAQ
What exactly is the difference between BED and GFF coordinates?
Only the start differs. BED uses 0-based half-open intervals; GFF uses 1-based closed intervals. BED's start is 1 less than GFF's, while both end values are numerically identical. For bases 3 through 7: GFF has start=3, end=7; BED has start=2, end=7. Adding 1 to end as well is the most common mistake — it silently adds one extra base to every interval.
Why doesn't the BED length formula require adding 1?
Because the half-open interval excludes the endpoint. BED length = end − start; GFF length = end − start + 1; both formulas yield the same number. If your interval lengths are consistently 1 off from database values, you have almost certainly mixed up the two formulas.
How do I convert a SNP from VCF to BED?
Subtract 1 from start; leave end unchanged. A VCF site with POS=1000 becomes the BED line chr1 999 1000. It looks like it spans two numbers, but the length is 1000−999=1 — exactly one base.
What does it mean when start equals end in BED?
It is a zero-length insertion point, indicating an insertion between that position and the next. This is valid in BED. However, a 1-based closed interval cannot represent zero length (GFF3 requires start ≤ end), so such intervals cannot be converted to GFF — only described in text. This tool will say so explicitly rather than returning a plausible-looking but wrong result.
Should start and end be swapped for minus-strand genes?
No. In both BED and GFF, coordinates are always given relative to the forward strand — a minus-strand gene still has start < end. Strand is recorded separately in BED column 6 or GFF column 7. When you need the 5′ end of the gene itself, use strand to decide whether to take start or end.
Which other formats use 0-based coordinates?
According to the SAM specification terminology: 0-based half-open formats are BAM, BCFv2, BED, and PSL; 1-based closed-interval formats are SAM, VCF, GFF/GTF, and Wiggle. Note that SAM and BAM store the same data in two forms but with different coordinate conventions — text SAM is 1-based, binary BAM is 0-based; the conversion is handled transparently by tools when reading and writing.
Which coordinate system do samtools and IGV use for region queries?
1-based closed intervals. For example, chr1:1000-2000 means bases 1000 through 2000 inclusive — 1001 bp total. This differs from BED notation. When copying BED coordinates into a samtools region query, add 1 to start.
Related tools
DNA / RNA Reverse Complement Online Converter
Paste a sequence to get its reverse complement, complement, or reverse; supports FASTA input and IUPAC degenerate bases.
Online DNA GC Content and Tm Calculator
Calculate GC%, base composition, molecular weight, and two empirical Tm values — for rapid primer screening.
DNA to Protein Translation — Six-Frame Online Tool
Standard genetic code (NCBI table 1): single-frame or six-frame translation with ORF finder.
Buy me a coffee