# How to Export Ensembl Data to UCSC Genome Browser

By the end of this guide you will be able to export Ensembl data to [UCSC Genome Browser](/knowledge/bioinformatics/ucsc-genome-browser-beginner-tutorial-and-tips) and view it as a correctly aligned custom track or track hub. You will be able to move gene coordinates, variant positions, regulatory features, or whole-genome annotation from Ensembl to UCSC without the track appearing shifted by a base, dropped from the display, or misassigned to the wrong assembly.

Here is what you need on hand before starting:

- A terminal with `curl`, `awk`, `sort`, and `gzip` installed. On macOS these ship with the system. On Linux, install the `curl` and `gawk` packages through your package manager.
- The UCSC Kent tools (`fetchChromSizes`, `bedToBigBed`, `liftOver`) if you plan to build bigBed tracks. Download the precompiled binaries for your platform from the UCSC genome browser utilities page.
- A publicly reachable URL if you want UCSC to load your data by reference. A lab web server, an institutional file host, or any HTTPS endpoint that serves static files will do.
- Roughly 30 minutes for a gene-list export or an afternoon for a full-genome bigBed hub.

The exchange format that makes this workflow work is BED, a tab-delimited text format that both browsers accept for custom data. This is not a new idea. The arrayCGHbase platform, published in [BMC Bioinformatics](/blog/guides/bmc-bioinformatics), already exported copy-number results as BED files so they could be mapped on the genome using the Ensembl or UCSC genome browser in 2005 [1]. The same pattern holds today. You get coordinates out of Ensembl, reshape them into BED, and hand the file to UCSC.

## Why BED Is the Bridge Between Ensembl and UCSC

Ensembl and UCSC are separate databases with separate coordinate conventions, so you almost never move a native file from one straight into the other. The practical bridge is a simple interval format, usually BED, sometimes GFF3 or a tab-delimited table. The pipeline always has three stages.

1. Extract coordinates from Ensembl, either through the web interface, BioMart, the REST API, or the FTP server.
2. Convert those coordinates into BED or another UCSC-compatible format, adjusting the coordinate origin and chromosome names.
3. Load the file into UCSC as a custom track, a bigBed file, or a track hub, then verify alignment against a known feature.

Because BED is so simple (chromosome, start, end, plus optional name, score, and strand columns), the conversion stage is short. Most failures in this workflow happen in that short stage, and almost all of them trace back to two rules covered in the next section.

## Learn the Coordinate and Naming Rules First

If you skip this section, you will produce tracks that look almost right and then chase one-base offsets for an hour. Read it once and the rest of the workflow becomes mechanical.

### One-based versus zero-based coordinates

![Worked example turning the Ensembl BRCA1 interval 43,044,295 to 43,125,482 into a BED line starting at 43,044,294 on chr17.](/article-images/illustrations/export-ensembl-data-to-ucsc-genome-browser-brca1-coordinate-conversion.webp)

Ensembl reports positions in one-based, fully closed coordinates. Position 1 is the first base of the chromosome, and a feature from 100 to 200 includes both base 100 and base 200.

The UCSC BED format uses zero-based, half-open coordinates. The start position is counted from 0, and the end position is exclusive. A BED interval of `start=99, end=200` covers the same bases as the Ensembl interval 100 to 200.

The conversion rule:

- BED start = Ensembl start - 1
- BED end = Ensembl end (unchanged)

Worked example using BRCA1 on human chromosome 17. Ensembl reports the gene at 17:43,044,295-43,125,482 on the minus strand in GRCh38 coordinates. Converting to BED:

```
BED start = 43044295 - 1 = 43044294
BED end   = 43125482
BED line  = chr17  43044294  43125482  BRCA1  0  -
```

A useful memory aid: the Ensembl one-based start equals the BED end of the previous base. When you view a single-nucleotide variant at Ensembl position 43125482, the equivalent BED interval is `chr17 43125481 43125482`, a one-base interval where the start is one less than the end.

