Skip to main content
v2026.11,772 entries · CC-BY 4.0

BED File Format: The 0-Based, Half-Open Coordinate System Explained

The BED format for genomic intervals: required and optional columns, and the 0-based, half-open coordinate convention that differs from the 1-based, fully-closed systems used by VCF, GFF3, and GTF.

Written and maintained by CASRAI Editorial Board

Last updated

A BED file (Browser Extensible Data) is a plain-text, tab-delimited format for describing genomic intervals — a chromosome, a start coordinate, an end coordinate, and up to nine optional fields for name, score, strand, and exon structure. It is the working format for genomic regions across bioinformatics tooling: peak calls from ChIP-seq or ATAC-seq, exon and gene models, capture-panel targets, and the region files fed to bedtools, UCSC and Ensembl browsers, and variant annotators. The format itself is simple. The part that causes real bugs is its coordinate system: BED start coordinates are 0-based and its intervals are half-open, which is not how VCF, GFF3, GTF, or SAM/BAM express position. Converting between them without accounting for that difference is one of the most common silent errors in a genomics pipeline — silent because the script runs, produces a file, and is off by exactly one base at every boundary.

What a BED file contains

Each line of a BED file is one interval, with fields separated by tabs, not spaces. The specification (maintained as UCSC’s BED format documentation, part of the same family as the genome browser ecosystem) defines three required fields and nine optional ones, and a file can stop at any point after the third column — BED3, BED4, BED6, and BED12 are all valid, named for how many columns they carry.

The three required columns

Column Field Definition
1 chrom Chromosome or scaffold name (e.g. chr1, chrX, scaffold_12).
2 chromStart The starting position of the feature. The first base of a chromosome is numbered 0.
3 chromEnd The ending position of the feature. The base at this position is not part of the feature — the interval is half-open.

The nine optional columns (BED4–BED12)

Column Field Definition
4 name A label for the BED line, shown on browser tracks.
5 score An integer from 0–1000, often used to shade the feature on a browser display.
6 strand +, -, or . for unstranded/unknown.
7 thickStart Where the “thick” (typically coding) part of the feature begins, for display.
8 thickEnd Where the thick part ends.
9 itemRgb An R,G,B triplet controlling display colour, e.g. 255,0,0.
10 blockCount Number of sub-features (typically exons) within the line.
11 blockSizes Comma-separated list of block (exon) sizes.
12 blockStarts Comma-separated list of block start positions, relative to chromStart.

Columns 7–12 exist specifically to describe a multi-exon transcript as a single BED line: chromStart/chromEnd span the whole gene model, while blockCount/blockSizes/blockStarts carve out the individual exons within it. A tool reading a BED12 file has to combine all twelve fields to reconstruct the exon structure — there is no separate “exon” line the way GFF3 uses parent/child feature rows.

0-based, half-open: what the coordinate system actually means

Two independent design choices combine to define BED coordinates, and it is worth separating them:

  • 0-based: the first base of a chromosome is position 0, not position 1. This applies to chromStart.
  • Half-open: the interval [chromStart, chromEnd) includes chromStart but excludes chromEnd — the base at chromEnd is the first base not in the feature.

Put together, the number of bases in a BED feature is simply chromEnd − chromStart, with no off-by-one correction needed — a property that makes half-open coordinates convenient for programmatic interval arithmetic (concatenating two adjacent intervals, computing overlaps, or measuring length all reduce to plain subtraction). The trade-off is that chromStart and chromEnd are not symmetric: chromStart is 0-based, but because chromEnd points one base past the end of the feature, it has the same numeric value as the 1-based, inclusive coordinate a biologist would read off a browser or a paper. That asymmetry is exactly what trips people up when they convert by hand.

Why VCF, GFF3, GTF, and SAM disagree with BED

