# Ensembl Extract Coding Sequence: Step-by-Step Guide

By the end of this guide you will be able to extract the coding sequence (CDS) of any Ensembl transcript, confirm that it is a complete open reading frame, and repeat the extraction for hundreds of transcripts in a scripted, reproducible way. You will be able to do it five ways: through the [Ensembl genome browser](/blog/guides/ensembl-genome-browser), through the Ensembl REST API, through BioMart, through biomaRt in R, and offline from a GTF annotation file plus a genome FASTA file.

What you need depends on the route you pick. A web browser is enough for the browser and BioMart routes. For scripting, install Python 3 with the requests and Biopython packages, or R with the biomaRt and Biostrings packages. For the offline route, install wget, gffread, and samtools. Every command below was run against the [human genome](/blog/guides/human-genome) assembly GRCh38, and the same logic works for any species Ensembl annotates.

If you are new to Ensembl, the first two sections double as a short tutorial on how to use Ensembl: what its identifiers mean, how its data model is organized, and where the sequence views live.

## How Ensembl Organizes Genes, Transcripts, and Sequences

Ensembl, maintained by EMBL-EBI, annotates reference genomes and publishes the results as a database plus a browser. A few terms come up constantly, so they are defined here once.

A **genome assembly** is the reference DNA sequence for a species. The current human assembly is GRCh38, and mouse is GRCm39. Coordinates are only meaningful within one assembly, which is why every Ensembl record states its assembly name.

A **gene** is a genomic locus. A **transcript** is one spliced RNA product of that gene. An **exon** is a block of sequence that survives splicing. The **CDS** (coding sequence) is the part of the transcript that encodes protein, running from the ATG start codon through and including the stop codon. The **cDNA** is the full spliced transcript, including the 5' and 3' untranslated regions, called **UTRs**. The **[protein sequence](/blog/guides/protein-sequence)** is the translation of the CDS. These distinctions matter because requesting the wrong one is the most common way to end up with a sequence that will not translate.

Ensembl names things with **stable IDs**. Genes start with ENSG, transcripts with ENST, proteins with ENSP, and exons with ENSE, each prefixed by a species code (ENSG for human, ENSMUSG for mouse, ENSBTG for cattle). A version suffix after a dot increments when the annotation changes, so ENST00000357654.9 is version 9 of that transcript. Ensembl publishes a new release roughly every three months, and between releases IDs can be added, merged, or retired.

Finally, Ensembl flags one transcript per gene as the **Ensembl canonical transcript**. When you need a single representative sequence per gene, the canonical transcript is the sensible default, and the API exposes the flag directly.

## Five Ways to Extract a Coding Sequence from Ensembl

![Decision path asking how many sequences you need and whether you write code, leading to browser, BioMart, REST API or GTF extraction.](/article-images/illustrations/ensembl-extract-coding-sequence-cds-route-choice.webp)

| Method | Best for | Input | Output |
|, - |, - |, - |, - |
| Genome browser | One gene, quick visual check | Gene name or ID typed into search | FASTA via the export button |
| REST API | Scripts and small to medium batches | Stable transcript IDs | FASTA or JSON over HTTP |
| BioMart | Bulk web export without code | Pasted ID lists plus filters | FASTA or tab-separated table |
| biomaRt | R pipelines | IDs, filters, attribute names | Data frame, FASTA via Biostrings |
| GTF plus genome FASTA | Whole genomes, reproducible runs | Downloaded annotation and genome | Per-transcript CDS FASTA |

Pick by scale. For one gene, the browser is fastest. For tens to thousands of sequences, use the REST API or BioMart. For R-based pipelines, use biomaRt. For large or repeatable jobs where you must be able to state exactly which annotation version produced your sequences, download the GTF and genome and extract locally.

## Method 1: Point and Click in the Ensembl Genome Browser

This section works as a compact Ensembl [genome browser tutorial](/blog/guides/genome-browsers-for-researchers-a-guide-to-inspecting-genomic-evidence) for sequence retrieval. It requires no code and takes about a minute per gene.