Note that GFF3 and GTF use one-based closed coordinates like Ensembl. Only BED (and a few related formats such as PSL and BAM) use the zero-based half-open convention. When you convert GTF to BED, the same start-minus-one rule applies.

### Chromosome names and assembly versions

Two naming mismatches cause most failed tracks.

First, chromosome prefixes. Ensembl writes chromosome names without a prefix, so human chromosome 17 is `17`. UCSC writes it as `chr17`. Most UCSC tools and displays require the `chr` prefix. The fix is one string operation during conversion, shown in the command examples below.

Second, assembly versions. Ensembl and UCSC use different names for the same underlying genome builds. The common human and mouse pairs are:

| Ensembl name | UCSC name | Notes |
|--|--|--|
| GRCh38 | hg38 | Current human build used by both browsers |
| GRCh37 | hg19 | Previous human build, still widely used |
| GRCm39 | mm39 | Current mouse build |
| GRCm38 | mm10 | Previous mouse build, still common in older papers |

The pairs are close but not guaranteed identical. UCSC builds add its own sequence refinements and alternate locus handling, and Ensembl releases include patches that UCSC may represent differently. If your data comes from GRCh37 and you want it on hg38, the safe path is a liftOver conversion rather than a naive relabeling. The liftOver command appears in the common mistakes section.

The rule to internalize: check the assembly dropdown on both browsers before you export anything. A track built from GRCh38 coordinates loaded onto the hg19 display will land thousands of bases away from the correct genes, and nothing in the UCSC interface will warn you.

## Method 1: Export Straight from the Ensembl Browser

This is the fastest path for a single region and a good way to learn how to use Ensembl's export options. Think of it as the interactive part of any Ensembl [genome browser tutorial](/blog/guides/genome-browsers-for-researchers-a-guide-to-inspecting-genomic-evidence).

1. Go to ensembl.org and search for a gene or region, for example `BRCA1 human`. Open the region view.
2. Click **Location** in the top menu, then choose **Region in detail**. You are now looking at the graphical view of your region.
3. In the left-hand menu, click **Export data**. Ensembl presents a panel of output formats.
4. Select **BED** as the format. Set the output strand and any flanking sequence you want. The flank option is expressed in bases, so entering 5000 adds 5 kb on each side of the feature.
5. Click **Go** and download the file.

The output looks like this, with the exact values depending on your region:

```
track name=Ensembl_export description="BRCA1 region" visibility=dense
chr17  43044294  43125482  ENSG00000012048  0  -
```

Two things to notice. Ensembl writes chromosome names without the `chr` prefix even in its BED export, so you may still need to add the prefix yourself depending on which UCSC display you target. Second, the coordinates in the exported BED are already zero-based half-open, because Ensembl is emitting BED format. Do not subtract 1 from a file that is already BED. Subtract 1 only when the source is one-based data, such as GTF or BioMart tables.

This method scales poorly. It handles one region at a time, so for anything beyond a handful of features, move on to the methods below.

## Method 2: Export Gene Lists with BioMart

BioMart is Ensembl's bulk query tool. Use it when you want a filtered list of genes, transcripts, or other features with their coordinates, for example all protein-coding genes on chromosome 17.

1. Open martview.ensembl.org.
2. Under **Choose Database**, select the current **Ensembl Genes** release.
3. Under **Choose Dataset**, select **Human genes (GRCh38)** or your species of interest.
4. Open **Filters** and set your selection. To restrict to chromosome 17, expand **REGION**, set **Chromosome** to 17. You can also filter by gene biotype, which is how you would keep only protein-coding genes.
5. Open **Attributes**. Under **GENE**, keep **Gene stable ID** and **Gene name**. Under the coordinates section, select **Chromosome/scaffold name**, **Gene start (bp)**, **Gene end (bp)**, and **Strand**.
6. Click **Results**, set the output to **TSV**, and export or copy the table.