BED is the exception, not the rule, among genomics formats. VCF’s POS field, GFF3’s and GTF’s start/end columns, and SAM’s POS field are all 1-based and fully closed: the first base of a chromosome is position 1, and an interval’s start and end coordinates are both included in the feature. A 10-base feature beginning at the first base of a chromosome is start=1, end=10 in a VCF or GFF3 row, but chromStart=0, chromEnd=10 in a BED row — the end coordinate is numerically identical across the two systems; only the start shifts by one.

Worked example: the same interval, two conventions

Take a feature spanning eleven bases, positions 1000 through 1010 inclusive, as it would appear read off a genome browser or written in a GFF3/VCF-style 1-based file:

Representation Start End Bases covered Feature length
1-based, fully-closed (GFF3, GTF, VCF, SAM) 1000 1010 1000, 1001, … 1010 end − start + 1 = 11
0-based, half-open (BED) 999 1010 999, 1000, … 1009 chromEnd − chromStart = 11

Both rows describe the identical eleven bases of sequence. The conversion rule that falls out of the example generalizes cleanly: to go from a 1-based closed interval to BED, subtract 1 from the start and leave the end unchanged; to go the other direction, add 1 to chromStart and leave chromEnd unchanged. Get the direction backwards, or apply the subtraction to both ends instead of just the start, and every feature in the output file is shifted by one base — a bug that produces a file that loads, runs through bedtools without error, and returns results that are subtly wrong at every boundary.

Where the off-by-one bug actually bites

This is not a theoretical concern. The conversion between coordinate systems happens constantly in a real analysis, because BED-format tools like bedtools are the standard way to intersect, merge, and annotate intervals, while the files coming out of variant callers, annotation databases, and alignment steps are 1-based:

  • VCF → BED, to intersect variants against a target region. Naively copying POS into both chromStart and chromEnd (instead of POS−1 and POS) produces a zero-length interval that silently fails to match anything, or a single-base shift depending on which side is miscoded.
  • GFF3/GTF → BED, to extract exon or gene regions. The same subtract-one-from-start rule applies to the start column; forgetting it shifts every feature’s 5′ boundary by one base, which matters most at the transcription start site and splice junctions.
  • BED → VCF-style reporting, when publishing or comparing coordinates. Reporting a BED chromStart directly as a “1-based position” without adding 1 understates every start coordinate by one base — a common source of coordinates that are off by exactly one when a result set is checked against a paper or a browser.
  • Liftover between genome builds. Coordinate-liftover tools generally expect BED-style 0-based half-open input; feeding them 1-based coordinates unmodified introduces the same one-base error into every lifted feature.

The reason this class of bug is so persistent is that it does not throw an error. A shifted BED file has the right number of lines, the right chromosomes, and intervals that are almost always the right length — it is wrong by exactly one base at each boundary, which is easy to miss in a spot check and can matter enormously at a splice site, a transcription start site, or a small variant call.

Converting between coordinate systems correctly

The general-purpose fix is to be explicit about the subtraction rather than relying on a tool’s default. Converting single-base VCF positions to BED with awk, skipping header lines:

awk 'BEGIN{OFS="\t"} !/^#/ {print $1, $2-1, $2, $3}' variants.vcf > variants.bed

Here $2 is the VCF POS column; $2-1 becomes chromStart and the unmodified $2 becomes chromEnd — a single-base variant becomes a one-base-wide BED interval. For multi-base indels, check how your variant caller reports POS and the reference/alt allele lengths before assuming this simple form is sufficient; a deletion spanning several bases needs chromEnd extended by the deleted length, not left at POS.

Converting a GFF3 or GTF feature (columns 4 and 5 hold start/end in both formats) to BED follows the same pattern:

awk 'BEGIN{OFS="\t"} !/^#/ {print $1, $4-1, $5, $3}' features.gff3 > features.bed

Where a full-featured converter already exists — UCSC’s gtfToGenePred/genePredToBed chain, or a library function in a package like pybedtools or Bioconductor’s rtracklayer — prefer it over a hand-rolled awk line for anything beyond a quick check; those tools already handle the exon-block and strand edge cases that a one-line script does not. Whichever route you take, spot-check the result against a known feature in a genome browser (which displays 1-based coordinates) before trusting the converted file downstream, and treat any pipeline step that touches genomic coordinates as needing an explicit, commented note on which convention is in play at that point — especially in a Snakemake or Nextflow pipeline where a conversion step can be buried several rules deep and easy to lose track of.