1. Open https://www.ensembl.org. Type BRCA1 into the search box and choose the human BRCA1 gene from the results. The gene page shows the location (chromosome 17 on GRCh38), the gene ID ENSG00000012048, and a graphic of all transcripts.
2. Click "Transcript table" near the top of the gene page. The table lists every transcript with its ID, name, biotype, length, and flags such as "Ensembl canonical".
3. Click the transcript you want, for example ENST00000357654 (BRCA1-201), the canonical protein-coding transcript.
4. On the transcript page, open the menu on the left side and find the "Sequence" section. Click "CDS". The sibling entries are "cDNA sequence", "Protein sequence", "Exons", and "Transcript". Choosing "CDS" shows only the coding bases, which is what you want for cloning an open reading frame.
5. The sequence view displays the CDS in lines of 60 bases. A header line above the sequence lists the transcript ID, the assembly, the coordinates, and the gene symbol. Copy the sequence directly, or click "Export data" at the top left and download the record as FASTA.
6. Save the file under a name that records what it is, for example BRCA1_ENST00000357654_GRCh38_cds.fa. This habit pays off the first time you come back to a project months later.

The one trap in this flow is choosing "cDNA sequence" when you meant CDS. The cDNA view includes the UTRs, so the sequence is longer and will not translate cleanly as an open reading frame without trimming.

## Method 2: The Ensembl REST API for Scripts and Pipelines

The REST API at https://rest.ensembl.org serves sequences over plain HTTP, so it works from curl, Python, R, or any language that can make web requests. Anonymous access is rate limited to 15 requests per second per IP address, and the server answers excess traffic with HTTP status 429 plus a Retry-After header telling you how long to wait.

### Step 1: Look up the transcript and confirm it has a CDS

```bash
curl -s -H "Content-Type: application/json" \
     -H "Accept: application/json" \
     "https://rest.ensembl.org/lookup/id/ENST00000357654?expand=1"
```

Expected output, abbreviated:

```json
{
  "assembly_name": "GRCh38",
  "biotype": "protein_coding",
  "gene_id": "ENSG00000012048",
  "id": "ENST00000357654",
  "strand": -1
}
```

With expand=1 the response also lists the exons, and coding exons carry their CDS coordinates. Two fields decide your next move. If biotype is not protein_coding, there is no CDS to fetch. If strand is -1, the gene runs on the minus strand, which matters only for coordinate-based extraction later.

### Step 2: Fetch the CDS

```bash
curl -s -H "Accept: text/x-fasta" \
     "https://rest.ensembl.org/sequence/id/ENST00000357654?type=cds"
```

Expected output:

```
>ENST00000357654 cds chromosome:GRCh38:17:43044295:43125482:-1 gene:ENSG00000012048 gene_symbol:BRCA1
ATG...
```

The FASTA header carries the transcript ID, the sequence type, the location on the assembly, the gene ID, and the gene symbol, so any file you save keeps its own provenance. The sequence itself runs 60 bases per line for the full CDS.

### Step 3: Fetch many sequences with one POST

```bash
curl -s -H "Content-Type: application/json" \
     -H "Accept: text/x-fasta" \
     -d '{"ids": ["ENST00000357654", "ENST00000269305"]}' \
     "https://rest.ensembl.org/sequence/id"
```

This returns both FASTA records in a single response. Batch a few hundred IDs per call rather than thousands, and write results to disk as they arrive so a network hiccup does not cost you the whole run.

### A reusable Python script

```python
import time
import requests

SERVER = "https://rest.ensembl.org"
TRANSCRIPTS = ["ENST00000357654", "ENST00000269305"]

def fetch_cds(tx_id):
    url = f"{SERVER}/sequence/id/{tx_id}"
    params = {"type": "cds"}
    headers = {"Accept": "text/x-fasta"}
    r = requests.get(url, params=params, headers=headers)
    if r.status_code == 429:
        time.sleep(int(r.headers.get("Retry-After", "1")))
        r = requests.get(url, params=params, headers=headers)
    r.raise_for_status()
    return r.text

with open("cds_batch.fa", "w") as out:
    for tx in TRANSCRIPTS:
        out.write(fetch_cds(tx))
        time.sleep(0.15)

print("wrote cds_batch.fa")
```

The 0.15 second pause keeps you comfortably inside the rate limit. For thousands of transcripts, switch to the POST endpoint, chunk your ID list, and log any IDs that fail so you can retry them separately.

### Parameters that matter

| Option | Where it goes | Values | Effect |
|, - |, - |, - |, - |
| type | Query string | genomic, cdna, cds, protein | Which sequence flavor you get, genomic is the default |
| expand | Query string | 0 or 1 | Adds exon detail to lookup responses |
| Accept | Request header | text/x-fasta, application/json | Output format |
| Content-Type | Request header | application/json | Required for POST bodies |
| ids | POST body | JSON array of stable IDs | Batch retrieval in one call |
| Retry-After | Response header | Seconds | Wait this long after HTTP 429 |

