Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Search NCBI databases using Biopython Bio.Entrez. Use when finding records by keyword, building complex search queries, discovering database structure, or getting global query counts across databases.
.claude/skills/bio-entrez-search/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-11 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 130% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 108% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 155% | 0% |
| case-07 | ✓→✓ | = Same ✓ | 129% | 0% |
<!--
#
#
-->
Search NCBI databases using Biopython's Entrez module (ESearch, EInfo, EGQuery utilities).
pythonfrom Bio import Entrez Entrez.email = 'your.email@example.com' # Required by NCBI Entrez.api_key = 'your_api_key' # Optional, raises rate limit 3->10 req/sec
Search any NCBI database and get matching record IDs.
pythonhandle = Entrez.esearch(db='nucleotide', term='human[orgn] AND BRCA1[gene]') record = Entrez.read(handle) handle.close() print(f"Found {record['Count']} records") print(f"IDs: {record['IdList']}") # First 20 IDs by default
Key Parameters: | Parameter | Description | Default | |-----------|-------------|---------| | db | Database to search | Required | | term | Search query | Required | | retmax | Max IDs to return | 20 | | retstart | Starting index (pagination) | 0 | | usehistory | Store results on server | 'n' | | sort | Sort order | database-specific | | datetype | Date field to search | 'pdat' | | reldate | Records from last N days | None | | mindate | Start date (YYYY/MM/DD) | None | | maxdate | End date (YYYY/MM/DD) | None |
ESearch Result Fields:
pythonrecord['Count'] # Total matching records (string) record['IdList'] # List of record IDs record['RetMax'] # Number of IDs returned record['RetStart'] # Starting index record['QueryKey'] # For history server (if usehistory='y') record['WebEnv'] # For history server (if usehistory='y') record['TranslationSet'] # Query translations applied record['QueryTranslation'] # Final translated query
Get information about available databases or specific database fields.
python# List all available databases handle = Entrez.einfo() record = Entrez.read(handle) handle.close() print(record['DbList']) # ['pubmed', 'protein', 'nucleotide', ...] # Get info about specific database handle = Entrez.einfo(db='nucleotide') record = Entrez.read(handle) handle.close() print(f"Description: {record['DbInfo']['Description']}") print(f"Record count: {record['DbInfo']['Count']}") # List searchable fields for field in record['DbInfo']['FieldList']: print(f"{field['Name']}: {field['Description']}")
Database Info Fields:
pythonrecord['DbInfo']['DbName'] # Database name record['DbInfo']['Description'] # Database description record['DbInfo']['Count'] # Total records in database record['DbInfo']['LastUpdate'] # Last update date record['DbInfo']['FieldList'] # Searchable fields record['DbInfo']['LinkList'] # Available links to other databases
Search across all NCBI databases simultaneously.
pythonhandle = Entrez.egquery(term='CRISPR') record = Entrez.read(handle) handle.close() for result in record['eGQueryResult']: if int(result['Count']) > 0: print(f"{result['DbName']}: {result['Count']} records")
NCBI uses a specific query syntax:
python# Search specific fields using [field_name] term = 'BRCA1[gene]' # Gene name field term = 'human[orgn]' # Organism field term = 'Homo sapiens[ORGN]' # Full organism name term = 'NM_007294[accn]' # Accession number term = 'Smith J[auth]' # Author (PubMed) term = 'Nature[jour]' # Journal (PubMed) term = '1000:5000[slen]' # Sequence length range term = 'mRNA[fkey]' # Feature key
pythonterm = 'BRCA1 AND human' # Both terms term = 'cancer OR tumor' # Either term term = 'human NOT mouse' # Exclude term term = '(BRCA1 OR BRCA2) AND human' # Grouping
python# Using date parameters handle = Entrez.esearch( db='pubmed', term='CRISPR', datetype='pdat', # Publication date mindate='2023/01/01', maxdate='2024/12/31' ) # Or in query string term = 'CRISPR AND 2024[pdat]' term = 'CRISPR AND 2023:2024[pdat]'
pythonterm = 'immun*' # Wildcard term = '"breast cancer"[title]' # Exact phrase
| Database | db value | Common Fields | |----------|------------|---------------| | PubMed | pubmed | [auth], [title], [jour], [pdat] | | Nucleotide | nucleotide | [orgn], [gene], [accn], [slen] | | Protein | protein | [orgn], [gene], [accn], [molwt] | | Gene | gene | [orgn], [sym], [chr] | | SRA | sra | [orgn], [platform], [strategy] | | Taxonomy | taxonomy | [scin], [comn], [rank] | | Assembly | assembly | [orgn], [level], [refseq] |
pythonfrom Bio import Entrez Entrez.email = 'your.email@example.com' def search_ncbi(db, term, max_results=100): handle = Entrez.esearch(db=db, term=term, retmax=max_results) record = Entrez.read(handle) handle.close() return record['IdList'], int(record['Count']) ids, total = search_ncbi('nucleotide', 'human[orgn] AND insulin[gene]') print(f'Retrieved {len(ids)} of {total} total records')
pythondef search_all_ids(db, term, batch_size=10000): all_ids = [] handle = Entrez.esearch(db=db, term=term, retmax=0) record = Entrez.read(handle) handle.close() total = int(record['Count']) for start in range(0, total, batch_size): handle = Entrez.esearch(db=db, term=term, retstart=start, retmax=batch_size) record = Entrez.read(handle) handle.close() all_ids.extend(record['IdList']) return all_ids
python# Store results on NCBI server for subsequent fetching handle = Entrez.esearch(db='nucleotide', term='human[orgn] AND mRNA[fkey]', usehistory='y') record = Entrez.read(handle) handle.close() webenv = record['WebEnv'] query_key = record['QueryKey'] total = int(record['Count']) # Use webenv and query_key with efetch for batch downloads # See batch-downloads skill for details
python# Records from last 30 days handle = Entrez.esearch(db='pubmed', term='CRISPR', reldate=30, datetype='pdat') record = Entrez.read(handle) handle.close()
pythondef get_search_fields(db): handle = Entrez.einfo(db=db) record = Entrez.read(handle) handle.close() return [(f['Name'], f['Description']) for f in record['DbInfo']['FieldList']] fields = get_search_fields('nucleotide') for name, desc in fields[:10]: print(f'{name}: {desc}')
pythonhandle = Entrez.esearch(db='nucleotide', term='human BRCA1') record = Entrez.read(handle) handle.close() # See how NCBI interpreted your query print(f"Your query was translated to: {record['QueryTranslation']}") # e.g., '"homo sapiens"[Organism] AND BRCA1[All Fields]'
| Error | Cause | Solution | |-------|-------|----------| | HTTPError 429 | Rate limit exceeded | Add delays or use API key | | HTTPError 400 | Invalid query syntax | Check field names and operators | | Empty IdList | No matches or typo | Check QueryTranslation field | | RuntimeError | Missing email | Set Entrez.email |
Need to search NCBI?
├── Finding records in one database?
│ └── Use Entrez.esearch()
├── Search across all databases?
│ └── Use Entrez.egquery()
├── Need database field names?
│ └── Use Entrez.einfo(db='database')
├── List all available databases?
│ └── Use Entrez.einfo() (no db argument)
├── Results > 10,000 records?
│ └── Use usehistory='y', then batch fetch
└── Need to fetch actual records?
└── See entrez-fetch skill<!-- AUTHOR_SIGNATURE: 9a7f3c2e-MD-BABU-MIA-2026-MSSM-SECURE -->
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 9,503 | 6,329 | -33% | 1 | 1 | 0% | 1,899 | 3,946 | +108% | 0 | 0 | — |
case-06 | pass→pass | 6,506 | 3,711 | -43% | 1 | 1 | 0% | 1,303 | 3,328 | +155% | 0 | 0 | — |
case-07 | pass→pass | 7,314 | 3,220 | -56% | 1 | 1 | 0% | 1,383 | 3,170 | +129% | 0 | 0 | — |
case-08 | pass→pass | 8,272 | 3,092 | -63% | 1 | 1 | 0% | 1,582 | 3,230 | +104% | 0 | 0 | — |
case-09 | pass→pass | 5,639 | 3,076 | -45% | 1 | 1 | 0% | 1,163 | 3,214 | +176% | 0 | 0 | — |
case-10 | pass→pass | 4,078 | 3,278 | -20% | 1 | 1 | 0% | 819 | 3,219 | +293% | 0 | 0 | — |
case-02 | pass→pass | 7,073 | 6,421 | -9% | 1 | 1 | 0% | 1,302 | 3,387 | +160% | 0 | 0 | — |
case-03 | pass→pass | 4,521 | 4,089 | -10% | 1 | 1 | 0% | 916 | 3,437 | +275% | 0 | 0 | — |
case-04 | pass→pass | 7,325 | 5,411 | -26% | 1 | 1 | 0% | 1,241 | 3,669 | +196% | 0 | 0 | — |
case-05 | pass→pass | 5,079 | 3,576 | -30% | 1 | 1 | 0% | 1,016 | 3,331 | +228% | 0 | 0 | — |
case-11 | fail→pass | 12,876 | 4,340 | -66% | 1 | 1 | 0% | 2,273 | 3,379 | +49% | 0 | 0 | — |
case-12 | pass→pass | 6,653 | 3,324 | -50% | 1 | 1 | 0% | 1,316 | 3,246 | +147% | 0 | 0 | — |
case-13 | pass→pass | 9,315 | 4,522 | -51% | 1 | 1 | 0% | 1,894 | 3,496 | +85% | 0 | 0 | — |
case-14 | pass→pass | 7,248 | 5,846 | -19% | 1 | 1 | 0% | 1,349 | 3,684 | +173% | 0 | 0 | — |
case-15 | pass→pass | 8,288 | 3,797 | -54% | 1 | 1 | 0% | 1,525 | 3,323 | +118% | 0 | 0 | — |
case-16 | pass→pass | 7,688 | 3,828 | -50% | 1 | 1 | 0% | 1,471 | 3,308 | +125% | 0 | 0 | — |
case-17 | pass→pass | 4,666 | 2,448 | -48% | 1 | 1 | 0% | 841 | 3,064 | +264% | 0 | 0 | — |
case-18 | fail→pass | 6,650 | 2,562 | -61% | 1 | 1 | 0% | 1,305 | 3,006 | +130% | 0 | 0 | — |
case-19 | pass→pass | 7,898 | 5,098 | -35% | 1 | 1 | 0% | 1,404 | 3,552 | +153% | 0 | 0 | — |
case-20 | pass→pass | 7,788 | 5,719 | -27% | 1 | 1 | 0% | 1,708 | 3,904 | +129% | 0 | 0 | — |
case-21 | pass→pass | 10,225 | 6,862 | -33% | 1 | 1 | 0% | 2,093 | 3,956 | +89% | 0 | 0 | — |
case-22 | pass→pass | 5,713 | 5,932 | +4% | 1 | 1 | 0% | 1,023 | 3,787 | +270% | 0 | 0 | — |
case-23 | pass→pass | 15,989 | 4,921 | -69% | 1 | 1 | 0% | 1,563 | 3,506 | +124% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 7/26/2026 | +5% |
Other measured skills in the registry, with their headline benchmark lift.