How to Index a FASTA File: Using samtools faidx
By Dr. Zubair Khalid, DVM, MS, PhD ·

You will be able to build a .fai index for a plain or bgzipped FASTA file, fetch any region by name and coordinates, confirm that the index matches the sequence, and recognize the errors that stop indexing. You need a FASTA file, a terminal, and samtools 1.x. For compressed input you also need bgzip, which ships with htslib and is usually installed alongside samtools.
The command is short. The details around it are where most problems live. A stale index, a Windows line ending, a duplicated sequence name, or a plain gzip file can produce wrong sequence or a failed run without an obvious warning. This guide walks through the whole workflow, including the index format itself, so you can check the result rather than assume it.
What a FASTA Index Actually Is
FASTA is a text format for biological sequences. Each record starts with a header line that begins with >. The first whitespace-delimited word after > is the sequence name. The following lines contain the sequence, usually wrapped at a fixed width. A reference genome FASTA might contain chromosomes, scaffolds, or contigs. A protein FASTA contains amino acid sequences. A transcript FASTA contains spliced or unspliced RNA sequences.
An index for a FASTA file is a small companion file that records where each sequence starts in the byte stream. The standard index created by samtools faidx is a plain-text file named after the FASTA with .fai appended. For reference.fa, the index is reference.fa.fai. It does not contain sequence. It contains coordinates.
The practical value is random access. Without an index, a tool that needs chr7:117,199,000-117,200,000 must scan from the beginning of the file until it reaches chromosome 7, then scan again to the requested position. With an index, the tool reads one line from the .fai, computes a byte offset, seeks directly to that offset, and reads only the requested bases. The same principle appears throughout bioinformatics. STABIX, for example, was built because finding all SNVs in a p-value range in a standard bgzip and Tabix file would otherwise require decompressing and scanning the whole file [1]. BigWig and BigBed files use indexes so that only the data needed for the current browser view is transmitted rather than the entire file [2]. A portable JavaScript VCF reader uses byte-range requests and binary search to fetch partial content without downloading the whole file [3]. The .fai is the FASTA version of that idea.
An index also lets many tools start work without reading the entire reference. Aligners may have their own index formats, but variant callers, visualization tools, and region query utilities often expect a .fai. If the file is missing, some tools build it automatically. Others fail with a message about a missing index. Building it once, explicitly, avoids surprises.
The .fai is not a validation certificate. It does not checksum the sequence, record the assembly name, or prove that the bases are correct. It only describes the layout of the text file. If the FASTA changes and the .fai does not, the index becomes a map to the wrong bytes.
FASTA vs FASTQ and Other Indexed Formats
FASTA and FASTQ are both text formats for sequences. They serve different purposes. FASTA stores sequence only. FASTQ stores sequence plus a per-base quality score. A FASTQ record has four lines: a header beginning with @, the sequence, a separator beginning with +, and a quality string of the same length as the sequence. The quality string encodes Phred scores. FASTQ is the usual output of a sequencing instrument. FASTA is the usual format for a reference genome, a transcript set, or a protein set.
Quality scores are the difficult part of FASTQ compression and random access. LCQS notes that quality scores are hard to compress and that random access requires a fine-grained index structure, with tradeoffs in compression speed and index size [4]. SCALCE notes that FASTQ data have a limited alphabet and high similarity among reads, which general-purpose gzip does not exploit [5]. Those concerns do not apply to a reference FASTA in the same way. A reference FASTA is a small number of long sequences with a four-letter alphabet and no quality values. Its index is correspondingly simple.
Common bioinformatics file formats use different index types:
| Format | Content | Typical index | Created by |
|---|---|---|---|
| FASTA | nucleotide or protein sequence | .fai | samtools faidx |
| FASTQ | reads plus quality scores | no universal index | tool-specific |
| BAM | aligned reads | .bai or .csi | samtools index |
| CRAM | compressed aligned reads | .crai | samtools index |
| VCF | variants | .tbi or .csi | tabix or bcftools index |
| BED, GFF, GTF | intervals and annotations | .tbi or .csi | tabix |
| BigWig, BigBed | signal or intervals | internal binary index | UCSC utilities |
The table matters because the word "index" is overloaded. samtools faidx does not create a BAM index, a variant index, or an aligner index. samtools index does not index a FASTA. bwa index creates a set of files for alignment, not for region retrieval. tabix indexes bgzipped tab-delimited files, not FASTA. Mixing these up is a common source of wasted time.
The scale of FASTA data is another reason indexes matter. A collection of 1,092 human diploid genomes is about 6.7 TB as uncompressed FASTA, which is why specialized compression tools exist [6]. Most working reference files are far smaller, but a human reference still has about 3.1 billion bases. Scanning it repeatedly for every region query is wasteful. The .fai turns those queries into seeks.
Before You Start
You need three things:
- A FASTA file with a
.fa,.fasta,.fna, or similar extension. The extension does not affect indexing. - A working samtools installation, version 1.x. Check it before building anything.
- Write permission in the directory that contains the FASTA, because the index is written next to the input by default.
Check the version:
samtools --version
Expected output looks like this, though your exact version may differ:
samtools 1.19
Using htslib 1.19
Copyright (C) 1993-2024 [Genome Research](/blog/guides/genome-research) Ltd.
If the command is not found, install samtools from your package manager or from Bioconda. On a cluster, load the module first. The commands in this guide use the standard samtools faidx interface that has been stable for years.
Check the file before indexing:
ls -lh reference.fa
head -n 4 reference.fa
grep -c '^>' reference.fa
Expected output for a small reference might look like this:
-rw-r--r-- 1 user group 3.1G Nov 10 09:14 reference.fa
>chr1
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
25
The grep -c '^>' count is the number of records. It should match the number of data rows in the .fai after indexing, unless the FASTA contains duplicate names or empty records.
If the FASTA is compressed, decide now whether it is BGZF-compressed. A plain gzip file is not suitable for samtools faidx. BGZF is the block gzip format used by BAM, VCF, and bgzip. It supports random access because the file is divided into independently decompressible blocks. A plain gzip file is a single continuous stream and cannot be seeked into efficiently.
Index a FASTA File with samtools faidx: Step by Step
This numbered walkthrough is the core workflow. Run the commands from the directory that contains your FASTA, or adjust the paths.
Step 1: Inspect the FASTA for obvious layout problems
A FASTA can be valid text and still be a poor indexing candidate. Check that every record has sequence data, that names are unique, and that sequence lines within a record are not wildly inconsistent.
awk '/^>/{if (name != "") print name, length(seq); name=$1; seq=""; next}{seq=seq$0}END{if (name != "") print name, length(seq)}' reference.fa | head
Expected output:
>chr1 248956422
>chr2 242193529
>chr3 198295559
This command loads one sequence at a time into memory. It is fine for a quick check on a small file. For a 3 GB human reference, it will use several gigabytes of RAM because it concatenates each chromosome. A lighter check is to look at the first few records with head and to count headers with grep.
Check for duplicate names:
grep '^>' reference.fa | awk '{print $1}' | sort | uniq -d | head
No output means no duplicates. If you see names, fix them before indexing.
Step 2: Verify samtools is available
samtools --version
You need a 1.x release. The exact patch version rarely matters for basic FASTA indexing. If you use a very old release, upgrade. The .fai format is stable, but error messages and BGZF support have improved.
Step 3: Compress with bgzip if you want a compressed FASTA
Skip this step for a plain FASTA. If you want compressed storage and random access, use bgzip, not gzip.
bgzip -k reference.fa
ls -lh reference.fa.gz
The -k flag keeps the original file. The result is reference.fa.gz in BGZF format. To use multiple threads:
bgzip -@ 4 -k reference.fa
Do not do this:
gzip -c reference.fa > reference.fa.gz
That produces a plain gzip file. samtools faidx may fail with a BGZF-related error when it tries to read it. If you already have a plain gzip file, decompress it and recompress with bgzip.
gzip -dc reference.fa.gz > reference.fa
bgzip -k reference.fa
Step 4: Build the index
For a plain FASTA:
samtools faidx reference.fa
For a bgzipped FASTA:
samtools faidx reference.fa.gz
A successful run prints nothing. That silence is normal. Check the files:
ls -lh reference.fa.fai
For the compressed case:
ls -lh reference.fa.gz.fai reference.fa.gz.gzi
Expected output:
-rw-r--r-- 1 user group 1.2K Nov 10 09:20 reference.fa.gz.fai
-rw-r--r-- 1 user group 8.4M Nov 10 09:20 reference.fa.gz.gzi
The .fai is small. The .gzi is larger because it maps compressed blocks to uncompressed offsets. Both are needed for random access to a bgzipped FASTA.
Step 5: Inspect the .fai
head -n 5 reference.fa.fai
Expected output:
chr1 248956422 80 60 61
chr2 242193529 123456789 60 61
chr3 198295559 246913578 60 61
chr4 190214555 370209137 60 61
chr5 181538259 493728291 60 61
The columns are name, length, offset, bases per line, and bytes per line. The offset and line values depend on the header lengths and line wrapping in your file. Your numbers will differ.
Step 6: Fetch a region
samtools faidx reference.fa chr1:1-60
Expected output:
>chr1:1-60
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
The output header includes the region you requested. The sequence is wrapped at 60 bases per line by default. Coordinates are 1-based and inclusive. chr1:1-60 returns 60 bases. chr1:1-1 returns one base.
Fetch multiple regions in one command:
samtools faidx reference.fa chr1:1-60 chr2:1-60
Fetch a whole chromosome:
samtools faidx reference.fa chr1
Step 7: Check the index against the file
Print the length recorded in the .fai for a sequence:
awk '$1=="chr1"{print $2}' reference.fa.fai
Expected output:
248956422
Ask samtools for the same length directly:
samtools faidx -n reference.fa chr1
Expected output:
248956422
The two numbers must match. If they do not, the index is stale or the FASTA layout changed.
Count records and index rows:
grep -c '^>' reference.fa
wc -l < reference.fa.fai
For a clean file, the counts match. Duplicate names or empty sequences can cause a mismatch.
Step 8: Use the index in downstream tools
Many tools find the .fai automatically when it sits next to the FASTA. Examples:
samtools view -T reference.fa aligned.bam
samtools mpileup -f reference.fa aligned.bam
bcftools mpileup -f reference.fa aligned.bam
GATK and Picard-style tools often require both a .fai and a sequence dictionary (.dict). Create the dictionary with:
samtools dict -o reference.dict reference.fa
The .fai and .dict are different files. The .fai describes byte layout for random access. The .dict describes sequence names, lengths, assembly metadata, and checksums for tools that need a formal sequence dictionary.
Reading the .fai Format: A Worked Example
The .fai has five tab-separated columns. Every column has a precise meaning.
| Column | Name | Meaning |
|---|---|---|
| 1 | NAME | Sequence name, the first word after > |
| 2 | LENGTH | Number of bases or residues in the sequence |
| 3 | OFFSET | Zero-based byte offset of the first base |
| 4 | LINEBASES | Number of bases per sequence line, excluding the newline |
| 5 | LINEWIDTH | Number of bytes per sequence line, including the newline |
Consider this small FASTA:
>chr1
ACGTACGTAC
GTACGTACGT
AC
>chr2
TTTT
AAAA
The byte layout is:
>chr1\nis 6 bytes, so the first base ofchr1starts at byte offset 6.- The first
chr1sequence line is 10 bases plus a newline, so 11 bytes. - The second line is also 11 bytes.
- The third line is 2 bases plus a newline, so 3 bytes.
chr1length is 10 + 10 + 2 = 22.>chr2\nis 6 bytes, starting after 6 + 11 + 11 + 3 = 31 bytes, so the first base ofchr2starts at byte offset 37.chr2has two lines of 4 bases, each 5 bytes including the newline.chr2length is 8.
The resulting .fai is:
chr1 22 6 10 11
chr2 8 37 4 5
To fetch chr1:5-12, a tool computes the byte position of base 5:
byte = offset + floor((start - 1) / LINEBASES) * LINEWIDTH + ((start - 1) % LINEBASES)
byte = 6 + floor(4 / 10) * 11 + (4 % 10)
byte = 6 + 0 + 4
byte = 10
Byte 10 is the fifth base of the first sequence line. The tool then reads across line breaks until it has 8 bases. The output is:
>chr1:5-12
ACGTACGT
That formula is the reason inconsistent line lengths break an index. If one line in the middle of a sequence is shorter than the first line, the offset calculation lands on the wrong byte. The sequence after that point is shifted. The tool may return the wrong bases, or it may stop with a line length error.
The formula also explains why the last line can be shorter. The index records the line width from the full lines. The final line is handled by the length field. A short final line is normal. A short middle line is not.
Key samtools faidx Options
Most users only need the bare samtools faidx reference.fa command. The same subcommand also fetches regions and has options that help with batch work.
| Option | What it does | Example |
|---|---|---|
| no region | Builds or rebuilds the .fai | samtools faidx reference.fa |
region | Fetches a 1-based inclusive region | samtools faidx reference.fa chr1:100-200 |
-o FILE | Writes sequence output to a file | samtools faidx -o out.fa reference.fa chr1:1-60 |
-n | Prints the sequence length instead of the sequence | samtools faidx -n reference.fa chr1 |
-r FILE | Reads regions from a file, one per line | samtools faidx -r regions.txt reference.fa |
-c | Continues after a region fails | samtools faidx -c reference.fa chr1 chr99 |
-i | Reverse-complements the output | samtools faidx -i reference.fa chr1:1-60 |
-m TYPE | Adds a strand marker to output headers | samtools faidx -m sign reference.fa chr1:1-60 |
A region file is useful for batch extraction. Each line contains one region in the same syntax you would use on the command line.
chr1:1-60
chr2:1000-1060
chrX:155000000-155000060
Run:
samtools faidx -r regions.txt reference.fa
If one region is missing, the default behavior is to stop. The -c option lets the command continue and report the failure for that region. Use it when you are extracting many regions and want the successful ones.
The -i option is handy when you need the reverse complement without writing a separate script. The output header still identifies the region. The -m option controls how the strand is marked in the header. Check the SAMtools manual page for the exact marker style in your version.
Compressed FASTA: bgzip, .gzi, and Random Access
A compressed FASTA is common for reference archives and for distribution. The compression must be BGZF. BGZF is a series of gzip blocks with a virtual offset scheme. Each block can be decompressed independently. The .gzi index records the compressed and uncompressed offsets of those blocks. The .fai records the sequence layout in the uncompressed stream.
Workflows that use BGZIP and an index are standard across bioinformatics. GAF annotations, for example, are sorted, BGZIP-compressed, and indexed with HTSlib and tabix so that annotations overlapping a subgraph can be extracted quickly [7]. The same block compression model supports partial reads in web applications, where byte-range requests fetch only the needed chunks [3]. BigWig and BigBed take a related approach for browser display, transmitting only the data needed for the current view [2].
Build a compressed FASTA index in two commands:
bgzip -k reference.fa
samtools faidx reference.fa.gz
The output files are:
reference.fa.gz
reference.fa.gz.fai
reference.fa.gz.gzi
Fetch a region directly from the compressed file:
samtools faidx reference.fa.gz chr1:1-60
Expected output:
>chr1:1-60
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
Do not use gzip -9 and expect random access. A plain gzip stream has no block boundaries that a reader can seek into. If you see an error such as [E::bgzf_read_block] Invalid BGZF header at offset 0, the file is probably plain gzip or another non-BGZF compression. Decompress and recompress with bgzip.
You can test whether a file is BGZF with the file command on many systems:
file reference.fa.gz
Expected output includes a phrase such as:
reference.fa.gz: Blocked GNU Zip Format (BGZF; gzip compatible), block length 12345
The exact wording depends on your file version. The key phrase is BGZF.
Keep both index files together with the compressed FASTA. If you move the FASTA without the .fai and .gzi, region queries will fail or will rebuild a new index. If you copy only the .fai, compressed random access will not work because the block map is missing.
Indexing Many FASTA Files Safely
Batch indexing is simple, but a few safeguards prevent half-indexed files and silent failures. Use a loop with strict error handling.
#!/usr/bin/env bash
set -euo pipefail
for f in "$@"; do
if [[ ! -s "$f" ]]; then
echo "missing or empty file: $f" >&2
exit 1
fi
echo "indexing $f"
samtools faidx "$f"
echo "done $f"
done
Run it with a shell glob:
./index_fastas.sh *.fa *.fasta
The set -euo pipefail line stops the script on the first error. That is usually what you want. If one file has a line length problem, you want to know before a downstream pipeline starts.
For parallel indexing, use xargs with a modest number of processes:
printf '%s\n' *.fa | xargs -n 1 -P 4 samtools faidx
Four processes is a reasonable default on a laptop or small server. The index build is I/O-heavy, so more processes may not help. On a shared cluster, check the queue limits before using parallelism.
A simple loop without error handling is fine for a one-off:
for f in *.fa; do
[ -e "$f" ] || continue
samtools faidx "$f"
done
The [ -e "$f" ] || continue guard prevents the loop from trying to index a literal *.fa when no files match.
If you have both plain and compressed FASTA files, handle them by extension:
for f in *.fa *.fa.gz; do
[ -e "$f" ] || continue
case "$f" in
*.gz) samtools faidx "$f" ;;
*) samtools faidx "$f" ;;
esac
done
The same command works for both because samtools faidx detects BGZF input. The important difference is that compressed input also produces a .gzi.
How to Check That the Index Is Correct
Do not stop at the absence of an error message. Run at least two checks.
First, fetch the first bases and compare them with the FASTA text.
samtools faidx reference.fa chr1:1-10
Expected output:
>chr1:1-10
NNNNNNNNNN
Second, fetch the last base of a chromosome and confirm that it is a real base, not an empty record.
samtools faidx reference.fa chr1:248956422-248956422
Expected output:
>chr1:248956422-248956422
N
Third, compare the length in the .fai with the length reported by samtools faidx -n.
awk '$1=="chr1"{print $2}' reference.fa.fai
samtools faidx -n reference.fa chr1
Both should print the same number.
Fourth, check for duplicate sequence names in the index.
cut -f1 reference.fa.fai | sort | uniq -d
No output means the names are unique.
Fifth, check that the index is newer than the FASTA.
if [ reference.fa.fai -nt reference.fa ]; then
echo "index is newer than FASTA"
else
echo "index may be stale"
fi
A newer index is not proof of correctness, but an older index is a red flag. If you edited the FASTA, rebuilt it, or replaced it with a different assembly, rebuild the index.
Sixth, compare record counts.
grep -c '^>' reference.fa
wc -l < reference.fa.fai
The counts should match for a clean file. If the .fai has fewer rows, some records may be empty. If it has more rows, something is wrong with the index or the count.
Using the .fai with Downstream Tools
The .fai is a shared contract between many tools. A few common uses:
samtools view -T reference.fauses the FASTA and its index when reading CRAM or when a BAM header references sequences.samtools mpileup -f reference.faneeds the reference for pileup.bcftools mpileup -f reference.faneeds the reference for variant calling.bedtools getfasta -fi reference.facan use the.faifor interval extraction.- Genome browsers such as IGV use the
.faifor region display. - GATK requires a
.faiand a.dictfor reference-backed walkers.
The .fai also makes direct lookups fast in shell scripts. A small wrapper can extract a promoter, an exon, or a variant neighborhood without loading the whole chromosome.
samtools faidx reference.fa chr17:43044295-43125364
That is the BRCA1 region on a commonly used human reference. The exact coordinates depend on the assembly. Always confirm the assembly and chromosome naming before using hard-coded coordinates.
Chromosome naming is a frequent integration issue. Some references use chr1, others use 1. Some use chrM, others use MT. The .fai records exactly what is in the FASTA. A BAM or VCF that uses a different naming convention will not match. Check the first column of the .fai against the sequence names in your other files.
head -n 3 reference.fa.fai | cut -f1
Expected output:
chr1
chr2
chr3
If your alignments use 1, 2, 3, you need a reference with matching names or a rename step. Do not rename chromosomes casually after alignment. Rebuild the affected files or use a conversion utility that updates all linked files.
Common Mistakes and Limitations
Inconsistent line lengths inside a sequence
This is the most common indexing failure. samtools faidx expects each sequence to have a consistent line width, with only the final line allowed to be shorter. A middle line that is shorter or longer breaks the offset calculation.
Typical error:
[E::fai_build_core] Different line length in sequence 'chr1'.
Fix the wrapping so that every line except the last has the same length. A simple reformat with awk can rewrite the FASTA with a fixed width:
awk '/^>/{if (seq != "") print seq; print; seq=""; next}{seq=seq$0}END{if (seq != "") print seq}' reference.fa > reference.wrapped.fa
This command concatenates each record and prints it as one long line. That is valid FASTA and avoids line length variation entirely. For very long chromosomes, a single-line record is fine for indexing, though some downstream tools prefer wrapped lines. A fixed width of 60 or 80 is conventional.
Windows CRLF line endings
A FASTA transferred from a Windows system may have \r\n line endings. The extra carriage return changes byte counts and can produce wrong offsets or a line length error. Convert to Unix line endings before indexing:
sed 's/\r$//' reference.fa > reference.unix.fa
mv reference.unix.fa reference.fa
Then rebuild the index.
Blank lines and comment lines
Blank lines inside a record confuse the line width calculation. Comment lines beginning with ; are allowed in some FASTA dialects but are not handled consistently by all tools. Remove blank lines and avoid comment lines in reference FASTA.
grep -v '^$' reference.fa > reference.clean.fa
Duplicate sequence names
Duplicate names do not always stop the index build. They create duplicate rows in the .fai. A region query may return the first match, and downstream tools may silently use the wrong record. Check for duplicates before indexing.
grep '^>' reference.fa | awk '{print $1}' | sort | uniq -d
Rename duplicates or remove the redundant records.
Spaces and descriptions in headers
The sequence name is the first word after >. A header such as >chr1 Homo sapiens chromosome 1 is indexed as chr1. The description is not part of the name. This is normal FASTA behavior, but it surprises users who try to fetch the full header. Use the first token in region queries.
Plain gzip instead of BGZF
A .gz extension does not guarantee BGZF. If the file was compressed with gzip, samtools faidx cannot build a usable random-access index. You may see a BGZF header error. Recompress with bgzip.
A stale index after editing the FASTA
The .fai is not updated automatically when the FASTA changes. If you add a chromosome, trim a sequence, or replace the file with a new assembly, rebuild the index. When in doubt, delete the old index and rebuild.
rm -f reference.fa.fai reference.fa.gz.fai reference.fa.gz.gzi
samtools faidx reference.fa
Empty sequences
A header followed immediately by another header creates an empty record. Some tools reject it. Some index it with length zero. Downstream region queries may fail. Replace empty records with a run of N bases if the sequence is truly unknown, or remove the record.
Invalid or non-standard characters
samtools faidx is permissive about sequence characters because it treats the sequence as text. Downstream tools are less permissive. Nucleotide FASTA should use A, C, G, T, N, and IUPAC ambiguity codes. Protein FASTA uses the standard amino acid alphabet. A stray digit, *, or - may pass indexing and fail later. Check with a simple character count if you suspect a problem.
grep -v '^>' reference.fa | tr -d 'ACGTNacgtn' | head
No output means the file contains only the expected nucleotide characters. For a protein FASTA, adjust the character set.
Index file location and permissions
The index is written next to the FASTA by default. If the directory is read-only, the build fails even if the FASTA is readable. Copy the FASTA to a writable directory or build the index elsewhere and move both files together.
Typical error:
[E::fai_build3_core] Failed to open the file 'reference.fa.fai'
Check directory permissions and free space.
Concurrency and race conditions
Two processes building the same index at the same time can produce a truncated or inconsistent .fai. Build indexes once, before launching parallel jobs. If a pipeline starts many tasks that each call samtools faidx on the same reference, pre-build the index and make the tasks read-only.
Region not found
A typo in a chromosome name or a coordinate beyond the sequence length produces a warning and an empty result.
Typical messages:
[W::fai_get_val] Reference 'chr99' not found in FASTA file, returning empty sequence
[faidx] Failed to fetch sequence in chr99:1-100
Check the first column of the .fai and the sequence length. Remember that coordinates are 1-based and inclusive. A request for chr1:0-10 is invalid because position 0 does not exist.
The .fai is not a validation certificate
The index says where the bytes are. It does not prove that the assembly is correct, that the sequence is complete, or that the file matches a published reference. If you need that level of confidence, use checksums from the data provider and a sequence dictionary with metadata.
Limits of the format
A .fai supports retrieval by sequence name and coordinate. It does not support retrieval by sequence content, k-mer, variant, or annotation. For k-mer queries you need a k-mer index, and k-mer dictionaries can be memory-inefficient without one [8]. For read compression, tools such as minicom use k-minimizers to index reads and group similar sequences [9]. For genome collections, specialized compressors can outperform general-purpose tools, as shown by a collection of 1,092 human genomes compressed from about 6.7 TB of FASTA to about 700 MB [6]. Those are different problems from FASTA region access.
The .fai also does not compress the sequence. It is a text map beside a text file. If you need compression plus random access, use BGZF and the .gzi. If you need graph-based pangenome access, a linear .fai is not enough, and graph formats use their own indexes [7].
Frequently Asked Questions
What command creates a .fai index for a FASTA file?
Run samtools faidx reference.fa. It writes reference.fa.fai next to the input and prints nothing on success.
Do I need a .fai index to read a FASTA file?
No for simple sequential reading. You need it for random access by region and for many tools that expect a .fai beside the reference.
Can samtools faidx index a gzipped FASTA file?
Yes if the file is BGZF-compressed, which is what bgzip produces. A plain gzip file is not suitable because it lacks seekable blocks.
What does "Different line length in sequence" mean?
It means one sequence has a short or long line in the middle of the record. Reformat the record so every line except the last has the same width, then rebuild the index.
Where does samtools faidx write the index file?
It writes the index next to the input by default. For reference.fa the file is reference.fa.fai. For reference.fa.gz it writes reference.fa.gz.fai and reference.fa.gz.gzi.
Is a .fai file the same as a .dict file?
No. A .fai stores byte offsets and line widths for random access. A .dict stores sequence names, lengths, and assembly metadata for tools such as GATK.
How do I index many FASTA files at once?
Use a shell loop with set -euo pipefail and run samtools faidx "$f" for each file. For parallel work, use xargs -n 1 -P 4 samtools faidx.
Does samtools faidx modify the FASTA file?
No. It reads the FASTA and writes a separate index file. The FASTA sequence and headers are unchanged.