The type parameter is the one people get wrong most often. genomic returns the raw chromosome span, cdna returns the spliced transcript with UTRs, cds returns coding bases only, and protein returns the translated product.

## Method 3: BioMart for Bulk Export Without Code

1. Open https://www.ensembl.org/biomart.
2. Under CHOOSE DATABASE pick Ensembl Genes, and under CHOOSE DATASET pick Human genes (GRCh38).
3. Click Filters, expand the GENE section, and paste your IDs into the Ensembl Gene ID or Ensembl Transcript ID input box. You can also filter by gene name, biotype, chromosome, or chromosomal region.
4. Click Attributes. Expand SEQUENCES, select the "Sequences" radio button, and set the dropdown to "Coding sequence (CDS)". Then, under GENE, tick "Ensembl Transcript ID", "Ensembl Gene ID", and "Gene name" so the exported FASTA headers carry readable labels.
5. Click Results. Preview the first ten rows to confirm the columns look right, then click "Export all results" and choose FASTA as the format.
6. Compare the returned record count with the number of IDs you submitted. BioMart silently drops IDs it cannot match, so a mismatch means some inputs were typos or belonged to a different assembly.

BioMart is the fastest no-code route for hundreds to a few thousand sequences. For very large jobs it can time out, and the REST API or the offline method below will serve you better.

## Method 4: biomaRt in R

biomaRt talks to the same BioMart backend from R, which makes it the natural choice inside RMarkdown or Snakemake-driven analysis pipelines.

```r
library(biomaRt)

ensembl <- useEnsembl(biomart = "genes", dataset = "hsapiens_gene_ensembl")

cds <- getSequence(
  id         = "ENSG00000012048",
  type       = "ensembl_gene_id",
  seqType    = "coding",
  attributes = c("ensembl_transcript_id", "external_gene_name"),
  mart       = ensembl
)

head(cds)
```

The returned data frame has one row per transcript, with the CDS in the coding column. Write it out as FASTA with Biostrings:

```r
library(Biostrings)
seqs <- DNAStringSet(cds$coding)
names(seqs) <- cds$ensembl_transcript_id
writeXStringSet(seqs, "brca1_cds.fa")
```

If connections from the United States are slow, add mirror = "useast" to the useEnsembl call. Other useful seqType values are "cdna" for full spliced transcripts and "peptide" for protein sequences, which lets you pull a CDS and its translation in one query.

## Method 5: Extract CDS Offline from the GTF and Genome FASTA

For reproducible pipelines, download the annotation and the genome once, then extract locally as many times as you like. A GTF file is a tab-delimited annotation that lists the genomic coordinates of every gene, transcript, exon, and CDS block for one release.

```bash
wget https://ftp.ensembl.org/pub/release-113/gtf/homo_sapiens/Homo_sapiens.GRCh38.113.gtf.gz
wget https://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz
gunzip Homo_sapiens.GRCh38.113.gtf.gz Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz
```

Release 113 is shown as an example. Substitute the current release number from the FTP index, because Ensembl publishes a new release roughly every three months. The primary_assembly FASTA contains the chromosomes and unplaced scaffolds and skips alternate haplotype sequences, which is what most pipelines want.

Subset the GTF to your gene of interest, then run gffread, a command-line tool that builds sequences from an annotation plus a genome:

```bash
grep 'gene_id "ENSG00000012048"' Homo_sapiens.GRCh38.113.gtf > brca1.gtf
gffread -x brca1_cds.fa -g Homo_sapiens.GRCh38.dna.primary_assembly.fa brca1.gtf
grep -c '>' brca1_cds.fa
```

The -x flag writes the spliced CDS of every transcript in the GTF, reverse complementing minus-strand transcripts automatically. FASTA headers are the transcript IDs, and the final grep counts the records so you can check the output against the transcript table you saw in the browser. Swap -x for -w to get full cDNA transcripts, or -y to get translated proteins from the same input.

For a single genomic region, samtools is enough. First index the genome, then pull the locus:

```bash
samtools faidx Homo_sapiens.GRCh38.dna.primary_assembly.fa
samtools faidx Homo_sapiens.GRCh38.dna.primary_assembly.fa 17:43044295-43125482 > brca1_locus.fa
```

samtools returns the forward strand of the genome as stored. BRCA1 sits on the minus strand, so this output is the reverse complement of the sense sequence. Whenever strand matters, use gffread, seqkit, or Biopython rather than raw coordinate extraction.

