[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M73K513Y93P20AW231SHCW0B":3,"skill-same:01M73K513Y93P20AW231SHCW0B":50},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":26,"commitSha":27,"skillDirectory":28,"forksCount":29,"repositoryHtmlUrl":30,"repositoryHomepageUrl":31,"ownerHtmlUrl":32,"ownerBlogUrl":33,"ownerDescription":34,"updatedAt":35,"install":36,"resources":49},"01M73K513Y93P20AW231SHCW0B","uniprot-protein-database",null,"Query UniProt REST API: search by gene\u002Fprotein name, fetch FASTA, map IDs (Ensembl, PDB, RefSeq), access Swiss-Prot annotations. Use bioservices for multi-DB access; alphafold-database-access for structures.","bg-szy\u002FTOP-SKILLS","bg-szy","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F106576190?v=4","01M73A4E8KPV67SFXRY8XZGNBX","ShuZhiyong","01M73A4E96MQ294MHM74TZBVQD",6,"CC-BY-4.0","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fawesome-skills\u002Funiprot-protein-database\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: uniprot-protein-database\ndescription: \"Query UniProt REST API: search by gene\u002Fprotein name, fetch FASTA, map IDs (Ensembl, PDB, RefSeq), access Swiss-Prot annotations. Use bioservices for multi-DB access; alphafold-database-access for structures.\"\nlicense: CC-BY-4.0\nmetadata:\n  quick_use: 'one entry: GET https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002F{ACC}.json?fields=accession,protein_name,gene_names,organism_name,length -> primaryAccession, proteinDescription.recommendedName.fullName.value, sequence.length. By gene: GET https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch?query=gene_exact:EGFR AND organism_id:9606 AND reviewed:true&fields=\u003Csame>&format=json -> results[0]. Unknown accession -> 404, malformed -> 400, a deleted entry -> 200 with entryType ''Inactive'' and inactiveReason (not a live protein). Cite https:\u002F\u002Fwww.uniprot.org\u002Funiprotkb\u002F{ACC}\u002Fentry'\n---\n\n# UniProt — Protein Database\n\n## Overview\n\nUniProt is the most comprehensive protein sequence and functional annotation database, containing 250M+ entries. This skill covers programmatic access via the UniProt REST API for protein search, sequence retrieval, ID mapping, and annotation queries. Swiss-Prot entries are manually curated; TrEMBL entries are computationally predicted.\n\n## When to Use\n\n- Searching for proteins by gene name, accession, organism, or function keywords\n- Retrieving protein sequences in FASTA format for downstream analysis\n- Mapping identifiers between databases (UniProt ↔ Ensembl, PDB, RefSeq, KEGG)\n- Accessing protein annotations: GO terms, domains, post-translational modifications\n- Batch retrieving multiple protein entries for comparative analysis\n- Downloading reviewed (Swiss-Prot) protein datasets for a specific organism\n- For **unified access to 40+ databases**, use bioservices instead\n- For **protein 3D structures**, use alphafold-database-access or pdb-database\n\n## Prerequisites\n\n```bash\npip install requests pandas\n```\n\n**API Rate Limits**: UniProt REST API has no strict rate limit but recommends adding `time.sleep(0.5)` between batch requests. For large queries (>10k results), use the streaming endpoint instead of paginated search. Maximum 100,000 IDs per ID mapping job.\n\n## Quick Start\n\n```python\nimport requests\n\n# Search for human insulin proteins (reviewed\u002FSwiss-Prot only)\nurl = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\"\nparams = {\"query\": \"insulin AND organism_id:9606 AND reviewed:true\", \"format\": \"tsv\",\n          \"fields\": \"accession,gene_names,protein_name,length\"}\nresponse = requests.get(url, params=params)\nprint(response.text[:500])\n# accession  gene_names  protein_name  length\n# P01308     INS         Insulin       110\n```\n\n## Core API\n\n### 1. Protein Search\n\nSearch UniProt with structured queries combining Boolean operators and field-specific filters.\n\n```python\nimport requests\nimport time\n\nBASE = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\"\n\ndef search_uniprot(query, fields=None, format=\"json\", size=25):\n    \"\"\"Search UniProt with query syntax.\"\"\"\n    params = {\"query\": query, \"format\": format, \"size\": size}\n    if fields:\n        params[\"fields\"] = \",\".join(fields)\n    resp = requests.get(BASE, params=params)\n    resp.raise_for_status()\n    return resp.json() if format == \"json\" else resp.text\n\n# Search by gene name\nresults = search_uniprot(\"gene:BRCA1 AND reviewed:true\",\n                         fields=[\"accession\", \"gene_names\", \"organism_name\", \"length\"])\nfor entry in results[\"results\"][:3]:\n    print(f\"{entry['primaryAccession']} | {entry.get('genes', [{}])[0].get('geneName', {}).get('value', 'N\u002FA')} | {entry.get('organism', {}).get('scientificName', 'N\u002FA')}\")\n```\n\n**Query syntax reference**:\n```\n# Boolean operators\nkinase AND organism_id:9606          # Human kinases\n(diabetes OR insulin) AND reviewed:true\ncancer NOT lung\n\n# Field-specific\ngene:BRCA1\naccession:P12345\ntaxonomy_name:\"Homo sapiens\"\ngo:0005515                           # GO term: protein binding\n\n# Range queries\nlength:[100 TO 500]\nmass:[50000 TO 100000]\n\n# Wildcards\ngene:BRCA*\n```\n\n### 2. Protein Entry Retrieval\n\nRetrieve individual protein entries by accession number.\n\n```python\nimport requests\n\ndef get_protein(accession, format=\"json\"):\n    \"\"\"Retrieve a single protein entry.\"\"\"\n    url = f\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002F{accession}\"\n    resp = requests.get(url, headers={\"Accept\": f\"application\u002F{format}\"})\n    resp.raise_for_status()\n    return resp.json() if format == \"json\" else resp.text\n\n# Get human insulin\nentry = get_protein(\"P01308\")\nprint(f\"Protein: {entry['proteinDescription']['recommendedName']['fullName']['value']}\")\nprint(f\"Gene: {entry['genes'][0]['geneName']['value']}\")\nprint(f\"Length: {entry['sequence']['length']} aa\")\nprint(f\"Sequence: {entry['sequence']['value'][:50]}...\")\n\n# Get FASTA directly\nfasta = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002FP01308.fasta\").text\nprint(fasta[:200])\n```\n\n### 3. ID Mapping\n\nMap identifiers between UniProt and other databases.\n\n```python\nimport requests\nimport time\n\ndef map_ids(ids, from_db, to_db):\n    \"\"\"Map identifiers between databases (async job).\"\"\"\n    # Submit job\n    resp = requests.post(\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Frun\",\n                         data={\"from\": from_db, \"to\": to_db, \"ids\": \",\".join(ids)})\n    resp.raise_for_status()\n    job_id = resp.json()[\"jobId\"]\n\n    # Poll for completion\n    while True:\n        status = requests.get(f\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Fstatus\u002F{job_id}\").json()\n        if \"results\" in status or \"failedIds\" in status:\n            break\n        time.sleep(1)\n\n    # Get results\n    results = requests.get(f\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Fresults\u002F{job_id}\").json()\n    return results\n\n# UniProt → PDB mapping\nresults = map_ids([\"P01308\", \"P12345\"], from_db=\"UniProtKB_AC-ID\", to_db=\"PDB\")\nfor r in results.get(\"results\", []):\n    print(f\"{r['from']} → PDB: {r['to']}\")\n\n# UniProt → Ensembl mapping\nresults = map_ids([\"P01308\"], from_db=\"UniProtKB_AC-ID\", to_db=\"Ensembl\")\nfor r in results.get(\"results\", []):\n    print(f\"{r['from']} → Ensembl: {r['to']}\")\n```\n\n**Common database codes**: `UniProtKB_AC-ID`, `Ensembl`, `RefSeq_Protein`, `PDB`, `Gene_Name`, `GeneID`, `KEGG`\n\n### 4. Batch Retrieval and Streaming\n\nRetrieve large datasets efficiently.\n\n```python\nimport requests\nimport time\n\ndef batch_retrieve(accessions, fields=None, format=\"tsv\"):\n    \"\"\"Retrieve multiple proteins by accession.\"\"\"\n    query = \" OR \".join(f\"accession:{acc}\" for acc in accessions)\n    params = {\"query\": query, \"format\": format}\n    if fields:\n        params[\"fields\"] = \",\".join(fields)\n    resp = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\", params=params)\n    resp.raise_for_status()\n    return resp.text\n\n# Batch retrieve\naccessions = [\"P01308\", \"P12345\", \"Q9Y6K9\"]\ntsv = batch_retrieve(accessions, fields=[\"accession\", \"gene_names\", \"protein_name\", \"length\"])\nprint(tsv)\n\n# Streaming for large queries (no pagination needed)\ndef stream_query(query, format=\"fasta\"):\n    \"\"\"Stream large result sets.\"\"\"\n    url = f\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fstream?query={query}&format={format}\"\n    resp = requests.get(url, stream=True)\n    resp.raise_for_status()\n    for chunk in resp.iter_content(chunk_size=8192, decode_unicode=True):\n        yield chunk\n\n# Stream all human kinases as FASTA\n# for chunk in stream_query(\"kinase AND organism_id:9606 AND reviewed:true\"):\n#     print(chunk[:200])\n```\n\n### 5. Pagination and Cursor-Based Iteration\n\nHandle large result sets with pagination using the `Link` header cursor.\n\n```python\nimport requests\n\ndef paginate_search(query, fields=None, page_size=500):\n    \"\"\"Iterate all pages of a UniProt search using cursor pagination.\"\"\"\n    params = {\"query\": query, \"format\": \"tsv\", \"size\": page_size}\n    if fields:\n        params[\"fields\"] = \",\".join(fields)\n    url = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\"\n    rows = []\n    header = None\n    while url:\n        resp = requests.get(url, params=params)\n        resp.raise_for_status()\n        params = {}  # cursor is embedded in the next URL\n        lines = resp.text.strip().split(\"\\n\")\n        if header is None:\n            header = lines[0]\n        rows.extend(lines[1:])\n        # Follow Link header for next page\n        link = resp.headers.get(\"Link\", \"\")\n        url = link.split(\"\u003C\")[1].split(\">\")[0] if \"\u003C\" in link else None\n    return header, rows\n\nheader, rows = paginate_search(\n    \"kinase AND organism_id:9606 AND reviewed:true\",\n    fields=[\"accession\", \"gene_names\", \"length\"]\n)\nprint(f\"Retrieved {len(rows)} proteins\")\nprint(header)\nprint(\"\\n\".join(rows[:3]))\n```\n\n### 6. Field Selection and Annotations\n\nCustomize which data fields to retrieve.\n\n```python\nimport requests\nimport pandas as pd\nfrom io import StringIO\n\n# Retrieve specific annotation fields\nparams = {\n    \"query\": \"gene:TP53 AND organism_id:9606 AND reviewed:true\",\n    \"format\": \"tsv\",\n    \"fields\": \"accession,gene_names,protein_name,go_p,go_f,go_c,cc_function,ft_domain\",\n}\nresp = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\", params=params)\ndf = pd.read_csv(StringIO(resp.text), sep=\"\\t\")\nprint(df.columns.tolist())\nprint(df.iloc[0])\n```\n\n**Common field groups**:\n- Sequence: `accession`, `sequence`, `length`, `mass`\n- Names: `gene_names`, `protein_name`, `organism_name`\n- GO: `go_p` (process), `go_f` (function), `go_c` (component)\n- Features: `ft_domain`, `ft_binding`, `ft_act_site`, `ft_mod_res`\n- Comments: `cc_function`, `cc_interaction`, `cc_subcellular_location`\n\n## Key Parameters\n\n| Parameter | Function\u002FEndpoint | Default | Range \u002F Options | Effect |\n|-----------|-------------------|---------|-----------------|--------|\n| `query` | `\u002Fsearch`, `\u002Fstream` | — | UniProt query syntax | Filter proteins by criteria |\n| `format` | All endpoints | `json` | `json`, `tsv`, `fasta`, `xml`, `gff` | Output format |\n| `fields` | `\u002Fsearch` | all | Comma-separated field names | Reduces response size |\n| `size` | `\u002Fsearch` | 25 | 1–500 | Results per page |\n| `from` \u002F `to` | `\u002Fidmapping\u002Frun` | — | Database codes | ID mapping direction |\n| `reviewed:true` | Query filter | — | `true`\u002F`false` | Swiss-Prot (curated) only |\n| `organism_id` | Query filter | — | NCBI taxonomy ID | Filter by species |\n\n## Best Practices\n\n1. **Filter `reviewed:true` for curated data**: Swiss-Prot entries are manually reviewed; TrEMBL entries are computationally predicted. Use Swiss-Prot for high-confidence annotations.\n\n2. **Use TSV format with `fields` for tabular analysis**: Requesting only needed fields as TSV is faster and easier to parse than full JSON entries.\n\n3. **Use streaming for large downloads**: The `\u002Fstream` endpoint returns all results without pagination, avoiding the need for multi-page iteration.\n\n4. **Add `time.sleep(0.5)` between batch requests**: Respect API resources, especially when making many sequential requests.\n\n5. **Cache frequently accessed entries locally**: UniProt updates monthly; cache results and re-fetch only when needed.\n\n6. **Anti-pattern — querying without `organism_id`**: Broad queries like `gene:INS` return thousands of entries across all species. Always filter by organism for targeted results.\n\n## Common Recipes\n\n### Recipe: Download All Human Kinases as DataFrame\n\n```python\nimport requests\nimport pandas as pd\nfrom io import StringIO\n\nurl = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fstream\"\nparams = {\n    \"query\": \"ec:2.7.* AND organism_id:9606 AND reviewed:true\",\n    \"format\": \"tsv\",\n    \"fields\": \"accession,gene_names,protein_name,length,go_f\",\n}\nresp = requests.get(url, params=params)\ndf = pd.read_csv(StringIO(resp.text), sep=\"\\t\")\nprint(f\"Human kinases (Swiss-Prot): {len(df)}\")\nprint(df.head())\n```\n\n### Recipe: Extract GO Annotations for a Gene Set\n\n```python\nimport requests\nimport pandas as pd\nfrom io import StringIO\n\ngene_list = [\"BRCA1\", \"BRCA2\", \"TP53\", \"ATM\", \"CHEK2\"]\nquery = \" OR \".join(f\"gene:{g}\" for g in gene_list)\nquery += \" AND organism_id:9606 AND reviewed:true\"\n\nparams = {\n    \"query\": query,\n    \"format\": \"tsv\",\n    \"fields\": \"accession,gene_names,go_p,go_f,go_c\",\n}\nresp = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\", params=params)\ndf = pd.read_csv(StringIO(resp.text), sep=\"\\t\")\nprint(df[[\"Accession\", \"Gene Names\", \"Gene Ontology (biological process)\"]].head())\n```\n\n### Recipe: Cross-Reference UniProt to PDB Structures\n\n```python\nimport requests\nimport time\n\naccessions = [\"P53_HUMAN\", \"P01308\", \"P00533\"]  # TP53, Insulin, EGFR\nresp = requests.post(\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Frun\",\n                     data={\"from\": \"UniProtKB_AC-ID\", \"to\": \"PDB\", \"ids\": \",\".join(accessions)})\njob_id = resp.json()[\"jobId\"]\ntime.sleep(2)\nresults = requests.get(f\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Fresults\u002F{job_id}\").json()\nfor r in results.get(\"results\", []):\n    print(f\"{r['from']} → PDB: {r['to']}\")\n```\n\n## Troubleshooting\n\n| Problem | Cause | Solution |\n|---------|-------|----------|\n| `400 Bad Request` | Invalid query syntax | Check Boolean operators, field names, bracket matching; use UniProt query syntax docs |\n| Too many results (slow) | No organism or review filter | Add `AND organism_id:9606 AND reviewed:true` to narrow results |\n| ID mapping returns empty | Wrong database code | Verify `from`\u002F`to` codes: use `UniProtKB_AC-ID` (not `UniProtKB` alone) |\n| Pagination missing entries | Large result set | Use `\u002Fstream` endpoint instead of paginated `\u002Fsearch` |\n| `429 Too Many Requests` | Excessive API calls | Add `time.sleep(0.5)` between requests; batch accessions in single queries |\n| FASTA has no gene name | TrEMBL entry with minimal annotation | Filter `reviewed:true` for Swiss-Prot entries with full annotations |\n\n## Related Skills\n\n- **biopython-molecular-biology** — parse FASTA sequences returned by UniProt; run BLAST with retrieved sequences\n- **alphafold-database-access** — retrieve predicted 3D structures using UniProt accessions\n- **esm-protein-language-model** — generate embeddings from UniProt protein sequences\n- **gget-genomic-databases** — alternative interface for quick gene\u002Fprotein lookups across databases\n\n## References\n\n- [UniProt REST API documentation](https:\u002F\u002Fwww.uniprot.org\u002Fhelp\u002Fapi) — official API reference\n- [UniProt query syntax](https:\u002F\u002Fwww.uniprot.org\u002Fhelp\u002Fquery-fields) — field-specific search operators\n- [UniProt Consortium (2023)](https:\u002F\u002Fdoi.org\u002F10.1093\u002Fnar\u002Fgkac1052) — \"UniProt: the Universal Protein Knowledgebase in 2023\" — Nucleic Acids Research\n","# UniProt — Protein Database\n\n## Overview\n\nUniProt is the most comprehensive protein sequence and functional annotation database, containing 250M+ entries. This skill covers programmatic access via the UniProt REST API for protein search, sequence retrieval, ID mapping, and annotation queries. Swiss-Prot entries are manually curated; TrEMBL entries are computationally predicted.\n\n## When to Use\n\n- Searching for proteins by gene name, accession, organism, or function keywords\n- Retrieving protein sequences in FASTA format for downstream analysis\n- Mapping identifiers between databases (UniProt ↔ Ensembl, PDB, RefSeq, KEGG)\n- Accessing protein annotations: GO terms, domains, post-translational modifications\n- Batch retrieving multiple protein entries for comparative analysis\n- Downloading reviewed (Swiss-Prot) protein datasets for a specific organism\n- For **unified access to 40+ databases**, use bioservices instead\n- For **protein 3D structures**, use alphafold-database-access or pdb-database\n\n## Prerequisites\n\n```bash\npip install requests pandas\n```\n\n**API Rate Limits**: UniProt REST API has no strict rate limit but recommends adding `time.sleep(0.5)` between batch requests. For large queries (>10k results), use the streaming endpoint instead of paginated search. Maximum 100,000 IDs per ID mapping job.\n\n## Quick Start\n\n```python\nimport requests\n\n# Search for human insulin proteins (reviewed\u002FSwiss-Prot only)\nurl = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\"\nparams = {\"query\": \"insulin AND organism_id:9606 AND reviewed:true\", \"format\": \"tsv\",\n          \"fields\": \"accession,gene_names,protein_name,length\"}\nresponse = requests.get(url, params=params)\nprint(response.text[:500])\n# accession  gene_names  protein_name  length\n# P01308     INS         Insulin       110\n```\n\n## Core API\n\n### 1. Protein Search\n\nSearch UniProt with structured queries combining Boolean operators and field-specific filters.\n\n```python\nimport requests\nimport time\n\nBASE = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\"\n\ndef search_uniprot(query, fields=None, format=\"json\", size=25):\n    \"\"\"Search UniProt with query syntax.\"\"\"\n    params = {\"query\": query, \"format\": format, \"size\": size}\n    if fields:\n        params[\"fields\"] = \",\".join(fields)\n    resp = requests.get(BASE, params=params)\n    resp.raise_for_status()\n    return resp.json() if format == \"json\" else resp.text\n\n# Search by gene name\nresults = search_uniprot(\"gene:BRCA1 AND reviewed:true\",\n                         fields=[\"accession\", \"gene_names\", \"organism_name\", \"length\"])\nfor entry in results[\"results\"][:3]:\n    print(f\"{entry['primaryAccession']} | {entry.get('genes', [{}])[0].get('geneName', {}).get('value', 'N\u002FA')} | {entry.get('organism', {}).get('scientificName', 'N\u002FA')}\")\n```\n\n**Query syntax reference**:\n```\n# Boolean operators\nkinase AND organism_id:9606          # Human kinases\n(diabetes OR insulin) AND reviewed:true\ncancer NOT lung\n\n# Field-specific\ngene:BRCA1\naccession:P12345\ntaxonomy_name:\"Homo sapiens\"\ngo:0005515                           # GO term: protein binding\n\n# Range queries\nlength:[100 TO 500]\nmass:[50000 TO 100000]\n\n# Wildcards\ngene:BRCA*\n```\n\n### 2. Protein Entry Retrieval\n\nRetrieve individual protein entries by accession number.\n\n```python\nimport requests\n\ndef get_protein(accession, format=\"json\"):\n    \"\"\"Retrieve a single protein entry.\"\"\"\n    url = f\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002F{accession}\"\n    resp = requests.get(url, headers={\"Accept\": f\"application\u002F{format}\"})\n    resp.raise_for_status()\n    return resp.json() if format == \"json\" else resp.text\n\n# Get human insulin\nentry = get_protein(\"P01308\")\nprint(f\"Protein: {entry['proteinDescription']['recommendedName']['fullName']['value']}\")\nprint(f\"Gene: {entry['genes'][0]['geneName']['value']}\")\nprint(f\"Length: {entry['sequence']['length']} aa\")\nprint(f\"Sequence: {entry['sequence']['value'][:50]}...\")\n\n# Get FASTA directly\nfasta = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002FP01308.fasta\").text\nprint(fasta[:200])\n```\n\n### 3. ID Mapping\n\nMap identifiers between UniProt and other databases.\n\n```python\nimport requests\nimport time\n\ndef map_ids(ids, from_db, to_db):\n    \"\"\"Map identifiers between databases (async job).\"\"\"\n    # Submit job\n    resp = requests.post(\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Frun\",\n                         data={\"from\": from_db, \"to\": to_db, \"ids\": \",\".join(ids)})\n    resp.raise_for_status()\n    job_id = resp.json()[\"jobId\"]\n\n    # Poll for completion\n    while True:\n        status = requests.get(f\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Fstatus\u002F{job_id}\").json()\n        if \"results\" in status or \"failedIds\" in status:\n            break\n        time.sleep(1)\n\n    # Get results\n    results = requests.get(f\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Fresults\u002F{job_id}\").json()\n    return results\n\n# UniProt → PDB mapping\nresults = map_ids([\"P01308\", \"P12345\"], from_db=\"UniProtKB_AC-ID\", to_db=\"PDB\")\nfor r in results.get(\"results\", []):\n    print(f\"{r['from']} → PDB: {r['to']}\")\n\n# UniProt → Ensembl mapping\nresults = map_ids([\"P01308\"], from_db=\"UniProtKB_AC-ID\", to_db=\"Ensembl\")\nfor r in results.get(\"results\", []):\n    print(f\"{r['from']} → Ensembl: {r['to']}\")\n```\n\n**Common database codes**: `UniProtKB_AC-ID`, `Ensembl`, `RefSeq_Protein`, `PDB`, `Gene_Name`, `GeneID`, `KEGG`\n\n### 4. Batch Retrieval and Streaming\n\nRetrieve large datasets efficiently.\n\n```python\nimport requests\nimport time\n\ndef batch_retrieve(accessions, fields=None, format=\"tsv\"):\n    \"\"\"Retrieve multiple proteins by accession.\"\"\"\n    query = \" OR \".join(f\"accession:{acc}\" for acc in accessions)\n    params = {\"query\": query, \"format\": format}\n    if fields:\n        params[\"fields\"] = \",\".join(fields)\n    resp = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\", params=params)\n    resp.raise_for_status()\n    return resp.text\n\n# Batch retrieve\naccessions = [\"P01308\", \"P12345\", \"Q9Y6K9\"]\ntsv = batch_retrieve(accessions, fields=[\"accession\", \"gene_names\", \"protein_name\", \"length\"])\nprint(tsv)\n\n# Streaming for large queries (no pagination needed)\ndef stream_query(query, format=\"fasta\"):\n    \"\"\"Stream large result sets.\"\"\"\n    url = f\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fstream?query={query}&format={format}\"\n    resp = requests.get(url, stream=True)\n    resp.raise_for_status()\n    for chunk in resp.iter_content(chunk_size=8192, decode_unicode=True):\n        yield chunk\n\n# Stream all human kinases as FASTA\n# for chunk in stream_query(\"kinase AND organism_id:9606 AND reviewed:true\"):\n#     print(chunk[:200])\n```\n\n### 5. Pagination and Cursor-Based Iteration\n\nHandle large result sets with pagination using the `Link` header cursor.\n\n```python\nimport requests\n\ndef paginate_search(query, fields=None, page_size=500):\n    \"\"\"Iterate all pages of a UniProt search using cursor pagination.\"\"\"\n    params = {\"query\": query, \"format\": \"tsv\", \"size\": page_size}\n    if fields:\n        params[\"fields\"] = \",\".join(fields)\n    url = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\"\n    rows = []\n    header = None\n    while url:\n        resp = requests.get(url, params=params)\n        resp.raise_for_status()\n        params = {}  # cursor is embedded in the next URL\n        lines = resp.text.strip().split(\"\\n\")\n        if header is None:\n            header = lines[0]\n        rows.extend(lines[1:])\n        # Follow Link header for next page\n        link = resp.headers.get(\"Link\", \"\")\n        url = link.split(\"\u003C\")[1].split(\">\")[0] if \"\u003C\" in link else None\n    return header, rows\n\nheader, rows = paginate_search(\n    \"kinase AND organism_id:9606 AND reviewed:true\",\n    fields=[\"accession\", \"gene_names\", \"length\"]\n)\nprint(f\"Retrieved {len(rows)} proteins\")\nprint(header)\nprint(\"\\n\".join(rows[:3]))\n```\n\n### 6. Field Selection and Annotations\n\nCustomize which data fields to retrieve.\n\n```python\nimport requests\nimport pandas as pd\nfrom io import StringIO\n\n# Retrieve specific annotation fields\nparams = {\n    \"query\": \"gene:TP53 AND organism_id:9606 AND reviewed:true\",\n    \"format\": \"tsv\",\n    \"fields\": \"accession,gene_names,protein_name,go_p,go_f,go_c,cc_function,ft_domain\",\n}\nresp = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\", params=params)\ndf = pd.read_csv(StringIO(resp.text), sep=\"\\t\")\nprint(df.columns.tolist())\nprint(df.iloc[0])\n```\n\n**Common field groups**:\n- Sequence: `accession`, `sequence`, `length`, `mass`\n- Names: `gene_names`, `protein_name`, `organism_name`\n- GO: `go_p` (process), `go_f` (function), `go_c` (component)\n- Features: `ft_domain`, `ft_binding`, `ft_act_site`, `ft_mod_res`\n- Comments: `cc_function`, `cc_interaction`, `cc_subcellular_location`\n\n## Key Parameters\n\n| Parameter | Function\u002FEndpoint | Default | Range \u002F Options | Effect |\n|-----------|-------------------|---------|-----------------|--------|\n| `query` | `\u002Fsearch`, `\u002Fstream` | — | UniProt query syntax | Filter proteins by criteria |\n| `format` | All endpoints | `json` | `json`, `tsv`, `fasta`, `xml`, `gff` | Output format |\n| `fields` | `\u002Fsearch` | all | Comma-separated field names | Reduces response size |\n| `size` | `\u002Fsearch` | 25 | 1–500 | Results per page |\n| `from` \u002F `to` | `\u002Fidmapping\u002Frun` | — | Database codes | ID mapping direction |\n| `reviewed:true` | Query filter | — | `true`\u002F`false` | Swiss-Prot (curated) only |\n| `organism_id` | Query filter | — | NCBI taxonomy ID | Filter by species |\n\n## Best Practices\n\n1. **Filter `reviewed:true` for curated data**: Swiss-Prot entries are manually reviewed; TrEMBL entries are computationally predicted. Use Swiss-Prot for high-confidence annotations.\n\n2. **Use TSV format with `fields` for tabular analysis**: Requesting only needed fields as TSV is faster and easier to parse than full JSON entries.\n\n3. **Use streaming for large downloads**: The `\u002Fstream` endpoint returns all results without pagination, avoiding the need for multi-page iteration.\n\n4. **Add `time.sleep(0.5)` between batch requests**: Respect API resources, especially when making many sequential requests.\n\n5. **Cache frequently accessed entries locally**: UniProt updates monthly; cache results and re-fetch only when needed.\n\n6. **Anti-pattern — querying without `organism_id`**: Broad queries like `gene:INS` return thousands of entries across all species. Always filter by organism for targeted results.\n\n## Common Recipes\n\n### Recipe: Download All Human Kinases as DataFrame\n\n```python\nimport requests\nimport pandas as pd\nfrom io import StringIO\n\nurl = \"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fstream\"\nparams = {\n    \"query\": \"ec:2.7.* AND organism_id:9606 AND reviewed:true\",\n    \"format\": \"tsv\",\n    \"fields\": \"accession,gene_names,protein_name,length,go_f\",\n}\nresp = requests.get(url, params=params)\ndf = pd.read_csv(StringIO(resp.text), sep=\"\\t\")\nprint(f\"Human kinases (Swiss-Prot): {len(df)}\")\nprint(df.head())\n```\n\n### Recipe: Extract GO Annotations for a Gene Set\n\n```python\nimport requests\nimport pandas as pd\nfrom io import StringIO\n\ngene_list = [\"BRCA1\", \"BRCA2\", \"TP53\", \"ATM\", \"CHEK2\"]\nquery = \" OR \".join(f\"gene:{g}\" for g in gene_list)\nquery += \" AND organism_id:9606 AND reviewed:true\"\n\nparams = {\n    \"query\": query,\n    \"format\": \"tsv\",\n    \"fields\": \"accession,gene_names,go_p,go_f,go_c\",\n}\nresp = requests.get(\"https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch\", params=params)\ndf = pd.read_csv(StringIO(resp.text), sep=\"\\t\")\nprint(df[[\"Accession\", \"Gene Names\", \"Gene Ontology (biological process)\"]].head())\n```\n\n### Recipe: Cross-Reference UniProt to PDB Structures\n\n```python\nimport requests\nimport time\n\naccessions = [\"P53_HUMAN\", \"P01308\", \"P00533\"]  # TP53, Insulin, EGFR\nresp = requests.post(\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Frun\",\n                     data={\"from\": \"UniProtKB_AC-ID\", \"to\": \"PDB\", \"ids\": \",\".join(accessions)})\njob_id = resp.json()[\"jobId\"]\ntime.sleep(2)\nresults = requests.get(f\"https:\u002F\u002Frest.uniprot.org\u002Fidmapping\u002Fresults\u002F{job_id}\").json()\nfor r in results.get(\"results\", []):\n    print(f\"{r['from']} → PDB: {r['to']}\")\n```\n\n## Troubleshooting\n\n| Problem | Cause | Solution |\n|---------|-------|----------|\n| `400 Bad Request` | Invalid query syntax | Check Boolean operators, field names, bracket matching; use UniProt query syntax docs |\n| Too many results (slow) | No organism or review filter | Add `AND organism_id:9606 AND reviewed:true` to narrow results |\n| ID mapping returns empty | Wrong database code | Verify `from`\u002F`to` codes: use `UniProtKB_AC-ID` (not `UniProtKB` alone) |\n| Pagination missing entries | Large result set | Use `\u002Fstream` endpoint instead of paginated `\u002Fsearch` |\n| `429 Too Many Requests` | Excessive API calls | Add `time.sleep(0.5)` between requests; batch accessions in single queries |\n| FASTA has no gene name | TrEMBL entry with minimal annotation | Filter `reviewed:true` for Swiss-Prot entries with full annotations |\n\n## Related Skills\n\n- **biopython-molecular-biology** — parse FASTA sequences returned by UniProt; run BLAST with retrieved sequences\n- **alphafold-database-access** — retrieve predicted 3D structures using UniProt accessions\n- **esm-protein-language-model** — generate embeddings from UniProt protein sequences\n- **gget-genomic-databases** — alternative interface for quick gene\u002Fprotein lookups across databases\n\n## References\n\n- [UniProt REST API documentation](https:\u002F\u002Fwww.uniprot.org\u002Fhelp\u002Fapi) — official API reference\n- [UniProt query syntax](https:\u002F\u002Fwww.uniprot.org\u002Fhelp\u002Fquery-fields) — field-specific search operators\n- [UniProt Consortium (2023)](https:\u002F\u002Fdoi.org\u002F10.1093\u002Fnar\u002Fgkac1052) — \"UniProt: the Universal Protein Knowledgebase in 2023\" — Nucleic Acids Research\n",{"name":5,"license":15,"metadata":24,"description":7},{"quick_use":25},"one entry: GET https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002F{ACC}.json?fields=accession,protein_name,gene_names,organism_name,length -> primaryAccession, proteinDescription.recommendedName.fullName.value, sequence.length. By gene: GET https:\u002F\u002Frest.uniprot.org\u002Funiprotkb\u002Fsearch?query=gene_exact:EGFR AND organism_id:9606 AND reviewed:true&fields=\u003Csame>&format=json -> results[0]. Unknown accession -> 404, malformed -> 400, a deleted entry -> 200 with entryType 'Inactive' and inactiveReason (not a live protein). Cite https:\u002F\u002Fwww.uniprot.org\u002Funiprotkb\u002F{ACC}\u002Fentry","master","fd76f882a04e445e899d5cfb2732f2105ea054ee","skills\u002Fawesome-skills\u002Funiprot-protein-database",0,"https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS","https:\u002F\u002Fbg-szy.github.io\u002FTOP-SKILLS\u002F","https:\u002F\u002Fgithub.com\u002Fbg-szy","https:\u002F\u002Fwww.ecust.edu.cn\u002F","a student of East China University of Science and Technology","2026-11-15 03:38:02",{"source":8,"skillName":5,"commands":37,"prompt":47,"zipAvailable":48},[38,41,44],{"tool":39,"command":40},"npx","npx skills add bg-szy\u002FTOP-SKILLS --skill uniprot-protein-database",{"tool":42,"command":43},"bunx","bunx skills add bg-szy\u002FTOP-SKILLS --skill uniprot-protein-database",{"tool":45,"command":46},"pnpm","pnpm dlx skills add bg-szy\u002FTOP-SKILLS --skill uniprot-protein-database","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fawesome-skills\u002Funiprot-protein-database\u002FSKILL.md",true,[],[51,61,69,77,86,93],{"skillNo":52,"name":53,"nameZh":6,"description":54,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":55,"licenseFileUrl":56,"sourceHtmlUrl":57,"categories":58,"keywords":59,"publishedAt":60},"01M748668J70YKWKS2VFVZ0ZRF","xlsx","Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .xltx, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like \"the xlsx in my downloads\") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fxlsx\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fxlsx\u002FSKILL.md",[],[],"2026-11-12 13:55:43",{"skillNo":62,"name":63,"nameZh":6,"description":64,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":55,"licenseFileUrl":65,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":60},"01M747X09GNGYJ7V4YE3NGGH7A","pptx","Use this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates (.potx), layouts, speaker notes, or comments. Trigger whenever the user mentions \"deck,\" \"slides,\" \"presentation,\" or references a .pptx or .potx filename, regardless of what they plan to do with the content afterward. If a .pptx or .potx file needs to be opened, created, or touched, use this skill.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fpptx\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fpptx\u002FSKILL.md",[],[],{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":55,"licenseFileUrl":73,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":60},"01M747QR3VN12KXYDZGRXETTGS","docx","Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files) or Word templates (.dotx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', '.dotx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx or .dotx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fdocx\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fdocx\u002FSKILL.md",[],[],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":81,"licenseFileUrl":82,"sourceHtmlUrl":83,"categories":84,"keywords":85,"publishedAt":60},"01M76KTXGSTXVVDC7YSBM41ZZS","wxpusher-integration","Use when（适用场景）：用户明确询问、指定或上下文已选定 WxPusher，需要了解、接入或排查通知（含微信 ClawBot\u002FiLink、appToken、UID、Topic、SPT）；仅说“微信通知”、未选服务商，或只出现通用 UID\u002FTopic 时不触发。","MIT","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fmarketplace\u002Fwxpusher-integration\u002FLICENSE.md","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fmarketplace\u002Fwxpusher-integration\u002FSKILL.md",[],[],{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":81,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":19},"01M748C5DS5BQBVBMG22FCGG34","branding","When the user wants to define, audit, or apply brand strategy—purpose, values, positioning, storytelling, voice, narrative (not only visuals). Also use when the user mentions \"brand strategy\", \"brand story\", \"brand storytelling\" or \"brand voice\". For typography, colors, design tokens, and frontend visuals, use brand-visual-generator.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fsuperskills\u002Fbranding\u002FSKILL.md",[],[],{"skillNo":94,"name":95,"nameZh":6,"description":96,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":81,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":19},"01M748C1GXJ9WRKP18X45DKP6G","brand-visual-generator","When the user wants to define, audit, or apply visual identity (typography, colors, spacing, design tokens, frontend aesthetics). Also use when the user mentions \"brand style guide\", \"visual identity\", \"design system\" or \"typography\". For brand story, positioning, and voice, use branding.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fsuperskills\u002Fbrand-visual-generator\u002FSKILL.md",[],[]]