
Human Protein Atlas Database
- 1.3k installs
- 2.6k repo stars
- Updated July 7, 2026
- google-deepmind/science-skills
human-protein-atlas-database is a Claude Code skill that teaches precise Human Protein Atlas (HPA) search query syntax for developers who need protein expression, mRNA, and subcellular localization filters inside scienti
About
human-protein-atlas-database is a reference skill from google-deepmind/science-skills for constructing case-insensitive HPA search queries using key-value filters such as protein_class, tissue expression, mRNA levels, and subcellular localization. The readme documents core syntax rules, including that spaced terms like protein_class:Transcription factors do not require quotes and that quoting can break queries. Developers reach for human-protein-atlas-database when building health, bioinformatics, or research agents that must retrieve structured protein records from the Human Protein Atlas instead of guessing filter field names. The skill focuses on query construction and field semantics rather than running a bundled CLI, making it a integration guide for agent workflows that call HPA search endpoints.
- Constructs complex HPA search queries using field:value syntax, boolean operators, and grouping
- Supports filtering by protein expression, mRNA levels, subcellular localization, and functional classifications
- Case-insensitive queries with semicolon-separated sub-categories and comma-separated multiple selections
- Full boolean logic including AND, OR, NOT plus parenthetical grouping for advanced research queries
- Provides ready-to-use patterns for tissue_category_rna, protein_class, chromosome and other core fields
Human Protein Atlas Database by the numbers
- 1,261 all-time installs (skills.sh)
- +169 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #262 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/google-deepmind/science-skills --skill human-protein-atlas-databaseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.3k |
|---|---|
| repo stars | ★ 2.6k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 7, 2026 |
| Repository | google-deepmind/science-skills ↗ |
How do you query Human Protein Atlas with filter syntax?
Query the Human Protein Atlas database using precise biological filters when building scientific or health-related AI agents.
Who is it for?
Bioinformatics or health AI developers integrating Human Protein Atlas protein expression and localization data into research agents.
Skip if: Developers who only need generic web search or who are not building biology-aware agents tied to HPA datasets.
When should I use this skill?
The user mentions Human Protein Atlas, HPA, protein expression filters, tissue localization, or mRNA queries for a scientific agent.
What you get
Valid HPA key-value search queries, filter field mappings, and agent-ready query examples.
- HPA search query strings
- Field-to-filter reference
Files
Human Protein Atlas (HPA) Database Integration
This skill provides semi-quantitative protein expression and spatial localisation data from the Human Protein Atlas (HPA). While RNA-seq (e.g., GTEx) tells us if a gene is being transcribed, HPA confirms if the protein product actually exists, where it is located within the cell (e.g. nucleus vs cytoplasm), and its concentration in systemic blood circulation. The data is based on Immunohistochemistry (IHC) across normal human tissues and cancer types.
Prerequisites
1. `uv`: Read the uv skill and follow its Setup instructions to ensure uv is installed and on PATH. 2. User Notification: If LICENSE_NOTIFICATION.txt does not already exist in this skill directory then (1) prominently notify the user to check the terms at https://www.proteinatlas.org/about/licence, then (2) create the file recording the notification text and timestamp.
When to Use
Use this skill when you need to:
- Map a gene symbol to its Ensembl ID for HPA queries.
- Retrieve the semi-quantitative protein abundance in normal human tissues and
cancer types based on IHC staining (High, Medium, Low, or Not Detected).
- Find the specific organelles or subcellular structures where a protein has
been localized (e.g., nucleoplasm, mitochondria).
- Check the consistency/agreement between RNA-seq consensus and protein
expression levels.
- Search for genes based on specific protein expression criteria (e.g.,
"elevated in amygdala" or "secreted proteins").
Do NOT use when you need to:
- Query eQTLs, pQTLs, or any variant-level associations. HPA provides
wild-type expression data and knows nothing about QTLs.
- Query gene expression in non-human species. HPA is strictly for human
proteins.
- Retrieve purely quantitative RNA expression without interest in the protein
product (consider using the GTEx skill instead).
Command Selection Guide
Pick the right command on the first try. Match the user's input to the correct subcommand below.
- Map a gene symbol to Ensembl ID:
resolve-ensembl-id - Get tissue protein expression levels:
get-tissue-expression - Get subcellular location of a protein:
get-subcellular-location - Get the full HPA metadata entry for a gene:
get-atlas-entry - Search HPA for genes matching specific criteria:
search-hpa
Quick Start
# Map the ERBB2 gene symbol to its Ensembl ID
uv run scripts/hpa_cli.py resolve-ensembl-id ERBB2 --output /tmp/erbb2_id.json
# Get subcellular location by Ensembl ID
uv run scripts/hpa_cli.py get-subcellular-location ENSG00000141736 --output /tmp/erbb2_location.jsonAll subcommands write JSON to disk. Always save output in the /tmp/ directory. The default output file is /tmp/hpa_output.json if --output is not specified.
Commands
1. resolve-ensembl-id — Gene Symbol → Ensembl ID
Maps a common gene symbol (e.g., "TP53", "ERBB2") to its Ensembl gene ID. HPA endpoints are strictly Ensembl-based.
uv run scripts/hpa_cli.py resolve-ensembl-id TP53 --output /tmp/tp53_id.jsonArguments:
-
gene_symbol(positional): The standard gene symbol (e.g., "TP53"). -
--output: Output file path (default:/tmp/hpa_output.json).
2. get-tissue-expression — Get Tissue Protein Levels
Returns a list of tissues and their corresponding protein expression levels (High, Medium, Low, or Not Detected) based on IHC staining.
uv run scripts/hpa_cli.py get-tissue-expression ENSG00000130234 \
--tissues "duodenum,thyroid gland" --output /tmp/tissue_expr.jsonArguments:
-
ensembl_id(positional): The Ensembl Gene ID. -
--tissues: Comma-separated list of tissues to filter by (optional,
defaults to all available tissues).
-
--output: Output file path (default:/tmp/hpa_output.json).
3. get-subcellular-location — Get Subcellular Location
Retrieves the specific organelles or cellular structures where the protein has been localized.
uv run scripts/hpa_cli.py get-subcellular-location ENSG00000141736 \
--output /tmp/subcellular.jsonArguments:
-
ensembl_id(positional): The Ensembl Gene ID. -
--output: Output file path.
4. get-atlas-entry — Get Full HPA Entry
Fetches the full metadata for a gene, including IHC scores, RNA-seq consensus, and subcellular location.
uv run scripts/hpa_cli.py get-atlas-entry ENSG00000254647 \
--output /tmp/ins_entry.jsonArguments:
-
ensembl_id(positional): The Ensembl Gene ID. -
--format: Format of the returned entry, e.g., json (default:json). -
--output: Output file path.
5. search-hpa — Search by Attribute
Allows filtering for genes based on specific criteria (e.g., "elevated in amygdala").
uv run scripts/hpa_cli.py search-hpa \
--query "brain_category_rna:amygdala" \
--output /tmp/search_results.jsonArguments:
-
--query: The search query string. Refer to references/search-api.md for
details.
-
--output: Output file path.
Core Rules
- Use the Wrapper: ALWAYS execute the provided helper scripts to query the
database rather than accessing the database directly. The scripts automatically enforce fair use and implement retry logic.
- Notification: If this skill is used, ensure this is mentioned in the
output.
API Versioning
The HPA website at www.proteinatlas.org always serves the latest data release. Older archived versions can be accessed via vNN.proteinatlas.org (e.g., v24.proteinatlas.org), while the current version's subdomain redirects to www.proteinatlas.org. This skill's scripts query the latest version by default.
Common Errors
- If no results are returned, confirm the query is detailed enough starting
with the api reference in references/search-api.md
- If you cannot find the results, search the web for example HPA queries and
use these to construct a better query.
- The output is usually large. Use jq or write your own python data parsing
library to process the search results. Never output to stdout, or cat the output file.
Human Protein Atlas Search Query API Reference
This document provides a comprehensive guide to constructing search queries for the Human Protein Atlas (HPA). The search engine allows users to filter the HPA database based on protein expression, mRNA levels, subcellular localization, and functional classifications.
---
1. Core Syntax Overview
The HPA search engine follows a standard key-value pair format. All queries are case-insensitive.
IMPORTANT: Terms with spaces do not need to be enclosed in double quotes (e.g. protein_class:Transcription factors), and adding quotes may actually break the query. When a field has sub-categories, values for them are separated by a semi-colon ;. Multiple selections within a sub-category are separated by a comma ,.
- Field Search:
field:value - Example:
chromosome:12 - Field with Subfields:
field:subvalue1;subvalue2 - Example:
tissue_category_rna:Brain;Tissue enriched - Multiple selections:
field:subval1;sel1,sel2 - Example:
tissue_category_rna:Any;Tissue enriched,Group enriched - Boolean AND:
term1 AND term2 - Example:
protein_class:Enzymes AND chromosome:X - Boolean OR:
term1 OR term2 - Example:
tissue_category_rna:Any;Tissue enriched OR tissue_category_rna:Any;Tissue enhanced - Boolean NOT:
term1 NOT term2 - Example:
protein_class:Enzymes NOT chromosome:1 - Grouping:
( ... ) - Example:
(tissue_category_rna:Any;Tissue enriched OR tissue_category_rna:Any;Group enriched) AND chromosome:1
---
2. Specificity Classifications
The HPA categorizes gene expression based on RNA-seq data across tissues (General Atlas), brain regions (Brain Atlas) and single cell types (Single Cell Atlas). These categories are built out of two dropdowns in the UI: the region/tissue to filter on, and the specificity category.
RNA Tissue Specificity (tissue_category_rna)
Filters based on the general tissue distribution across the entire human body. Format: tissue_category_rna:<Tissue Name>;<Specificity Category>
- Specificity Categories:
- `Tissue enriched`: Genes with mRNA levels at least 4-fold higher in a
single tissue compared to all others.
- `Group enriched`: Genes with mRNA levels at least 4-fold higher in a
group of 2-5 tissues compared to all others.
- `Tissue enhanced`: Genes with mRNA levels at least 4-fold higher in a
tissue compared to the average of all others.
- `Low tissue specificity`: Low tissue specificity; detected in many
tissues.
- `Not detected`: Not detected in tissues.
Example: tissue_category_rna:Liver;Tissue enriched Example: tissue_category_rna:Any;Tissue enriched,Group enriched
RNA Brain Region Specificity (brain_category_rna)
Filters based on distribution across different brain structures. Format: brain_category_rna:<Brain Region>;<Specificity Category>
- Specificity Categories:
- `Region enriched`: Genes with mRNA levels at least 4-fold higher in one
brain region compared to all others.
- `Group enriched`: mRNA levels at least 4-fold higher in 2-5 brain
regions.
- `Region enhanced`: mRNA levels at least 4-fold higher in a brain region
compared to the average of others.
Example: brain_category_rna:Amygdala;Region enriched,Group enriched
Pro-Tip: If you are specifically looking for proteins that are unique to
the brain compared to the rest of the body, combine tissue_category_rna andbrain_category_rna fields.---
3. Commonly Used Query Fields
Below is a reference of the most frequently used fields for filtering the database.
- `gene_name`: Search by the official HGNC symbol.
- Examples:
gene_name:APOE,gene_name:TP53 - `chromosome`: Filter by the genomic location.
- Examples:
1,2, ...,X,Y,MT - `protein_class`: Functional classification of the protein.
- Examples:
Enzymes,Transcription factors,FDA approved drug targets - `subcell_location`: Main localization based on ICC staining.
- Examples:
Nucleoplasm,Mitochondria,Cytosol - `predicted_location`: Filter for secreted or intracellular logic.
- Examples:
Predicted secreted proteins,Predicted membrane proteins - `cancer_category_rna`: Expression in specific cancers.
- Example:
cancer_category_rna:Breast cancer;Cancer enriched - `ihc_ab_validation`: The validation level of the IHC antibody data.
- Examples:
Supported,Approved,Enhanced - Independent
---
4. Constructing Complex Queries
Scenario A: Finding Specific Brain Markers
To find genes that are Enriched in a specific brain region (e.g., Hypothalamus) and localized to the Vesicles (for secretory/synaptic paths): brain_category_rna:Hypothalamus;Region enriched AND subcell_location:Vesicles
Scenario B: Finding Elevated Genes in a Region
To find genes that show an elevated protein expression level in the amygdala compared to other regions of the human brain:
brain_category_rna:Amygdala;Region enriched,Group enriched,Region enhanced
AND sort_by:Tissue specific scoreScenario C: Filtering for Validated Enzymes on Chromosome 1
To find Enzymes with Approved reliability (high-quality IHC data) located on Chromosome 1: protein_class:Enzymes AND chromosome:1 AND ihc_ab_validation:Approved
Scenario D: Identifying Tissue-Specific Transcription Factors
To find Transcription factors that are either Tissue Enriched or Group Enriched across any tissue:
protein_class:Transcription factors
AND tissue_category_rna:Any;Tissue enriched,Group enriched---
Note on Data Versions: The HPA is updated periodically. The specificity categories remain consistent, but the underlying RNA-seq datasets (e.g., HPA vs. GTEx) may yield slightly different results if you specify the data source.
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""CLI wrapper for the Human Protein Atlas (HPA).
Follows HPA Terms of Use by fetching sequentially and handling requests.
"""
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "scienceskillscommon",
# ]
# [tool.uv.sources]
# scienceskillscommon = { path = "../../scienceskillscommon" }
# ///
import argparse
import json
import sys
import urllib.parse
import xml.etree.ElementTree as ET
from science_skills.skills.scienceskillscommon import http_client
BASE_URL = 'https://www.proteinatlas.org/'
CLIENT = http_client.HttpClient(BASE_URL, qps=2.0)
def _fetch_json(params):
"""Fetches data from the HPA search API."""
params['format'] = 'json'
params['compress'] = 'no'
query_string = urllib.parse.urlencode(params)
base_api_url = urllib.parse.urljoin(BASE_URL, 'api/search_download.php')
full_url = f'{base_api_url}?{query_string}'
content = CLIENT.fetch_bytes(full_url)
if not content:
return []
return json.loads(content.decode('utf-8'))
def _fetch_xml(ensembl_id):
"""Fetches and parses the XML entry for a given Ensembl ID."""
full_url = urllib.parse.urljoin(BASE_URL, f'{ensembl_id}.xml')
content = CLIENT.fetch_bytes(full_url)
return ET.fromstring(content)
def resolve_ensembl_id(gene_symbol, output_file):
"""Maps a common gene symbol to its Ensembl ID."""
params = {'search': gene_symbol, 'columns': 'g,eg,gs,gd'}
data = _fetch_json(params)
if not data:
sys.stderr.write(f"Error: Could not find Ensembl ID for '{gene_symbol}'.\n")
sys.exit(1)
# Return the best exact match if possible
best_match = data[0]
for d in data:
if d.get('Gene', '').lower() == gene_symbol.lower():
best_match = d
break
result = {
'gene_symbol': best_match.get('Gene'),
'ensembl_id': best_match.get('Ensembl'),
'synonyms': best_match.get('Gene synonym'),
'description': best_match.get('Gene description'),
}
with open(output_file, 'w') as f:
json.dump(result, f, indent=2)
def get_tissue_expression(ensembl_id, tissues, output_file):
"""Returns tissue protein expression levels (IHC)."""
root = _fetch_xml(ensembl_id)
# The XML namespace is usually specified, e.g.,
# xmlns="http://www.proteinatlas.org/search/download/proteinatlas.xsd"
# But we can search without namespace by using local name or wildcards if
# needed. We clean the tags by stripping namespaces for easier parsing.
for elem in root.iter():
if '}' in elem.tag:
elem.tag = elem.tag.split('}', 1)[1]
expression_data = []
# Find <tissueExpression source="HPA" technology="IHC" assayType="tissue">
for te in root.findall('.//tissueExpression'):
if te.get('technology') == 'IHC':
for data_node in te.findall('./data'):
tissue_node = data_node.find('tissue')
level_node = data_node.find('level')
if tissue_node is not None and level_node is not None:
tissue_name = tissue_node.text
level = level_node.text
expression_data.append({
'tissue': tissue_name,
'organ': tissue_node.get('organ'),
'level': level,
})
if tissues:
tissue_filter = [t.strip().lower() for t in tissues.split(',')]
expression_data = [
d for d in expression_data if d['tissue'].lower() in tissue_filter
]
with open(output_file, 'w') as f:
json.dump(expression_data, f, indent=2)
def get_subcellular_location(ensembl_id, output_file):
"""Retrieves subcellular locations for a protein."""
params = {'search': ensembl_id, 'columns': 'g,eg,scl,scml,scal'}
data = _fetch_json(params)
result = {}
if data:
result = {
'ensembl_id': data[0].get('Ensembl'),
'gene_symbol': data[0].get('Gene'),
'subcellular_locations': data[0].get('Subcellular location', []),
'main_locations': data[0].get('Subcellular main location', []),
'additional_locations': (
data[0].get('Subcellular additional location', [])
),
}
with open(output_file, 'w') as f:
json.dump(result, f, indent=2)
def get_atlas_entry(ensembl_id, format_type, output_file):
"""Fetches the full metadata entry."""
if format_type.lower() == 'json':
# Let's fetch all relevant columns for the entry
cols = [
'g',
'gs',
'eg',
'gd',
'up',
'scl',
'scml',
'scal',
'pc',
'ccdp',
'ectissue',
'rnats',
'rnatd',
'rnatss',
]
params = {'search': ensembl_id, 'columns': ','.join(cols)}
data = _fetch_json(params)
entry = data[0] if data else {}
# Also fetch the XML to get the verification reliability
try:
root = _fetch_xml(ensembl_id)
for elem in root.iter():
if '}' in elem.tag:
elem.tag = elem.tag.split('}', 1)[1]
ver = root.find('.//tissueExpression/verification')
if ver is not None:
entry['RNA_protein_agreement'] = {
'reliability': ver.text,
'description': ver.get('description'),
}
except (ET.ParseError, AttributeError, TypeError):
# If XML fetching or parsing fails, just ignore and return the JSON entry
pass
with open(output_file, 'w') as f:
json.dump(entry, f, indent=2)
else:
sys.stderr.write(
f"Error: Format '{format_type}' not supported currently. Only JSON is"
' supported.\n'
)
sys.exit(1)
def search_hpa(query, output_file):
"""Searches HPA based on specific criteria."""
params = {'search': query, 'columns': 'g,eg,gd,scl,ectissue'}
data = _fetch_json(params)
with open(output_file, 'w') as f:
json.dump(data, f, indent=2)
def main():
parser = argparse.ArgumentParser(description='Human Protein Atlas CLI')
subparsers = parser.add_subparsers(dest='command', required=True)
p_resolve = subparsers.add_parser(
'resolve-ensembl-id', help='Map a standard gene symbol to its Ensembl ID'
)
p_resolve.add_argument('gene_symbol', help='Gene symbol (e.g. TP53)')
p_resolve.add_argument('--output', default='/tmp/hpa_output.json')
p_tissue = subparsers.add_parser(
'get-tissue-expression', help='Get tissue protein levels'
)
p_tissue.add_argument('ensembl_id', help='Ensembl Gene ID')
p_tissue.add_argument(
'--tissues', help='Comma-separated list of tissue names'
)
p_tissue.add_argument('--output', default='/tmp/hpa_output.json')
p_subcell = subparsers.add_parser(
'get-subcellular-location', help='Get subcellular location'
)
p_subcell.add_argument('ensembl_id', help='Ensembl Gene ID')
p_subcell.add_argument('--output', default='/tmp/hpa_output.json')
p_entry = subparsers.add_parser(
'get-atlas-entry', help='Get full HPA metadata entry'
)
p_entry.add_argument('ensembl_id', help='Ensembl Gene ID')
p_entry.add_argument(
'--format',
default='json',
help='Format of the returned entry (e.g., json)',
)
p_entry.add_argument('--output', default='/tmp/hpa_output.json')
p_search = subparsers.add_parser('search-hpa', help='Search HPA by attribute')
p_search.add_argument('--query', required=True, help='Search query string')
p_search.add_argument('--output', default='/tmp/hpa_output.json')
args = parser.parse_args()
if args.command == 'resolve-ensembl-id':
resolve_ensembl_id(args.gene_symbol, args.output)
elif args.command == 'get-tissue-expression':
get_tissue_expression(args.ensembl_id, args.tissues, args.output)
elif args.command == 'get-subcellular-location':
get_subcellular_location(args.ensembl_id, args.output)
elif args.command == 'get-atlas-entry':
get_atlas_entry(args.ensembl_id, args.format, args.output)
elif args.command == 'search-hpa':
search_hpa(args.query, args.output)
else:
parser.print_help()
if __name__ == '__main__':
main()
Related skills
How it compares
Pick human-protein-atlas-database when agents must query HPA expression and localization fields directly instead of running PPI enrichment on STRING networks.
FAQ
What query format does Human Protein Atlas search use?
Human Protein Atlas search uses case-insensitive key-value pairs such as protein_class:Transcription factors. The human-protein-atlas-database skill notes spaced values do not need double quotes and quoting may break the query.
Which HPA fields can agents filter on?
The human-protein-atlas-database skill covers filters for protein expression, mRNA levels, subcellular localization, and functional classifications like protein_class, giving agents structured biological lookup parameters.
Is Human Protein Atlas Database safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.