## Verify the Sequence Before You Use It

![Worked sum where a 5,592 base CDS gives 1,863 amino acid residues plus the stop codon.](/article-images/illustrations/ensembl-extract-coding-sequence-cds-length-check.webp)

Four checks catch almost every bad extraction:

1. The length is divisible by three.
2. The first three bases are ATG.
3. The last three bases are TAA, TAG, or TGA.
4. There is no in-frame stop codon in the middle.

Biopython performs all four at once, because translate with cds=True refuses sequences that fail them:

```python
from Bio.Seq import Seq

def read_fasta(path):
    seqs, name, parts = {}, None, []
    for line in open(path):
        line = line.strip()
        if line.startswith(">"):
            if name:
                seqs[name] = "".join(parts)
            name, parts = line[1:].split(), []
        else:
            parts.append(line)
    if name:
        seqs[name] = "".join(parts)
    return seqs

for name, seq in read_fasta("cds_batch.fa").items():
    checks = (
        len(seq) % 3 == 0,
        seq[:3] == "ATG",
        seq[-3:] in ("TAA", "TAG", "TGA"),
    )
    protein = Seq(seq).translate(table=1, cds=True)
    print(name, len(seq), checks, len(protein))
```

If a sequence fails, Biopython raises an error such as "Sequence does not start with ATG start codon". The arithmetic is easy to sanity check by hand: a CDS of 5,592 bases translates to 1,863 amino acid residues plus the stop codon, because 5,592 equals 1,863 times 3 plus 3.

As a final cross-check, fetch the same transcript with type=protein from the REST API and compare it with your translation. They should match residue for residue. In the GTF route, read the tags column as well: Ensembl marks transcripts with incomplete coding ends using the start_NF and end_NF tags, and those CDS are not full open reading frames by construction.

## Why Researchers Extract Coding Sequences from Ensembl

CDS extraction feeds directly into expression cloning, primer design, codon usage analysis, and [comparative genomics](/blog/guides/comparative-genomics). A published study of the tear protein lacritin is a representative example. The authors extracted coding sequences for human, primate, and nonprimate orthologs from Ensembl, ran them through a rare codon calculator with codon usage tables appropriate to each species, and found that removing rare codons improved protein yields less than mutations that improved protein stability [1]. Ensembl was the sequence source precisely because it provides consistently annotated CDS across species in one place.

Ensembl also serves as the reference data layer for quantitative studies of genome structure. Work modeling the statistical distribution of human exon lengths drew exon sizes in base pairs directly from the Ensembl database and used those measurements to fit and compare length distributions across chromosomes [2]. That kind of analysis begins with exactly the extraction steps in this guide, applied at genome scale.

## Other Species, Model Organisms, and Companion Databases

The same workflows apply to any Ensembl species. For mouse, repeat the steps with the mus_musculus dataset and the GRCm39 GTF and FASTA files. For plants, fungi, protists, and bacteria, use the Ensembl Genomes sites, which expose the same BioMart interface with their own species datasets.

Model organism databases add curated context on top of Ensembl. Xenbase, the Xenopus model organism database, hosts current and archived Xenopus genomes, links its gene pages to Ensembl, NCBI Entrez, and UniProtKB, and provides task-oriented guides for identifying nucleic acid and protein sequences [3]. When a specialized database exists for your organism, use it for gene-level decisions and use Ensembl for bulk sequence extraction. Cross-species CDS pulls follow the same pattern as the lacritin work: extract the ortholog CDS from each species, then compare [1]. To script the ID list, the REST homology endpoint at https://rest.ensembl.org/homology/id/ENSG00000012048?type=orthologues returns Ensembl orthologs for a given gene, and an ortholog is simply the same gene in another species.

## Alternative Retrieval Systems

Ensembl is not the only programmatic route to coding sequences. The ACNUC database system provides remote query and extraction across EMBL, GenBank, RefSeq, UniProt, and Ensembl-derived databases, with application programming interfaces in C, Python, and R and both graphical and command-line retrieval clients [4]. If your pipeline already speaks ACNUC, or you need to move between RefSeq and Ensembl annotations inside one tool, it is a reasonable alternative to direct Ensembl access.

## Ensembl Extract Coding Sequence Tips

