How to Visualize BED Files in IGV
By Dr. Zubair Khalid, DVM, MS, PhD ·

By the end of this workflow, you will be able to load a BED file into IGV, select the matching genome, navigate to a locus, adjust the track so the features are visible, and save a session or batch script that reproduces the view. You need IGV desktop installed, a BED file, the genome build that the BED coordinates refer to, and optional htslib tools for large files. A terminal and a text editor help with the file checks.
IGV (Integrated Genomics Viewer) is a desktop genome browser that can open local data without uploading it to a server [1]. A BED file is one of the common bioinformatics file formats used to describe genomic intervals [2]. The workflow below starts with the file itself because most IGV loading problems are format or genome-build problems, not IGV problems.
What a BED File Contains and How IGV Interprets It
BED (Browser Extensible Data) is a tab-delimited text format. Each line describes one interval on a reference genome. The first three columns are required. Additional columns add a name, a score, a strand, a color, and block structure for gene models.
BED coordinates are 0-based and half-open. The start is the first base before the interval, and the end is the first base after the interval. IGV displays coordinates in 1-based, closed format. A BED interval with start = 100 and end = 200 covers the 100 bases from position 101 through position 200 in the IGV coordinate display. This difference is not a bug. It is the main reason a BED feature can look shifted by one base when compared with a VCF or a manually typed coordinate.
| Column | Name | Meaning | Required |
|---|---|---|---|
| 1 | chrom | Chromosome name, such as chr1 | Yes |
| 2 | start | 0-based start coordinate | Yes |
| 3 | end | End coordinate, exclusive | Yes |
| 4 | name | Feature label | No |
| 5 | score | 0 to 1000 value | No |
| 6 | strand | +, -, or . | No |
| 7 | thickStart | Start of the thick display block | No |
| 8 | thickEnd | End of the thick display block | No |
| 9 | itemRgb | Color as R,G,B or 0 | No |
| 10 | blockCount | Number of blocks in a BED12 feature | No |
| 11 | blockSizes | Comma-separated block lengths | No |
| 12 | blockStarts | Comma-separated offsets relative to chromStart | No |
A file with three columns is called BED3. A file with six columns is called BED6. A file with twelve columns is called BED12 and can represent spliced gene models. IGV can display all three. BED12 features use thickStart and thickEnd to draw thick coding blocks and thin untranslated blocks. blockStarts are offsets from the feature start, not absolute chromosome coordinates.
A valid BED12 line looks like this, with tab-separated columns:
chr1 1000 1300 GeneA 0 + 1000 1300 255,0,0 2 100,50 0,200
This feature starts at chromosome 1 position 1000 in BED coordinates. It has two blocks. The first block begins at offset 0 and is 100 bases long. The second block begins at offset 200 and is 50 bases long. The second block starts at chromosome coordinate 1200, not at coordinate 200.
BEDGraph is a related tab-delimited format with four columns: chromosome, start, end, and value. IGV can draw BEDGraph as a continuous bar chart, but a four-column BED file can also be read as a BED file with a name column. Use the .bedgraph extension or select the correct format when the fourth column is a numeric value.
Where BED Fits Among Bioinformatics File Formats
BED is an annotation format. It describes regions of interest, such as ChIP-seq peaks, ATAC-seq peaks, copy-number segments, or custom intervals. It does not contain raw reads or base qualities.
FASTA is a text format for sequences. Each record starts with a > header line, followed by sequence lines. FASTA does not store per-base quality scores. FASTQ is a text format for sequencing reads. Each read uses four lines: a header, the sequence, a + separator, and a quality string with one character per base. FASTQ is used for raw reads. FASTA is used for reference sequences or assembled contigs.
VCF (Variant Call Format) stores variants such as single-nucleotide changes and small insertions or deletions. BAM and CRAM are binary aligned-read formats. GFF and GTF are feature annotation formats with attribute columns. IGV can display BED, BEDGraph, GFF, GTF, VCF, BAM, CRAM, bigBed, and bigWig tracks against a reference genome.
Genomic compression tools support these formats directly. Genozip, for example, lists FASTQ, FASTA, SAM/BAM/CRAM, VCF, and GVF among its supported formats [3]. Automated workflows commonly move from FASTQ or CRAM into a VCF after alignment and variant calling [4]. BED sits downstream of those steps as a compact interval track. Genomic data models also mediate between these formats so that one analysis system can read data produced by another [5]. Tab-separated genomic formats such as tbg show that plain text tables remain a practical exchange layer in genomics [6].
Before You Load: Prepare the BED File and Genome
Prepare four things before you open IGV:
- IGV desktop installed and able to launch.
- A BED file with the correct number of columns.
- The genome build that the BED coordinates refer to, such as hg38, hg19, or mm10.
- Optional htslib tools (
bgzipandtabix) if the BED file is large.
IGV runs on Java. If IGV launches but stalls on a large file, the Java heap may be too small. A indexed file or a binary bigBed file is a better fix than repeatedly raising memory.
Check the File Is Not Empty
Run a line count and exclude comment lines that start with #:
wc -l example.bed
grep -vc '^#' example.bed
The first command prints the total line count. The second prints the number of data lines. If the second number is zero, IGV has nothing to draw. A track may appear with a message such as Feature file has no features.
Check Column Count and Tabs
BED columns must be separated by tabs, not spaces. Run:
awk -F'\t' 'NF < 3 {print "Line " NR " has " NF " fields"}' example.bed
Expected output is no output. If the command prints line numbers, those lines have fewer than three tab-separated fields. A common cause is a file saved with spaces between columns. For a simple BED3 file, convert runs of spaces to tabs with:
tr -s ' ' '\t' < example.bed > example.tabs.bed
Do not use that conversion on a BED file whose name column contains spaces. Fix those files in a spreadsheet or with a targeted script that preserves the name field.
Check Start and End Coordinates
Run a coordinate check:
awk -F'\t' 'BEGIN{OFS="\t"} $2 !~ /^[0-9]+$/ || $3 !~ /^[0-9]+$/ {print "Non-numeric coordinate at line " NR; next} $2 < 0 || $3 <= $2 {print "Invalid interval at line " NR ": " $0}' example.bed
Expected output is no output. A negative start or an end that is less than or equal to the start will produce an invalid interval. IGV may reject the line or draw a zero-width feature.
Check Chromosome Names
List the chromosome names in the BED file:
cut -f1 example.bed | sort -u
Expected output is a short list such as chr1, chr2, chr3, and so on. Compare that list with the genome selected in IGV. Many BED files use chr1, while some references use 1. If the BED file lacks the chr prefix and the IGV genome uses it, add the prefix:
awk 'BEGIN{OFS="\t"} {if ($1 !~ /^chr/) $1="chr"$1; print}' example.bed > example.chr.bed
If the BED file has the prefix and the genome does not, remove it instead. The important rule is one consistent naming scheme across the BED file and the selected genome.
Remove Browser Track Lines
Some BED files begin with browser configuration lines such as track or browser. IGV tolerates these in many versions, but a shared analysis file is cleaner without them. Remove them if IGV reports a parse error on the first line:
grep -v -E '^(track|browser)' example.bed > example.clean.bed
Fix Windows Line Endings
Windows carriage returns can appear as stray characters at the end of the last column. Check with:
file example.bed
If the output mentions CRLF line terminators, convert the file:
dos2unix example.bed
Sort and Index Large BED Files
IGV can load a small BED file directly. For a BED file with millions of intervals, an index lets IGV fetch only the visible region instead of reading the whole file. Indexed genomic files are designed for exactly this kind of in-situ query and interactive exploration [7].
Sort the BED file by chromosome and start position:
sort -k1,1 -k2,2n example.clean.bed > example.sorted.bed
Compress with bgzip, which is block gzip, then build a tabix index:
bgzip -c example.sorted.bed > example.sorted.bed.gz
tabix -p bed example.sorted.bed.gz
Expected output is two files:
example.sorted.bed.gz
example.sorted.bed.gz.tbi
Load the .bed.gz file in IGV. IGV detects the .tbi index and uses it for region queries. If bgzip or tabix is missing, install htslib:
conda install -c bioconda htslib
Compression gains vary by file type, so check the final size rather than assuming a fixed ratio [8].
Optional: Convert to bigBed
For very large interval sets, bigBed is an indexed binary format that IGV can read efficiently. You need a chromosome sizes file. If you have the reference FASTA, create the sizes file with samtools:
samtools faidx reference.fa
cut -f1,2 reference.fa.fai > chrom.sizes
bedToBigBed example.sorted.bed chrom.sizes example.bb
Expected output is example.bb. Load that file in IGV instead of the text BED file. The tradeoff is that bigBed is not human-readable. Keep the text BED as the source record.
Step-by-Step: Visualize a BED File in IGV
This is the practical GUI walkthrough for how to visualize BED files in IGV step by step. The same steps work for a small BED3 file and for an indexed BED file.
- Launch IGV desktop. Wait for the genome drop-down to populate. If the window opens with a default genome, do not load the BED file yet.
- Select the matching genome. Use the genome drop-down at the top left. Choose hg38 for human hg38 coordinates, hg19 for human hg19 coordinates, or mm10 for mouse mm10 coordinates. If the BED file uses a custom assembly, choose
Genomes > Load Genome from Fileand select the reference FASTA. The genome build must match the BED coordinates. A correct BED file on the wrong genome will produce features on the wrong chromosome or no features at all.
- Load the BED file. Use
File > Load from Fileand selectexample.bedorexample.sorted.bed.gz. You can also drag the file onto the IGV window. If the file is indexed, load the.bed.gzfile, not the.tbifile. IGV uses the index automatically.
- Find the new track. The track appears in the track panel, usually below the gene annotation track. The track label is the file name unless the BED file supplies a name. If the track is present but empty, the view is probably outside the data range or the feature visibility window is too small.
- Navigate to a locus. Type a gene name or a coordinate range into the search box. For a coordinate range, use
chr1:1000-2000. Press Enter. IGV moves the viewport to that region. If you do not know where the features are, useView > Fit to Windowafter selecting the track, or search for a gene you expect the BED file to overlap.
- Adjust the track height. Right-click the track label and choose
Change Track Height. Increase the height until the feature labels and block structure are readable. A height of 60 to 100 pixels is usually enough for a BED12 gene model. A height of 20 to 40 pixels is enough for a peak track.
- Set the feature visibility window. Right-click the track and choose
Set Feature Visibility Window. If the value is small, features disappear when you zoom out. Set it to-1to remove the limit for that track. This setting matters for BED tracks with many small intervals. Without it, a zoomed-out view can look empty even though the file contains data.
- Color the features. If the BED file has an
itemRgbvalue in column 9, right-click the track and use the color options to applyitemRgb. If the file has no color column, use the track color setting to choose a single color. For BED6 files, the strand column can be used to draw directional arrows on features.
- Check alignment with the gene annotation. Load or enable the built-in gene annotation track. Navigate to a gene you know is in the BED file. The BED feature should sit on the expected gene body or promoter. If the feature is on a different chromosome, the genome build or chromosome naming is wrong. If the feature is shifted by one base, remember the BED 0-based start versus the IGV 1-based display.
- Save the view. Use
File > Save Sessionto write an.igvsession file. The session records the genome, the loaded tracks, the viewport, and the track settings. UseFile > Save Screenshotto write a PNG image for a figure or a lab notebook. A saved session is more useful than a screenshot because it can be reopened and adjusted.
A small worked example helps. Create a file named example.bed with these two tab-separated lines:
chr1 1000 1200 PeakA 500 + 1000 1200 255,0,0
chr1 1500 1600 PeakB 200 - 1500 1600 0,0,255
Load the file on hg38, search for chr1:900-1700, and set the track height to 60 pixels. You should see two features. PeakA is red and PeakB is blue because column 9 supplies itemRgb. PeakA points right and PeakB points left because column 6 supplies the strand. If you see one feature or none, check the tab characters and the chromosome name first.
Command-Line and Batch Workflow for Reproducible Views
The GUI is fine for exploration. For a figure that you need to regenerate, use an IGV batch script. A batch script is a text file of IGV commands. IGV runs the commands in order, then exits.
Create commands.txt:
new
genome hg38
load /absolute/path/example.sorted.bed.gz
goto chr1:900-1700
snapshot /absolute/path/example_view.png
exit
Run IGV in batch mode:
igv.sh -b commands.txt
On Windows, use:
igv.bat -b commands.txt
Expected output is a new IGV window that loads the genome, loads the BED track, moves to the locus, writes example_view.png, and exits. If IGV is already running, close it first or use a separate IGV instance. Use absolute paths in batch scripts because the working directory of the launcher may differ from the directory where you created the script.
| Batch command | Purpose | Example |
|---|---|---|
new | Start a fresh IGV session | new |
genome | Select the reference genome | genome hg38 |
load | Load a BED, BAM, VCF, or other track | load /data/example.bed.gz |
goto | Move the viewport to a locus | goto chr1:900-1700 |
snapshot | Write a PNG image of the current view | snapshot /data/view.png |
exit | Close IGV after the commands finish | exit |
Batch scripts are useful for three situations. They reproduce a figure after a track is updated. They create the same view for many BED files. They document the exact genome and locus used for a screenshot. Interactive visualization is powerful because viewers can query and share data rather than rely on static images [9]. A batch script adds reproducibility to that interactive workflow.
Tips for Clean BED Visualization in IGV
These tips prevent the most common display problems and make the track easier to interpret.
Use an index for large files. A plain BED file is read into memory. An indexed .bed.gz file lets IGV query only the visible region. This is the same principle behind indexed genomic file servers that support interactive exploration without downloading or loading an entire file [7].
Use bigBed for very large interval sets. A bigBed file is binary and indexed. It is faster than a text BED file for whole-genome browsing. Keep the text BED as the editable source and generate the bigBed as a derived file.
Keep chromosome naming consistent. Decide whether the project uses chr1 or 1 and apply that rule to every BED, VCF, and BAM file. Mixed naming is the most common reason a track loads but shows nothing. A quick check with cut -f1 example.bed | sort -u catches the problem before IGV sees it.
Keep the genome build in the file name. Name files sample_hg38_peaks.bed rather than peaks.bed. The genome build is metadata that IGV cannot infer from the BED file. A file name that records the build prevents the wrong-genome mistake.
Use BED12 for gene models. A BED6 file can show a feature and a strand. A BED12 file can show exons, introns, and coding regions. If the BED file comes from a gene annotation conversion, check that blockStarts are relative to the feature start, not absolute chromosome coordinates.
Use itemRgb for categorical colors. Column 9 accepts values such as 255,0,0 for red and 0,0,255 for blue. Use 0 when you want the track default. A BED file with many categories can encode a simple color scheme without a separate sample sheet.
Set the feature visibility window before you conclude the track is empty. A BED track can look blank at whole-genome scale because the visibility window is smaller than the view. Set the window to -1 for the track, then zoom out. If the features appear, the file was fine.
Use track height to separate dense tracks. A peak track with hundreds of intervals needs more vertical space than a six-feature gene model. Right-click the track label and change the height. A crowded track is harder to read than a tall track.
Load tracks in a deliberate order. Put the gene annotation track at the top, then the BED track, then BAM or VCF tracks. IGV draws tracks from top to bottom in the order they appear. A consistent order makes screenshots easier to compare.
Save a session for every figure. An .igv session records the genome, tracks, locus, and track settings. A PNG records only the pixels. The session is the reproducible artifact.
Test with a small subset first. Extract the first 100 lines of a large BED file and load that subset. If the subset displays correctly, the problem is scale or indexing. If the subset fails, the problem is format.
Common Mistakes and Limitations
Most BED visualization failures come from a short list of causes. The table below maps the symptom to the likely cause and the fix.
| Symptom or message | Likely cause | Fix | |
|---|---|---|---|
Feature file has no features | Empty file, all lines commented, or wrong path | Run grep -vc '^#' example.bed and confirm the path | |
Invalid BED file with a line number | Fewer than three columns, spaces instead of tabs, or non-numeric coordinates | Run the awk column and coordinate checks, then fix the line | |
| Track loads but no features appear | Viewport outside the data, or feature visibility window too small | Search a known locus, use View > Fit to Window, set visibility window to -1 | |
| Features appear on the wrong chromosome | Genome build mismatch or chr prefix mismatch | Select the matching genome, check `cut -f1 example.bed | sort -u` |
[E::hts_idx_push] Chromosome blocks not continuous | BED file was not sorted before tabix | Sort with sort -k1,1 -k2,2n, then bgzip and tabix again | |
bgzip: command not found | htslib is not installed | Install htslib with conda or the system package manager | |
tabix: command not found | htslib is not installed | Install htslib, then rerun tabix -p bed | |
java.lang.OutOfMemoryError: Java heap space | BED file is too large for the Java heap | Use bgzip plus tabix or bigBed, and raise the heap only as a secondary fix | |
| BED12 blocks look wrong | blockStarts were written as absolute coordinates | Recalculate each block start as blockStart - chromStart | |
| First line fails to parse | track or browser line at the top | Remove the line with `grep -v -E '^(track | browser)'` |
| Last column has a stray character | Windows CRLF line endings | Run dos2unix example.bed |
The first mistake is selecting the wrong genome build. A BED file does not carry its genome build in a machine-readable header. IGV trusts the genome you select. If the BED file is hg19 and IGV is set to hg38, the features can appear on the right chromosome but at the wrong coordinates. The fix is to select the correct genome or convert the coordinates with a liftover tool before loading.
The second mistake is confusing BED coordinates with IGV coordinates. BED starts at 0. IGV displays 1-based positions. A feature that starts at BED position 100 is drawn starting at IGV position 101. This one-base difference is expected. It becomes a real error when a BED file was created by hand with 1-based starts. In that case, every feature is shifted by one base. Check a known feature against the gene annotation track before you publish the view.
The third mistake is using spaces instead of tabs. A BED file that looks aligned in a text editor can still be space-delimited. IGV expects tabs. The awk column check catches this because a space-delimited line has one field, not three or more.
The fourth mistake is indexing an unsorted file. tabix requires chromosome blocks to be continuous. If the BED file alternates between chromosomes, tabix fails with a chromosome block error. Sort by chromosome and start before compressing.
The fifth mistake is loading the .tbi file instead of the .bed.gz file. The .tbi file is an index, not a track. IGV loads the .bed.gz file and finds the index next to it.
The sixth mistake is assuming that a BED file can represent reads. BED is an interval format. It has no base qualities, no mapping positions, and no read sequence. If you need to see read alignments, load a BAM or CRAM file. If you need to see variants, load a VCF file. If you need the reference sequence, load a FASTA file as the genome
Reading the IGV Track Before You Change It
When a BED file loads successfully, IGV presents it as a feature track rather than as an alignment track or a variant track. That distinction matters because the controls that make a BED track readable are not always the same controls that make a BAM or VCF track readable. A BED track has interval features, optional labels, optional strand information, optional colors, and, for BED12, optional block geometry. Before changing colors or height, read the track label and the track menu. Confirm that the track name matches the file you intended to load. Confirm that the track is not collapsed to a few pixels. Confirm that the feature visibility setting is not hiding features at the current zoom level. These checks take less time than reloading the file repeatedly.
The track panel is also a record of what is currently in the session. If two BED files have similar names, rename them before loading so the track labels are unambiguous. If a BED file contains multiple samples or conditions, consider separate files rather than one combined file. Separate tracks can be colored independently, reordered independently, and saved independently in a session. Combined tracks are harder to troubleshoot because a problem with one class of intervals can look like a problem with the whole file. The same principle applies when a BED file is paired with a BAM file. The BED track answers where the intervals are. The BAM track answers what reads support those intervals. Keeping those questions separate in the track panel helps prevent misinterpretation.
A BED track can also be ambiguous because the column count determines how IGV interprets the file. A three-column file is an interval file. A four-column file can be an interval file with a name column, or a BEDGraph file with a numeric value column, depending on the extension and the load settings. A six-column file can carry name, score, and strand. A twelve-column file can carry block structure. The practical lesson is to make the intended format explicit before loading. Use a clear file extension, use the load dialog, and inspect the first few lines in a text editor. If the fourth column is a numeric value that should be drawn as a continuous signal, do not rely on IGV to guess. Name the file with the .bedgraph extension or select BEDGraph explicitly. If the fourth column is a feature label, keep it as a BED file. The interval character of BED is what makes it useful as a compact annotation layer, but that same compactness means small formatting choices change the display [2].
Worked Example: A Peak Track Beside a BAM and Gene Annotation
A common visualization task is to place a peak BED track beside aligned reads and a gene annotation. The goal is not only to see the peak call, but to judge whether the peak sits over a promoter, an exon, an intron, or an intergenic region, and whether the read pileup supports the called interval. Start with a small BED file so the display is easy to inspect. The following example uses tabs between columns:
chr2 5000 5200 PeakX 400 + 5000 5200 200,0,0
chr2 6100 6350 PeakY 250 - 6100 6350 0,0,200
Save this as peaks_demo.bed. Load the matching genome first. If the coordinates are from hg38, select hg38. If they are from another assembly, select that assembly. Do not load the BED file first and choose the genome afterward by guessing. The genome selection determines how the chromosome names and coordinates are interpreted. After loading the BED file, search for chr2:4800-6500. The viewport should display both intervals. If the track is too short to show labels, open the track menu and increase the track height. If labels overlap, either increase the height or turn labels off and rely on the feature color and position.
Now load the BAM file that corresponds to the same sample and the same genome build. The BAM file should have an index next to it. Indexed files are designed for region based queries, which is why a viewer can move around a large alignment file without reading every record at once [7]. Place the BED track above the BAM track so the called intervals sit visually above the read pileup. Use a consistent color for the BED intervals. If the BED file already has itemRgb in column 9, use that color. If not, apply a single track color. Then navigate to a gene annotation track and confirm that the peak positions fall where expected. A peak over a promoter should sit near the annotated transcription start site. A peak over an exon should overlap the exon block. A peak in an intron should fall between exon blocks. If the peak appears on a different chromosome from the expected gene, suspect a genome build or chromosome naming mismatch before suspecting the peak caller.
The comparison is more informative when the BED and BAM tracks are read together. The BED file reports the interval that a caller selected. The BAM file shows the reads that support that interval. A BED interval with no visible read support may reflect a low coverage region, a filtering decision, or a mismatch between samples. A BAM pileup with no BED interval may reflect a region that did not pass the caller's criteria. Neither track alone tells the whole story. This is the practical value of interactive visualization: the viewer can move between interval level evidence and read level evidence without rebuilding a static figure [9].
Worked Example: BED12 Gene Model and Block Geometry
BED12 is the format to use when a single feature needs to represent multiple blocks, such as exons separated by introns. The fields are easy to misread because blockStarts are not absolute chromosome coordinates. They are offsets from the feature start. A worked example makes the arithmetic visible. Suppose a gene model starts at chromosome position 5000 in BED coordinates and has three blocks: one from 5000 to 5100, one from 5300 to 5450, and one from 5700 to 5800. The feature start is 5000. The first block starts at offset 0. The second block starts at 5300 minus 5000, which is 300. The third block starts at 5700 minus 5000, which is 700. The block sizes are 100, 150, and 100. A BED12 line with a name, a score, a strand, thick start, thick end, color, block count, block sizes, and block starts looks like this:
chr3 5000 5800 GeneModelDemo 0 + 5000 5800 120,80,0 3 100,150,100 0,300,700
Load this file on the genome that matches the coordinates, then search for chr3:4900-5900. In IGV, the feature should appear as three blocks connected by thin intron lines. The thick region is controlled by thickStart and thickEnd. If the thick region covers the whole feature, the display may look like a solid block rather than a gene model with coding and noncoding portions. If the blocks appear in the wrong positions, the first field to check is blockStarts. A common mistake is to place absolute chromosome coordinates in column 12. That produces offsets far beyond the feature length,
Sources
- Visualizing and interpreting cancer genomics data via the Xena platform
- Common File Formats.
- Genozip: a universal extensible genomic data compressor
- ILIAD: a suite of automated Snakemake workflows for processing genomic data for downstream applications
- Processing of big heterogeneous genomic datasets for tertiary analysis of Next Generation Sequencing data
- tbg - a new file format for genomic data
- Epiviz File Server: Query, transform and interactively explore data from indexed genomic files
- Compression Performance Analysis of Different File Formats
- Microreact: visualizing and sharing data for genomic epidemiology and phylogeography