The result looks like this:

```
Gene stable ID    Gene name  Chromosome  Gene start  Gene end  Strand
ENSG00000012048   BRCA1      17          43044295    43125482  -1
```

Two details matter here. BioMart's start and end values are one-based closed coordinates, exactly like the Ensembl website, so the BED conversion subtracts 1 from the start column. BioMart encodes strand as `1` or `-1` rather than `+` or `-`.

Convert the whole table with a single `awk` command. Save the BioMart export as `biomart_genes.tsv` and run:

```
awk -F'\t' 'NR>1 && $3!="" {str=( $6==-1 ? "-" : "+" )
  print "chr"$3 "\t" ($5-1) "\t" $6 "\t" $2 "\t0\t" str }' biomart_genes.tsv > chr17_genes.bed
```

Wait, check the column order. In the TSV shown, column 4 is start and column 5 is end. Corrected command:

```
awk -F'\t' 'NR>1 && $3!="" {str=( $6==-1 ? "-" : "+" )
  print "chr"$3 "\t" ($4-1) "\t" $5 "\t" $2 "\t0\t" str }' biomart_genes.tsv > chr17_genes.bed
```

The output:

```
chr17  43044294  43125482  BRCA1  0  -
```

Practical tips for BioMart. The web interface can truncate very large exports, so for whole-genome gene lists prefer the FTP method below or write the query through the BioMart REST interface. Also confirm the dataset version matches your target UCSC assembly. BioMart keeps older assemblies available, which is convenient, but grabbing human genes from a GRCh37 dataset and loading them on hg38 is a silent misalignment.

## Method 3: Query the Ensembl REST API

The REST API is the right tool when you want a scriptable, repeatable extraction for one or many regions, and it forms the backbone of most automated export workflows. The API returns JSON, and you reshape it to BED with standard Unix tools.

The example below extracts all genes overlapping the BRCA1 locus in human GRCh38.

```
curl -s 'https://rest.ensembl.org/overlap/region/human/17:43044294-43125482?feature=gene' \
  -H 'Content-Type: application/json'
```

The response is a JSON array. Each element contains the coordinate fields you need, for example:

```
[
  {
    "seq_region_name": "17",
    "start": 43044295,
    "end": 43125482,
    "strand": -1,
    "id": "ENSG00000012048",
    "feature_type": "gene",
    ...
  }
]
```

The `start` and `end` values in the JSON are one-based closed, consistent with the website. Convert to BED with `jq` and `awk`:

```
curl -s 'https://rest.ensembl.org/overlap/region/human/17:43044294-43125482?feature=gene' \
  -H 'Content-Type: application/json' \
| jq -r '.[] | [.seq_region_name, .start, .end, .id, .strand] | @tsv' \
| awk -F'\t' 'BEGIN{OFS="\t"}
  { str=( $5=="-1" ? "-" : "+" )
    print "chr"$1, ($2-1), $3, $4, 0, str }' > brca1_genes.bed
```

Expected output:

```
chr17  43044294  43125482  ENSG00000012048  0  -
```

Parameters worth knowing as you expand this beyond the example:

- The `feature` parameter accepts `gene`, `transcript`, `exon`, `cds`, `repeat`, `variation`, `regulatory`, and others. Change the value, not the endpoint, to change what you pull.
- Replace `human` with any species assembly shortname Ensembl supports, for example `mouse` for the current mouse reference.
- Change the coordinate string to any region, including whole chromosomes such as `17:1-83257441` if you need chromosome-wide extraction, though the FTP method is better for whole-chromosome work.
- Add `?feature=gene;feature=transcript` style repeated parameters or use the `expand_5prime` and `expand_3prime` options where the endpoint supports them to widen the returned intervals.