- **Request CDS by transcript ID.** The sequence endpoint returns clean results when you pass an ENST and ask for type=cds. To start from a gene, call the lookup endpoint with expand=1, list the transcripts, and fetch each one.
- **Use the canonical transcript as your default.** The gene lookup response includes the canonical_transcript field, so a script can pick one representative sequence per gene without manual choices.
- **Record provenance in the filename and a manifest.** Store the release number, assembly, date, and ID list in a small text file next to your FASTA. The FASTA headers Ensembl returns already carry IDs and coordinates, so keep them intact.
- **Batch and cache.** Use the POST endpoint for lists, sleep between calls, and save responses locally so you never fetch the same sequence twice.
- **Validate every sequence.** Run the four translation checks on the whole file, not just the first record. One bad transcript in a batch used for cloning costs days.
- **Match releases to files.** A GTF from one release and a genome FASTA from another will produce wrong or failed extractions. Download both from the same release directory.
- **Map retired IDs.** When an old ID returns HTTP 404, POST it to https://rest.ensembl.org/archive/id to find its current equivalent instead of guessing.
- **Use the US mirror in R.** biomaRt accepts mirror = "useast", which often speeds up queries from North America.
- **Pull the protein at the same time.** One extra request with type=protein gives you the translation for immediate comparison, which is cheaper than debugging a frame error later.
- **Know when you need cDNA instead.** For open reading frame cloning, use CDS. For expression quantification reference or UTR analysis, use cDNA. Deciding this before you extract prevents most rework.

## Common Mistakes and Limitations

**Confusing CDS with cDNA.** The symptom is a sequence longer than expected that translates with extra residues before the protein starts. The cause is selecting cDNA, which includes UTRs, when you wanted CDS. The fix is to request type=cds, or to choose "CDS" rather than "cDNA sequence" in the browser and BioMart.

**Using a gene ID where a transcript ID is required.** Requesting type=cds with an ENSG gives unexpected results because a gene has many transcripts, each with its own CDS. Enumerate transcripts with the lookup endpoint first, then fetch CDS per transcript.

**Leaving the version suffix on stable IDs.** Some endpoints reject versioned IDs such as ENST00000357654.9. Strip the suffix before calling the API, and keep the version in your own records instead.

**Mixing assemblies.** GRCh37 and GRCh38 coordinates differ, so a transcript ID or coordinate from one assembly can fail or mislead on the other. For GRCh37 work, use the archive site at https://grch37.ensembl.org and download the matching archive GTF and FASTA. Always state the assembly in your methods.

**Ignoring HTTP status codes.** A 404 response with the body {"error":"ID not found"} means the ID is mistyped, belongs to another database (NCBI RefSeq NM_ numbers are not Ensembl IDs), or was retired between releases. A 429 means you exceeded the request rate, and the Retry-After header tells you how long to wait. Scripts that ignore these codes end up writing empty records into FASTA files.

**Picking the wrong attribute in BioMart.** The sequence dropdown offers cDNA, CDS, peptide, and gene region options side by side. Choosing cDNA instead of CDS is silent, because BioMart happily returns a longer sequence. Preview the first rows and check lengths before exporting.

**Forgetting the strand with coordinate extraction.** samtools faidx returns the forward strand of the genome. For minus-strand genes like BRCA1, that is the reverse complement of the coding sense. Use gffread or a reverse complement step whenever strand matters.

**Requesting a CDS from a non-coding transcript.** Pseudogene and non-coding RNA transcripts have no CDS, so the request fails or returns nothing. Check biotype in the lookup response before fetching.

**Trusting unversioned downloads.** Ensembl changes annotation between releases, and IDs can be retired. A pipeline that fetches "the current" sequences today will not reproduce itself next quarter. Pin the release number everywhere, and keep the downloaded GTF and genome files if you used the offline route.

**Assuming Ensembl and RefSeq agree.** The two annotation groups can differ on transcript structures and CDS boundaries for the same locus. When a reviewer or collaborator works from RefSeq, compare the two annotations for your gene before claiming a discrepancy in your own data.

The main limitation of any extracted CDS is that it is an annotation, not a measurement. Annotation reflects current evidence and changes with each release, so sequences used for experiments such as cloning or antibody design should be confirmed against the latest release and, where it matters, against the literature for that gene.

## Frequently Asked Questions

### What is the difference between CDS and cDNA in Ensembl?

The CDS contains only the coding bases from the ATG start codon through the stop codon, while the cDNA is the full spliced transcript including the 5' and 3' UTRs. Choose CDS for open reading frame work and cDNA when you need the whole transcript.

### How do I extract the coding sequence for every transcript of a gene?

