Claude
Skills
Sign in
Back

bio-uniprot-access

Included with Lifetime
$97 forever

Query UniProt's REST API (post-2022 endpoint at rest.uniprot.org) for protein sequences, annotations, GO terms, cross-references, ID mappings, and proteomes. Use when fetching UniProtKB entries, navigating the JSON schema, choosing between UniProtKB/UniRef/UniParc/Proteomes resources, deciding stream vs search endpoint for batch retrieval, running ID-mapping jobs with the async pattern, handling isoform suffixes, or filtering reviewed Swiss-Prot vs auto-annotated TrEMBL. Encodes the legacy URL migration (2022), the new JSON schema layout, and bulk-pull patterns.

Backend & APIs

What this skill does


## Version Compatibility

Reference examples tested with: requests 2.31+, pandas 2.2+; UniProt REST API as of 2024_06 release

Before using code patterns, verify installed versions match. If versions differ:
- Python: `pip show requests pandas`
- API surface: confirm endpoint URLs match https://www.uniprot.org/help/api

The REST API JSON schema is stable within a release; major schema changes are documented at https://www.uniprot.org/release-notes. The 2022 migration broke the legacy `https://www.uniprot.org/uniprot/...` endpoints.

# UniProt Access

**"Get protein information from UniProt"** -> Two facts dominate every UniProt workflow in 2026: (1) **the API endpoint migrated in 2022** from `https://www.uniprot.org/uniprot/...` to `https://rest.uniprot.org/uniprotkb/...` with a substantially different JSON schema; pre-2022 code does not work as-is. (2) **`?fields=`** is essential — default JSON returns the full entry (~20-30 KB each); for bulk pulls, request only the fields actually needed.

The major databases under the UniProt umbrella have different scopes:

- **UniProtKB**: the curated knowledgebase — Swiss-Prot (manually reviewed, ~570K entries as of 2024) + TrEMBL (auto-annotated, ~250M). Always specify `reviewed:true` for high-quality reference work.
- **UniRef**: clustered sequences at 100%, 90%, 50% identity. UniRef50 is the standard for redundancy reduction.
- **UniParc**: archival "every unique sequence ever seen" — for provenance and historical lookup.
- **Proteomes**: organism-level groupings; reference proteomes (one per species) are the canonical subset.

- Python: `requests.get('https://rest.uniprot.org/uniprotkb/...')` (REST API)
- Python: `Bio.ExPASy.get_sprot_raw()` (BioPython; legacy SwissProt format)
- CLI: `curl https://rest.uniprot.org/uniprotkb/P04637.json`

## Required Setup

```python
import requests
import pandas as pd
import time
```

No API key required. Rate limit is generous (~200 req/sec tolerated empirically); ID-mapping has its own job queue.

## Endpoint reference

Base: `https://rest.uniprot.org/`

| Resource | Endpoint | Use |
|---|---|---|
| Single entry | `/uniprotkb/{accession}` | One protein record |
| Search | `/uniprotkb/search` | Query with up to 500 results per page |
| Stream | `/uniprotkb/stream` | No 500-result limit; for bulk |
| Batch by accession | `/uniprotkb/accessions` | Multiple specific accessions |
| ID Mapping (run) | `/idmapping/run` | Submit conversion job |
| ID Mapping (status) | `/idmapping/status/{jobId}` | Poll |
| ID Mapping (results) | `/idmapping/results/{jobId}` | Retrieve |
| UniRef entry | `/uniref/{cluster_id}` | One cluster |
| UniRef search | `/uniref/search` | UniRef cluster queries |
| Proteome | `/proteomes/{upid}` | Organism proteome |
| Proteome FASTA | `/proteomes/{upid}.fasta.gz` | Download whole proteome |
| Taxonomy | `/taxonomy/{taxid}` | Taxonomy info |

Append `.json`, `.fasta`, `.tsv`, `.xml`, `.txt`, or `.gff` to single-entry URLs to control format.

## Search query syntax

UniProt search queries use a Lucene-like syntax distinct from Entrez:

| Query | Means |
|---|---|
| `gene:TP53` | Gene name TP53 |
| `gene_exact:TP53` | Exact gene name (no wildcard match) |
| `organism_id:9606` | Human (NCBI taxonomy ID) |
| `organism_name:"Homo sapiens"` | By name (slower than taxid) |
| `reviewed:true` | Swiss-Prot only |
| `reviewed:false` | TrEMBL only |
| `length:[100 TO 500]` | Sequence length range |
| `go:0006915` | GO term (apoptosis) |
| `keyword:KW-0067` | UniProt keyword |
| `ec:2.7.1.1` | Enzyme classification |
| `database:pdb` | Has PDB cross-ref |
| `xref:pdb` | Same as above |
| `existence:1` | Evidence at protein level (1 = strongest) |