The public REST server is rate-limited. For a few thousand requests this is fine if you sleep between calls. For anything larger, batch your regions, or use the FTP files in the next method and reserve the API for lookups and spot checks.

## Method 4: Download Full GTF Files and Convert to BED

When you need complete annotation, such as every gene in the genome, skip per-feature queries and download Ensembl's own annotation files from the FTP server. The GTF (gene transfer format) file lists every feature with one-based closed coordinates.

Download the current human GTF. Release numbers change with every Ensembl update, so check the current release on the Ensembl site and substitute it:

```
wget https://ftp.ensembl.org/pub/release-113/gtf/homo_sapiens/Homo_sapiens.GRCh38.113.gtf.gz
```

The file is tab-delimited with nine columns. Column 1 is the chromosome name, column 4 is the one-based start, column 5 is the end, column 7 is the strand, and column 9 holds attributes including `gene_name`. Convert gene records to BED:

```
zcat Homo_sapiens.GRCh38.113.gtf.gz \
| awk -F'\t' 'BEGIN{OFS="\t"}
  $1 !~ /^#/ && $3 == "gene" {
    match($9, /gene_name "[^"]+"/)
    gn = substr($9, RSTART+11, RLENGTH-12)
    print "chr"$1, ($4-1), $5, gn, 0, $7 }' > genes_hg38.bed
```

Expected output for the first lines:

```
chr1  11868  14409  DDX11L1  0  +
chr1  14403  29557  WASH7P   0  -
```

Check the arithmetic on the first line. The GTF start 11868 becomes BED start 11867, wait, 11868 minus 1 is 11867. If you see 11869 or 11868 in your own output, your `awk` is missing the minus one and every track you build will be shifted. This one-character bug is the most common error in the entire workflow, which is why the verification section below matters.

The same conversion works for transcripts (`$3 == "transcript"`) and exons (`$3 == "exon"`). For exons, extract `transcript_id` instead of `gene_name` so each exon carries the identifier of its parent transcript. If you want UCSC to draw spliced gene models rather than flat intervals, you need BED12 with the thickStart, thickEnd, and block fields filled in from exon coordinates, or you should move to a genePred-based pipeline, both of which are described in the UCSC format documentation.

Why not simply download UCSC's own annotation and skip Ensembl entirely? Because the two browsers disagree on some transcript models and gene counts, and projects that compare calls across both browsers, as the arrayCGHbase workflow did for copy-number mapping on Ensembl or UCSC [1], often need Ensembl's models rendered inside UCSC. Keeping the source of truth consistent with your analysis pipeline avoids artifacts that look like biological differences.

## Method 5: Put the Data on UCSC as a Custom Track or Hub

You now have a BED file. Three display routes exist on UCSC, ordered here from simplest to most robust.

### Option A: Paste or upload a custom track

For files up to a few thousand lines, the classic custom track works well. Prepare your file with a track line on top:

```
track name="Ensembl_Genes_GRCh38" description="Ensembl gene regions, GRCh38" visibility=dense color=0,0,180
chr17  43044294  43125482  BRCA1  0  -
chr17  7687486   7690150   TP53   0  -
```

Key track line parameters:

- `name`, a short internal identifier, no spaces.
- `description`, shown to the user in the track controls.
- `visibility`, one of `hide`, `dense`, `pack`, `full`, or `squish`. `dense` shows a single collapsed bar, `pack` stacks items with labels.
- `color`, RGB values from 0 to 255, commas between the values, no spaces.
- `url`, a link attached to items so clicking opens your page of choice.

Then open the UCSC Genome Browser at genome.ucsc.edu, click **Tracks**, then **Add Custom Tracks** (the link is labeled **add custom tracks** on the main page), and either paste the whole block into the text box or upload the file. Click **Submit**, then **Go to genome browser**.

For files already sitting on a web server, you can skip the upload entirely by opening a display URL with the file location embedded:

```
https://genome.ucsc.edu/cgi-bin/hgTracks?db=hg38&hgt.customText=https://yourserver.org/genes.bed
```