Related interval-based formats

Several other formats extend or piggyback on BED’s conventions, and are worth distinguishing:

  • bedGraph — BED4 restricted so the fourth column is a numeric signal value rather than free text, used for coverage tracks and continuous scores. Same 0-based, half-open coordinates as BED.
  • BEDPE — pairs two BED intervals on one line (chrom1, start1, end1, chrom2, start2, end2, ...), used by bedtools for paired-end and structural-variant data where a “feature” connects two separate genomic locations.
  • narrowPeak / broadPeak (ENCODE formats) — BED6+3/BED6+4 extensions used for ChIP-seq and ATAC-seq peak calls, adding signal, p-value, and q-value columns on top of the standard BED6 fields.

All three inherit BED’s coordinate system, so the same conversion caution applies to each of them.

Frequently asked questions

Is a BED file 0-based or 1-based?

chromStart is 0-based. chromEnd is numerically what a 1-based, inclusive end coordinate would be, because the interval is half-open — so the honest answer is “both,” depending on which column you’re looking at, which is exactly why hand-converting a single coordinate without checking whether it is a start or an end is a common source of error.

Why do half-open intervals make length calculation easier?

Because chromEnd − chromStart gives the feature length directly, with no +1 or -1 correction. In a fully-closed system like VCF or GFF3, length is end − start + 1; forgetting the +1 there is its own, mirror-image off-by-one bug.

Does GTF use the same coordinates as GFF3?

Yes. GTF (Gene Transfer Format) is a restricted dialect of GFF2 with a fixed attribute structure, but it shares GFF’s 1-based, fully-closed coordinate convention for the start/end columns — the same conversion rule to and from BED applies to both.

Is a SAM/BAM alignment position 0-based or 1-based?

SAM’s POS field is 1-based, matching VCF and GFF3, not BED — a common assumption to double-check when a pipeline moves data between alignment output and interval files. This is a separate coordinate question from the per-base Phred quality scores carried in the same alignment record, which describe base-call confidence rather than position.

Where does BED coordinate confusion typically surface in a real pipeline?

Most often at the seam between two tools written by different groups: a variant caller or aligner producing 1-based output feeding into a bedtools-based filtering or annotation step, or a custom region file built by hand for a targeted panel or a differential expression analysis and then intersected against BED-format peak calls. Any pipeline step, whether run interactively or scheduled as part of a batch job on shared compute, is worth an explicit unit test on a small, known interval before it runs on a full dataset.

Does the coordinate system depend on which tool or environment I’m using?

No — 0-based/half-open is a property of the BED file format itself, not of any particular tool, and it holds regardless of whether you built your environment with conda, pip, or mamba. A tool can choose to display 1-based coordinates to a user while storing 0-based coordinates internally (most genome browsers do exactly this), but the underlying BED file on disk is always 0-based, half-open by specification.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · included with Regulatory Radar

Ask about BED File Format: The 0-Based, Half-Open Coordinate System Explained

Ask CASRAI answers research-administration questions and cites the passages behind every claim — and says so when the corpus does not cover something, instead of guessing. It comes with a Regulatory Radar subscription at $29 a month, alongside the daily digest of regulatory changes and the dashboard of what changed.

150 questions a day, on this site, over the API, or inside your own tools through the CASRAI MCP server.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Regulatory Radar

Stop finding out after the fact

$29/month, cancel anytime. Daily digest updates from our analysis, a dashboard holding the same items, and a cited assistant for everything they raise.

  • Federal Register, Federal Register+, Grants.gov, Regulations.gov, NSF News, UKRI, plus CASRAI’s own published content.
  • 72,264 indexed passages, and every answer cites the ones it drew on.