Call the lookup endpoint with the gene ID and expand=1, loop over the transcripts, and fetch type=cds for each transcript ID. In BioMart, filter by gene ID and select the CDS sequence attribute, which returns one row per transcript.

### Can I extract coding sequences from Ensembl without writing code?

Yes. Use the genome browser sequence view and its export button for one gene, or use BioMart with a pasted ID list for bulk export as FASTA. Both routes are point and click.

### Why is my extracted CDS not divisible by three?

The most common causes are a cDNA chosen instead of a CDS, an incomplete CDS flagged with start_NF or end_NF in the GTF, or a pseudogene transcript with no real CDS. Check the biotype and the GTF tags, then re-extract.

### How do I get the protein sequence instead of the CDS?

Use type=protein in the REST API, click "Protein sequence" in the browser, or set seqType to "peptide" in biomaRt. Comparing this sequence with your own translation of the CDS is a good validation step.

### Which transcript should I use when a gene has many transcripts?

Use the Ensembl canonical transcript as the default representative. If your project follows a specific protein or reference isoform, pick the transcript whose CDS matches it instead.

### How do I extract coding sequences from an older assembly such as GRCh37?

Use the GRCh37 archive site at https://grch37.ensembl.org for browsing, and download the matching archive GTF and FASTA files for offline extraction. Coordinates and IDs from GRCh38 will not line up with GRCh37.

### How do I avoid rate limit errors when extracting many sequences?

Batch IDs into POST requests, pause between calls, and honor the Retry-After header after any HTTP 429 response. Save responses to disk as you go so retries only cover failed IDs.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What is the difference between CDS and cDNA in Ensembl?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "The CDS contains only the coding bases from the ATG start codon through the stop codon, while the cDNA is the full spliced transcript including the 5' and 3' UTRs. Choose CDS for open reading frame work and cDNA when you need the whole transcript."
      }
    },
    {
      "@type": "Question",
      "name": "How do I extract the coding sequence for every transcript of a gene?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Call the lookup endpoint with the gene ID and expand=1, loop over the transcripts, and fetch type=cds for each transcript ID. In BioMart, filter by gene ID and select the CDS sequence attribute, which returns one row per transcript."
      }
    },
    {
      "@type": "Question",
      "name": "Can I extract coding sequences from Ensembl without writing code?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Use the genome browser sequence view and its export button for one gene, or use BioMart with a pasted ID list for bulk export as FASTA. Both routes are point and click."
      }
    },
    {
      "@type": "Question",
      "name": "Why is my extracted CDS not divisible by three?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "The most common causes are a cDNA chosen instead of a CDS, an incomplete CDS flagged with start_NF or end_NF in the GTF, or a pseudogene transcript with no real CDS. Check the biotype and the GTF tags, then re-extract."
      }
    },
    {
      "@type": "Question",
      "name": "How do I get the protein sequence instead of the CDS?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use type=protein in the REST API, click Protein sequence in the browser, or set seqType to peptide in biomaRt. Comparing this sequence with your own translation of the CDS is a good validation step."
      }
    },
    {
      "@type": "Question",
      "name": "Which transcript should I use when a gene has many transcripts?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use the Ensembl canonical transcript as the default representative. If your project follows a specific protein or reference isoform, pick the transcript whose CDS matches it instead."
      }
    },
    {
      "@type": "Question",
      "name": "How do I extract coding sequences from an older assembly such as GRCh37?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use the GRCh37 archive site at grch37.ensembl.org for browsing, and download the matching archive GTF and FASTA files for offline extraction. Coordinates and IDs from GRCh38 will not line up with GRCh37."
      }
    },
    {
      "@type": "Question",
      "name": "How do I avoid rate limit errors when extracting many sequences?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Batch IDs into POST requests, pause between calls, and honor the Retry-After header after any HTTP 429 response. Save responses to disk as you go so retries only cover failed IDs."
      }
    }
  ]
}
</script>

## Sources

1. [Conserved regional 3' grouping of rare codons in the coding sequence of ocular prosecretory mitogen lacritin.](https://pubmed.ncbi.nlm.nih.gov/23422824/)
2. [Superstatistical and DNA sequence coding of the human genome.](https://pubmed.ncbi.nlm.nih.gov/36671113/)
3. [Navigating Xenbase: An Integrated Xenopus Genomics and Gene Expression Database.](https://pubmed.ncbi.nlm.nih.gov/29761462/)
4. [Remote access to ACNUC nucleotide and protein sequence databases at PBIL.](https://pubmed.ncbi.nlm.nih.gov/17825976/)