The `hgt.customText` parameter tells UCSC to fetch the track from your URL. The file must be reachable without a login.

### Option B: Build a bigBed for large datasets

Custom tracks that live in the browser session are limited in size and lifetime. For datasets with tens of thousands of intervals or more, convert to bigBed, a binary indexed format UCSC streams efficiently. The arrayCGH-era approach of shipping BED files to the browsers still works, but bigBed is the modern container for the same data [1].

```
# 1. Sort by chromosome, then by start position
sort -k1,1 -k2,2n genes_hg38.bed > genes_hg38.sorted.bed

# 2. Fetch the chromosome sizes for the target assembly
fetchChromSizes hg38 hg38.chrom.sizes

# 3. Convert to bigBed
bedToBigBed -type=bed6 genes_hg38.sorted.bed hg38.chrom.sizes genes_hg38.bb
```

Put `genes_hg38.bb` on your web server, then add a custom track that points to it:

```
track name="Ensembl_Genes" type=bigBed 6 description="Ensembl GRCh38 genes" bigDataUrl=https://yourserver.org/genes_hg38.bb visibility=pack
```

The chromosome sizes file matters more than people expect. If your BED contains a chromosome name absent from the sizes file, `bedToBigBed` fails with an error pointing at the offending line, typically a message about the chromosome name not being found in the chrom info. If your BED contains an end coordinate past the chromosome length, for example an end beyond 83,257,441 on chr17 in hg38, the tool rejects the line with a range error. Both failures are conversion bugs, not UCSC bugs, and both are caught by the validation steps below.

### Option C: Build a track hub for many tracks

When you have dozens of Ensembl-derived tracks, wrap them in a hub. A hub is a small directory of text files plus your data files, served over HTTPS, that UCSC reads as a track group.

A minimal hub has three text files:

```
# hub.txt
hub EnsemblExport
shortLabel Ensembl export
longLabel Ensembl GRCh38 annotation exported to UCSC
genomesFile genomes.txt
email you@example.org
```

```
# genomes.txt
genome hg38
trackDb trackDb.txt
```

```
# trackDb.txt
track genes
bigDataUrl https://yourserver.org/genes_hg38.bb
shortLabel Ensembl genes
longLabel Ensembl GRCh38 gene regions
visibility pack
type bigBed 6
```

Register the hub by pasting the URL of `hub.txt` into **Track Hubs** under **My Data** on genome.ucsc.edu. Hubs persist, support multiple assemblies through the `genomes.txt` file, and let collaborators load your full annotation set in one step.

## Method 6: Variant Data and VEP Output on UCSC

Variant calls deserve their own section because they arrive with assembly and representation quirks. If you annotate variants with Ensembl VEP, the output is a VCF or a tab-delimited file in Ensembl coordinates, and moving it onto UCSC follows the same three-stage pattern as everything else.

Start from a VCF. Extract the variant positions and convert to one-base BED intervals:

```
bcftools view -H variants.vcf.gz \
| awk -F'\t' 'BEGIN{OFS="\t"}
  { print "chr"$1, ($2-1), $2, $4">"$5, 0, "+" }' > variants.bed
```

Every line becomes a one-base interval, where the BED start is the VCF position minus 1 and the BED end equals the VCF position. This is the direct application of the half-open rule to a single base.

If your variants were annotated with VEP, you may also want consequence terms carried into the UCSC display. The clean approach is to keep the annotation in the BED name field or in an attached bigBed with extra fields. Building those pipelines by hand, with plugin configuration and format conversion scripts at every step, is exactly the pain point that reproducible annotation frameworks address. MuSA, a Nextflow pipeline published in BMC Bioinformatics, integrates Ensembl VEP with dozens of curated plugins and standardizes input VCFs while automating the format conversion and prioritization steps that ad hoc scripts usually handle [2]. If your variant annotation workflow is growing beyond a one-off export, running it inside a containerized pipeline and exporting the final annotated table to BED is more durable than maintaining a hand-written converter.