Combine: `organism_id:9606 AND reviewed:true AND keyword:KW-0067 AND xref:pdb`.

## `?fields=` for bulk pulls

Default JSON entry is ~20-30 KB. For batch work, restrict fields:

```python
fields = 'accession,id,gene_names,protein_name,length,sequence,xref_pdb,xref_alphafolddb'
url = 'https://rest.uniprot.org/uniprotkb/search'
params = {'query': 'organism_id:9606 AND reviewed:true', 'fields': fields, 'format': 'tsv', 'size': 500}
```

Common field selectors:
| Field | Returns |
|---|---|
| `accession`, `id` | Primary accession (P04637), entry name (P53_HUMAN) |
| `gene_names` | All gene names |
| `gene_primary` | Primary gene name only |
| `protein_name` | Recommended name |
| `organism_name`, `organism_id` | Species |
| `length`, `mass` | Sequence stats |
| `sequence` | The actual sequence |
| `cc_function`, `cc_subcellular_location` | Function and localization comments |
| `ft_domain`, `ft_binding`, `ft_active_site` | Domain/site features |
| `go_p`, `go_c`, `go_f` | GO biological process / cellular component / molecular function |
| `xref_pdb`, `xref_alphafolddb`, `xref_ensembl`, `xref_refseq` | Cross-references |
| `keyword` | UniProt keywords |
| `ec` | Enzyme classification |
| `reviewed` | Swiss-Prot vs TrEMBL flag |
| `cc_alternative_products` | Isoforms |

## Stream vs search vs accessions

| Endpoint | When | Limit |
|---|---|---|
| `/uniprotkb/{acc}` | One accession | 1 entry |
| `/uniprotkb/accessions?accessions=...` | Several known accessions | Up to ~100 per call |
| `/uniprotkb/search?query=...` | Query-driven; need pagination | 500 results per page; `cursor=` for paging |
| `/uniprotkb/stream?query=...` | Bulk query (>500) | No hard limit; one HTTP stream |

For 1000+ results, `/stream` is the right endpoint. Stream returns one HTTP response; iterate over the stream to avoid memory blowup.

## JSON schema navigation (the post-2022 layout)

The new schema is deeply nested. Common access patterns:

```python
entry = requests.get('https://rest.uniprot.org/uniprotkb/P04637.json').json()

acc = entry['primaryAccession']                                                # 'P04637'
entry_name = entry['uniProtkbId']                                              # 'P53_HUMAN'
sequence = entry['sequence']['value']                                          # actual AA sequence
length = entry['sequence']['length']

# Names (nested; defensive .get() because some fields are optional)
recommended = entry.get('proteinDescription', {}).get('recommendedName', {}).get('fullName', {}).get('value')
primary_gene = entry.get('genes', [{}])[0].get('geneName', {}).get('value')

# Cross-references
xrefs_by_db = {}
for xref in entry.get('uniProtKBCrossReferences', []):
    xrefs_by_db.setdefault(xref['database'], []).append(xref['id'])

# Features (domains, binding sites)
domains = [f for f in entry.get('features', []) if f['type'] == 'Domain']
binding = [f for f in entry.get('features', []) if f['type'] == 'Binding site']

# Isoforms
isoforms = []
for comment in entry.get('comments', []):
    if comment.get('commentType') == 'ALTERNATIVE PRODUCTS':
        isoforms = [iso['name']['value'] for iso in comment.get('isoforms', [])]
```

## Isoform handling

Canonical sequence is returned for the bare accession (e.g. `P04637`). Isoforms have `-2`, `-3`, etc. suffixes (`P04637-2`). To fetch a specific isoform:

```python
iso = requests.get('https://rest.uniprot.org/uniprotkb/P04637-2.fasta').text
```

The canonical entry's `comments[type=ALTERNATIVE PRODUCTS]` lists all isoforms with their differences. For workflows needing all isoforms, iterate the list and fetch separately.

## ID Mapping API (async)

Convert between identifier systems (Ensembl Gene -> UniProt; PDB -> UniProt; UniProt -> RefSeq; etc.). The job pattern:

1. **Submit**: `POST /idmapping/run` with `ids`, `from`, `to`.
2. **Poll**: `GET /idmapping/status/{jobId}` — returns `{'jobStatus': 'RUNNING'}` or `{'results': [...]}`.
3. **Fetch**: `GET /idmapping/results/{jobId}` once status is complete.

Job typically completes in 30s; larger batches take 5-10 min. **Always set a poll timeout** — the API doesn't fail-soft on stuck jobs.

| From | To | Notes |
|---|---|---|
| `UniProtKB_AC-ID` | `UniProtKB` | Resolve obsolete to current accessions |
| `Gene_Name` | `UniProtKB` | Symbol -

Related in Backend & APIs