One caution specific to variants: VCF files may contain chromosomes named `17` or `chr17` depending on the caller and the reference used. Normalize the naming before building the track, and confirm the reference assembly stamped in the VCF header matches your UCSC target.

## Choosing a Method

![Decision path asking how much data you need and whether the extraction must be scriptable, ending on browser export, BioMart, REST API or FTP GTF.](/article-images/illustrations/export-ensembl-data-to-ucsc-genome-browser-choose-export-method.webp)

| Method | Best for | Scale | Output format |
|--|--|--|--|
| Ensembl browser export | One region, quick visual checks | Single regions | BED, GFF3, others |
| BioMart | Filtered gene or feature lists | Hundreds to low thousands of records | TSV, then convert to BED |
| REST API | Scriptable, repeatable extraction | Hundreds to thousands of requests | JSON, then convert to BED |
| FTP GTF or GFF3 download | Whole-genome annotation | Millions of features | GTF or GFF3, convert to BED |
| VCF plus VEP output | Variant positions and consequences | Thousands to millions of variants | VCF or TSV, convert to BED |

All five methods converge on the same delivery step, a BED file pushed to UCSC as a custom track, bigBed, or hub. Learn one extraction method well and one delivery method well, and you can move anything.

## Check Your Work

Verification takes two minutes and catches every error class described above.

1. **Confirm the assembly.** On the UCSC display, check the assembly name in the header reads `hg38` (or your chosen target). On the Ensembl side, confirm the export came from GRCh38. Mismatch here invalidates everything else.
2. **Spot-check one feature against a known gene.** Jump your UCSC view to a gene you know, for example BRCA1, and confirm your track's interval starts and ends within a base of the UCSC-known gene model. If your track item begins exactly one base upstream of the UCSC gene's first base, you forgot the minus-one conversion. If it is off by thousands of bases, you have an assembly mismatch.
3. **Check chromosome naming.** Your track should appear on the chromosome you expect. A track that renders at the far edge of the chromosome view or under an unfamiliar name is a prefix problem.
4. **Validate against the chromosome size.** For hg38, chr17 spans 83,257,441 bases. If your BRCA1 BED interval reads `chr17 43044294 43125482`, both values sit comfortably inside that length, and the interval ordering (start less than end, start at least 0) holds. A quick shell check for any file:

```
awk -F'\t' '$2 < 0 || $3 <= $2 {print "BAD:", $0}' genes_hg38.sorted.bed
```

An empty result means every interval has a nonnegative start and an end greater than the start.

5. **Compare strand.** A minus-strand gene rendered as plus will still align at the right bases, so this check catches logic errors in your conversion script rather than display problems. Compare the arrow direction on your track items against the UCSC reference gene track.

## Common Mistakes and Limitations

These are the failures seen most often when exporting Ensembl data to UCSC, with the symptom and the fix for each.

**Forgetting the one-based to zero-based conversion.** If your source is GTF, GFF3, BioMart output, or JSON from the REST API, subtract 1 from the start. If your source is already BED, including Ensembl's own BED export, do not subtract anything. The symptom of getting this wrong is a track where every item starts one base late, visible only when you zoom to single-base resolution.

**Missing or extra `chr` prefix.** Ensembl names chromosomes `17`, UCSC expects `chr17`. The `awk` examples above add the prefix during conversion. Adding it twice produces `chrchr17`, which UCSC treats as an unknown chromosome and silently drops, so a whole track can vanish for a naming reason. Check with:

```
grep -c '^chrchr' genes.bed
grep -v '^chr' genes.bed | head
```

**Loading onto the wrong assembly.** GRCh37 data on an hg38 display is misaligned by more than the coordinate offset, because the builds differ in some regions. Relabeling chromosome names does not convert assemblies. Use `liftOver` with the correct chain file:

```
liftOver ensembl_grch37.bed hg19ToHg38.over.chain ensembl_on_hg38.bed unlifted.bed
```

Then check `unlifted.bed`. Features that could not be converted land there, and a large unlifted fraction signals that your source coordinates were not what you thought.

**Feeding compressed files to the custom track upload.** UCSC custom tracks accept plain text, not `.gz` archives. Decompress first with `gunzip`. The browser rejects the file with an unrecognized-format error.

**Breaking the track line.** The track line must be the first line of the file, must define a `name`, and must be followed directly by data. A blank line between the track line and the first data line can cause display failures. A `name` with spaces or a missing name produces a custom track error in the browser's error report.

**Mismatched chromosome sizes in bedToBigBed.** Building a bigBed for hg38 with an hg19 sizes file, or with a sizes file you generated yourself rather than fetched for the exact assembly, produces either a hard failure or, worse, a file that loads and displays wrong. Always use `fetchChromSizes` for the exact target database.

**BioMart truncation on large exports.** The web interface can cut off very large result sets without a clear warning. If your exported line count is lower than the filter count BioMart reports, switch to the FTP download or the REST API. Checking the returned row count against your expected feature count is a one-line sanity check that saves silent data loss.

**Score fields outside the allowed range.** BED's score column must run from 0 to 1000. Copying a p-value or an unbounded metric into that column makes UCSC clamp or reject values. Rescale your scores into the valid range or write 0.

**Assuming patch versions matter for routine display.** Ensembl GRCh38 releases carry patch versions in their naming, and UCSC hg38 represents a single curated assembly. For display purposes the difference rarely matters, but if a coordinate falls in a patched region, verify it against both browsers rather than assuming agreement.

**Treating format conversion as throwaway scripting.** The MuSA authors identify ad hoc scripts for format conversion as a recurring bottleneck that undermines reproducibility in variant annotation workflows [2]. The same lesson applies to browser exports. Save your conversion commands in a versioned script with the release number and assembly recorded in a comment, so the track you build today can be rebuilt identically next year.

A final limitation worth stating plainly. This workflow moves coordinates and their labels. It does not translate biological meaning between the two resources. If a variant is pathogenic in your analysis, the UCSC track will show where it sits, not whether it matters. Individual interpretation of any exported feature needs domain expertise and, in clinical contexts, appropriate review.

## Frequently Asked Questions

### Do I need to convert coordinates between Ensembl and UCSC?

Yes, when your source data is one-based, which includes Ensembl web exports of GTF, BioMart tables, and REST JSON. Subtract 1 from the start position to get BED coordinates. If your data is already in BED format, including Ensembl's own BED export, the conversion is already done.

### Which UCSC assembly matches Ensembl GRCh38?

The matching UCSC build is hg38. Other common pairs are GRCh37 with hg19, GRCm39 with mm39, and GRCm38 with mm10. The pairs are equivalent for most purposes but not guaranteed base-for-base identical, so use liftOver when moving data across builds.

### Why does my track appear shifted by one base?

Your conversion script subtracted 1 from the start when it should not have, or failed to subtract 1 when it should have. Zoom to single-base resolution on a known gene and compare your item's first base against the UCSC reference gene track to see which case you have.

### What is the largest dataset I can upload as a custom track?

Custom tracks are meant for modest files, roughly in the low thousands of intervals. For larger datasets, convert to bigBed with `bedToBigBed` and serve it from a URL, or package multiple tracks into a hub. Both scale to millions of features.

### Can I display VEP annotation on the UCSC Genome Browser?

Yes. Export the VEP-annotated VCF, convert each variant to a one-base BED interval, and load it as a custom track or bigBed. For comprehensive annotations with many plugins, a containerized pipeline such as MuSA handles the format conversion and keeps the workflow reproducible.

### How do I export sequence data rather than just coordinates?

Use the Ensembl REST sequence endpoints, for example the endpoint that returns sequence for a region, and request plain text with the appropriate content-type header. Sequence itself has no coordinates, so it does not go on a UCSC track, but you can pair a sequence export with a BED interval to annotate what you retrieved.

### Why are the chromosome names different between the two browsers?

Ensembl uses bare numbers and letters such as `17` while UCSC prefixes with `chr`, giving `chr17`. This is a long-standing convention difference, not a data difference. Add or strip the prefix with a string operation during conversion.

### Is BioMart still the right tool for bulk Ensembl exports?

BioMart remains the easiest interactive tool for filtered gene lists up to a few thousand records. For whole-genome exports or anything that risks truncation, download the GTF or GFF3 files from the Ensembl FTP server instead, then convert them to BED yourself.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Do I need to convert coordinates between Ensembl and UCSC?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes, when your source data is one-based, which includes Ensembl web exports of GTF, BioMart tables, and REST JSON. Subtract 1 from the start position to get BED coordinates. If your data is already in BED format, including Ensembl's own BED export, the conversion is already done."
      }
    },
    {
      "@type": "Question",
      "name": "Which UCSC assembly matches Ensembl GRCh38?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "The matching UCSC build is hg38. Other common pairs are GRCh37 with hg19, GRCm39 with mm39, and GRCm38 with mm10. The pairs are equivalent for most purposes but not guaranteed base-for-base identical, so use liftOver when moving data across builds."
      }
    },
    {
      "@type": "Question",
      "name": "Why does my track appear shifted by one base?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Your conversion script subtracted 1 from the start when it should not have, or failed to subtract 1 when it should have. Zoom to single-base resolution on a known gene and compare your item's first base against the UCSC reference gene track to see which case you have."
      }
    },
    {
      "@type": "Question",
      "name": "What is the largest dataset I can upload as a custom track?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Custom tracks are meant for modest files, roughly in the low thousands of intervals. For larger datasets, convert to bigBed with bedToBigBed and serve it from a URL, or package multiple tracks into a hub. Both scale to millions of features."
      }
    },
    {
      "@type": "Question",
      "name": "Can I display VEP annotation on the UCSC Genome Browser?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Export the VEP-annotated VCF, convert each variant to a one-base BED interval, and load it as a custom track or bigBed. For comprehensive annotations with many plugins, a containerized pipeline such as MuSA handles the format conversion and keeps the workflow reproducible."
      }
    },
    {
      "@type": "Question",
      "name": "How do I export sequence data rather than just coordinates?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use the Ensembl REST sequence endpoints, for example the endpoint that returns sequence for a region, and request plain text with the appropriate content-type header. Sequence itself has no coordinates, so it does not go on a UCSC track, but you can pair a sequence export with a BED interval to annotate what you retrieved."
      }
    },
    {
      "@type": "Question",
      "name": "Why are the chromosome names different between the two browsers?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Ensembl uses bare numbers and letters such as 17 while UCSC prefixes with chr, giving chr17. This is a long-standing convention difference, not a data difference. Add or strip the prefix with a string operation during conversion."
      }
    },
    {
      "@type": "Question",
      "name": "Is BioMart still the right tool for bulk Ensembl exports?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "BioMart remains the easiest interactive tool for filtered gene lists up to a few thousand records. For whole-genome exports or anything that risks truncation, download the GTF or GFF3 files from the Ensembl FTP server instead, then convert them to BED yourself."
      }
    }
  ]
}
</script>

## Sources

1. [arrayCGHbase: an analysis platform for comparative genomic hybridization microarrays.](https://pubmed.ncbi.nlm.nih.gov/15910681/)
2. [MuSA: a Nextflow pipeline for deep, reproducible annotation and clinical ranking of genomic variants.](https://pubmed.ncbi.nlm.nih.gov/42304195/)