SciAgent-Skills gtopdb-database
Query the IUPHAR/BPS Guide to Pharmacology (GtoPdb) REST API for receptor-ligand interaction data, target pharmacology, and quantitative affinity metrics. Retrieve pKi/pIC50/pEC50 values, ligand classifications (approved drugs, biologics, natural products), target families (GPCRs, ion channels, nuclear receptors, kinases), and selectivity profiles across the pharmacological target space.
git clone https://github.com/jaechang-hits/SciAgent-Skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/jaechang-hits/SciAgent-Skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/structural-biology-drug-discovery/gtopdb-database" ~/.claude/skills/jaechang-hits-sciagent-skills-gtopdb-database && rm -rf "$T"
skills/structural-biology-drug-discovery/gtopdb-database/SKILL.mdGtoPdb Database
Overview
The Guide to Pharmacology (GtoPdb), maintained by IUPHAR/BPS, is the curated reference database for pharmacological targets and their ligands. It covers 3,000+ targets (GPCRs, ion channels, nuclear receptors, catalytic receptors, transporters, and enzymes) with 12,000+ ligands and 90,000+ interaction records annotated with quantitative affinity values (Ki, IC50, EC50, Kd). Access is via a free REST API at
https://www.guidetopharmacology.org/services/ — no authentication required.
When to Use
- Retrieving curated receptor-ligand interaction data with quantitative affinity (pKi, pIC50, pEC50) for GPCR, ion channel, or kinase targets
- Finding all approved drugs, clinical candidates, or research ligands that act on a specific receptor family
- Getting the pharmacological target classification for a receptor (family, type, HGNC symbol, UniProt ID)
- Building selectivity profiles for a ligand across all annotated targets in GtoPdb
- Identifying receptor families (GPCR subfamilies, ion channel families) and browsing their member targets
- Retrieving quantitative agonist/antagonist/allosteric modulator affinity data for lead optimization
- Comparing endogenous ligand potency with drug affinity at the same receptor
- For large-scale ADMET/bioactivity data use
; GtoPdb is the authoritative source for receptor pharmacology annotationchembl-database-bioactivity - For structural data (binding poses, crystal structures) use
; GtoPdb provides affinity numbers, not 3D structurespdb-database
Prerequisites
- Python packages:
,requests
,pandasmatplotlib - Data requirements: GtoPdb target IDs, ligand IDs, or receptor family names as starting points; HGNC gene symbols or UniProt IDs accepted for target lookup
- Environment: internet connection; no API key required
- Rate limits: ~50 requests/minute; no hard enforcement but use
in batch loops for polite accesstime.sleep(0.2)
pip install requests pandas matplotlib
Quick Start
import requests GTOPDB_API = "https://www.guidetopharmacology.org/services" def gtopdb_get(endpoint: str, params: dict = None) -> list | dict: """GET request to GtoPdb API; raise on HTTP errors.""" r = requests.get(f"{GTOPDB_API}/{endpoint}", params=params, timeout=20) r.raise_for_status() return r.json() # Find the beta-2 adrenoceptor target targets = gtopdb_get("targets", params={"name": "beta-2 adrenoceptor"}) if targets: t = targets[0] tid = t["targetId"] print(f"Target: {t['name']} (GtoPdb ID: {tid})") print(f"Family: {t.get('familyIds', [])}") # Get its approved drug interactions interactions = gtopdb_get(f"targets/{tid}/interactions") approved = [i for i in interactions if i.get("ligandType") == "Approved"] print(f"Approved drugs acting on beta-2 AR: {len(approved)}") for ia in approved[:3]: affinity = ia.get("affinityParameter", ""), ia.get("affinity", "") print(f" {ia['ligandName']:25s} {affinity[0]}={affinity[1]}")
Core API
Query 1: Target Search and Details
Search targets by name, HGNC symbol, UniProt accession, or target family type. Returns target metadata including GtoPdb target ID, gene symbol, family assignment, and species.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def search_targets(name: str = None, hgnc_symbol: str = None, target_type: str = None) -> pd.DataFrame: """Search GtoPdb targets. Args: name: Partial target name (case-insensitive substring match) hgnc_symbol: Exact HGNC gene symbol (e.g., 'ADRB2') target_type: One of 'GPCR', 'Ion channel', 'Nuclear receptor', 'Catalytic receptor', 'Transporter', 'Enzyme', 'Other' """ params = {} if name: params["name"] = name if hgnc_symbol: params["geneSymbol"] = hgnc_symbol if target_type: params["type"] = target_type r = requests.get(f"{GTOPDB_API}/targets", params=params, timeout=20) r.raise_for_status() targets = r.json() if not targets: return pd.DataFrame() rows = [] for t in targets: rows.append({ "target_id": t.get("targetId"), "name": t.get("name"), "type": t.get("type"), "hgnc_symbol": t.get("hgncSymbol"), "uniprot_id": t.get("uniprotId"), "species": t.get("species", "Human"), }) return pd.DataFrame(rows) # Search for dopamine receptors df = search_targets(name="dopamine receptor") print(f"Found {len(df)} dopamine receptor targets:") print(df[["target_id", "name", "type", "hgnc_symbol"]].to_string(index=False))
# Get full details for a specific target def get_target_details(target_id: int) -> dict: """Retrieve full target record by GtoPdb target ID.""" r = requests.get(f"{GTOPDB_API}/targets/{target_id}", timeout=15) r.raise_for_status() return r.json() # Mu-opioid receptor (OPRM1) target = get_target_details(319) print(f"Target: {target['name']}") print(f"Type: {target.get('type')}") print(f"HGNC symbol: {target.get('hgncSymbol')}") print(f"UniProt: {target.get('uniprotId')}") print(f"Family IDs: {target.get('familyIds', [])}") print(f"Synonyms: {', '.join(target.get('synonyms', [])[:4])}")
Query 2: Target Interactions — Ligand Affinity Data
Retrieve all ligand-target interactions for a given target, including quantitative affinity values, ligand type classification, and experimental context.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def get_target_interactions(target_id: int, species: str = "Human") -> pd.DataFrame: """Get all interactions for a target with affinity data. Returns a DataFrame with ligand name, type, affinity parameters, and action type. """ r = requests.get(f"{GTOPDB_API}/targets/{target_id}/interactions", params={"species": species}, timeout=20) r.raise_for_status() interactions = r.json() rows = [] for ia in interactions: rows.append({ "ligand_id": ia.get("ligandId"), "ligand_name": ia.get("ligandName"), "ligand_type": ia.get("ligandType"), "action": ia.get("action"), # agonist, antagonist, etc. "action_comment": ia.get("actionComment"), "affinity_param": ia.get("affinityParameter"), # pKi, pIC50, pEC50 "affinity": ia.get("affinity"), # numeric value "affinity_high": ia.get("affinityHigh"), "affinity_low": ia.get("affinityLow"), "endogenous": ia.get("endogenous", False), "primary_target": ia.get("primaryTarget", False), "assay_type": ia.get("assayType"), "pubmed_id": ia.get("refs", [{}])[0].get("pmid") if ia.get("refs") else None, }) return pd.DataFrame(rows) # Serotonin 2A receptor (5-HT2A, target_id=11) df = get_target_interactions(11) print(f"5-HT2A receptor interactions: {len(df)} total") print(f"\nAction type breakdown:") print(df["action"].value_counts().head(8)) print(f"\nLigand type breakdown:") print(df["ligand_type"].value_counts().head(6)) # Show top antagonists by affinity antagonists = df[df["action"] == "Antagonist"].dropna(subset=["affinity"]) antagonists = antagonists.sort_values("affinity", ascending=False) print(f"\nTop 5-HT2A antagonists (by pKi/pIC50):") print(antagonists[["ligand_name", "ligand_type", "affinity_param", "affinity"]].head(8).to_string(index=False))
Query 3: Ligand Search and Details
Search for ligands by name, approved drug status, or ligand type. Retrieve full ligand records including structure IDs (InChIKey, SMILES), clinical status, and cross-references.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def search_ligands(name: str = None, approved_drug: bool = None, ligand_type: str = None) -> pd.DataFrame: """Search GtoPdb ligands. Args: name: Ligand name substring (case-insensitive) approved_drug: If True, filter to approved drugs only ligand_type: One of 'Approved', 'Labelled', 'Peptide', 'Antibody', 'Endogenous', 'Inorganic', 'Metabolite', 'Natural product', 'Synthetic organic' """ params = {} if name: params["name"] = name if approved_drug is not None: params["approvedDrug"] = str(approved_drug).lower() if ligand_type: params["type"] = ligand_type r = requests.get(f"{GTOPDB_API}/ligands", params=params, timeout=20) r.raise_for_status() ligands = r.json() rows = [] for lig in ligands: rows.append({ "ligand_id": lig.get("ligandId"), "name": lig.get("name"), "type": lig.get("type"), "approved": lig.get("approvedDrug", False), "inchikey": lig.get("inchikey"), "smiles": lig.get("smiles", "")[:60] if lig.get("smiles") else "", "pubchem_cid": lig.get("pubchemCid"), "chembl_id": lig.get("chemblId"), }) return pd.DataFrame(rows) # Search for beta-blocker drugs df = search_ligands(name="propranolol") print(df[["ligand_id", "name", "type", "approved", "inchikey", "chembl_id"]].to_string(index=False))
# Get full details for a specific ligand def get_ligand_details(ligand_id: int) -> dict: """Retrieve full ligand record by GtoPdb ligand ID.""" r = requests.get(f"{GTOPDB_API}/ligands/{ligand_id}", timeout=15) r.raise_for_status() return r.json() # Morphine (ligand_id=1627) lig = get_ligand_details(1627) print(f"Name: {lig['name']}") print(f"Type: {lig.get('type')}") print(f"Approved drug: {lig.get('approvedDrug')}") print(f"InChIKey: {lig.get('inchikey')}") print(f"SMILES: {lig.get('smiles', 'N/A')[:80]}") print(f"ChEMBL ID: {lig.get('chemblId')}") print(f"PubChem CID: {lig.get('pubchemCid')}")
Query 4: Ligand Interactions — Target Selectivity Profile
Given a ligand, retrieve all targets it acts on with affinity values. Use this to build a selectivity profile or identify off-target effects.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def get_ligand_interactions(ligand_id: int, species: str = "Human") -> pd.DataFrame: """Get all target interactions for a ligand. Returns a DataFrame with target name, type, action, and affinity. """ r = requests.get(f"{GTOPDB_API}/ligands/{ligand_id}/interactions", params={"species": species}, timeout=20) r.raise_for_status() interactions = r.json() rows = [] for ia in interactions: rows.append({ "target_id": ia.get("targetId"), "target_name": ia.get("targetName"), "target_type": ia.get("targetType"), "action": ia.get("action"), "affinity_param": ia.get("affinityParameter"), "affinity": ia.get("affinity"), "endogenous": ia.get("endogenous", False), "primary_target": ia.get("primaryTarget", False), }) return pd.DataFrame(rows) # Clozapine selectivity profile (ligand_id=31 in GtoPdb) df = get_ligand_interactions(31) print(f"Clozapine interactions: {len(df)} targets") # Filter to records with affinity data has_affinity = df.dropna(subset=["affinity"]).sort_values("affinity", ascending=False) print(f"\nTargets with quantitative affinity (n={len(has_affinity)}):") print(has_affinity[["target_name", "target_type", "action", "affinity_param", "affinity"]].head(10).to_string(index=False))
Query 5: Browse Target Families
Retrieve the receptor family hierarchy: superfamilies → families → individual targets. Use this to enumerate all GPCRs, ion channels, or nuclear receptors.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def get_families(family_id: int = None) -> list: """Get all families or a specific family by ID.""" endpoint = f"families/{family_id}" if family_id else "families" r = requests.get(f"{GTOPDB_API}/{endpoint}", timeout=20) r.raise_for_status() data = r.json() return data if isinstance(data, list) else [data] def get_family_targets(family_id: int) -> pd.DataFrame: """Get all targets in a given receptor family.""" r = requests.get(f"{GTOPDB_API}/targets", params={"familyId": family_id}, timeout=20) r.raise_for_status() targets = r.json() rows = [{"target_id": t.get("targetId"), "name": t.get("name"), "type": t.get("type"), "hgnc_symbol": t.get("hgncSymbol"), "uniprot_id": t.get("uniprotId")} for t in targets] return pd.DataFrame(rows) # Browse top-level families families = get_families() print(f"Total GtoPdb families: {len(families)}") for fam in families[:8]: print(f" [{fam['familyId']}] {fam['name']}") # Get all targets in a specific GPCR subfamily # Family ID 694 = Adenosine receptors adenosine_targets = get_family_targets(694) print(f"\nAdenosine receptor targets: {len(adenosine_targets)}") print(adenosine_targets[["target_id", "name", "hgnc_symbol"]].to_string(index=False))
Query 6: Global Interaction Search
Search all interactions by affinity type, action, or ligand type to extract a curated dataset for pharmacological analysis.
import requests, pandas as pd, time GTOPDB_API = "https://www.guidetopharmacology.org/services" def search_interactions(action: str = None, target_type: str = None, affinity_param: str = None, species: str = "Human") -> pd.DataFrame: """Search all GtoPdb interactions with optional filters. Args: action: 'Agonist', 'Antagonist', 'Inhibitor', 'Allosteric modulator', etc. target_type: 'GPCR', 'Ion channel', 'Nuclear receptor', etc. affinity_param: 'pKi', 'pIC50', 'pEC50', 'pKd' species: 'Human' (default), 'Mouse', 'Rat' """ params = {"species": species} if action: params["action"] = action if target_type: params["targetType"] = target_type if affinity_param: params["affinityParameter"] = affinity_param r = requests.get(f"{GTOPDB_API}/interactions", params=params, timeout=60) r.raise_for_status() interactions = r.json() rows = [] for ia in interactions: rows.append({ "target_id": ia.get("targetId"), "target_name": ia.get("targetName"), "target_type": ia.get("targetType"), "ligand_id": ia.get("ligandId"), "ligand_name": ia.get("ligandName"), "ligand_type": ia.get("ligandType"), "action": ia.get("action"), "affinity_param": ia.get("affinityParameter"), "affinity": ia.get("affinity"), "endogenous": ia.get("endogenous", False), "approved_drug": ia.get("approvedDrug", False), }) return pd.DataFrame(rows) # Get all GPCR antagonist interactions with pKi values df = search_interactions(action="Antagonist", target_type="GPCR", affinity_param="pKi") print(f"GPCR antagonists with pKi data: {len(df)} interactions") df_clean = df.dropna(subset=["affinity"]) print(f"With numeric affinity: {len(df_clean)}") print(f"\npKi distribution:") print(df_clean["affinity"].describe().round(2)) print(f"\nTop 5 by pKi:") print(df_clean.nlargest(5, "affinity")[["ligand_name", "target_name", "affinity"]].to_string(index=False))
Key Concepts
GtoPdb Pharmacological Hierarchy
GtoPdb organizes targets into a two-level hierarchy: target types (GPCR, Ion channel, Nuclear receptor, Catalytic receptor, Transporter, Enzyme, Other protein) → families (e.g., GPCR > Aminergic receptors > Adrenoceptors > beta-Adrenoceptors) → individual targets (e.g., beta-2 adrenoceptor). The
familyId parameter lets you enumerate all members of a receptor family efficiently.
Affinity Parameters
| Parameter | Definition | Typical range | Notes |
|---|---|---|---|
| -log₁₀(Ki) equilibrium dissociation constant | 4–12 | Direct binding; higher = tighter |
| -log₁₀(IC50) half-maximal inhibitory concentration | 4–12 | Functional inhibition |
| -log₁₀(EC50) half-maximal effective concentration | 4–12 | Functional activation |
| -log₁₀(Kd) dissociation constant | 4–12 | Equilibrium binding (often from SPR/ITC) |
| Percent effect at fixed concentration | 0–100 | Qualitative; no affinity constant |
A pKi of 9 = Ki of 1 nM (high affinity); pKi of 6 = Ki of 1 µM (moderate). GtoPdb requires at least two independent measurements to include a value.
Ligand Type Classifications
| Type | Description |
|---|---|
| Regulatory-approved drug (FDA, EMA) |
| Research tool compound |
| Plant/animal/microbial origin |
| Endogenous ligand (neurotransmitter, hormone) |
| Peptide/peptidomimetic |
| Therapeutic antibody |
| Metal ions, inorganic compounds |
| Metabolic product |
Common Workflows
Workflow 1: Build a Target Pharmacology Table for a Receptor
Goal: Retrieve all interactions for a GPCR, separate by action type, and export a structured table with quantitative affinities for SAR analysis.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def get_pharmacology_table(target_id: int, species: str = "Human") -> pd.DataFrame: """Full pharmacology table for a target: agonists, antagonists, allosteric modulators.""" r = requests.get(f"{GTOPDB_API}/targets/{target_id}/interactions", params={"species": species}, timeout=30) r.raise_for_status() rows = [] for ia in r.json(): rows.append({ "ligand_id": ia.get("ligandId"), "ligand_name": ia.get("ligandName"), "ligand_type": ia.get("ligandType"), "action": ia.get("action"), "action_comment": ia.get("actionComment"), "affinity_param": ia.get("affinityParameter"), "affinity": ia.get("affinity"), "affinity_high": ia.get("affinityHigh"), "affinity_low": ia.get("affinityLow"), "endogenous": ia.get("endogenous", False), "approved": ia.get("approvedDrug", False), "pubmed_id": ia.get("refs", [{}])[0].get("pmid") if ia.get("refs") else None, }) df = pd.DataFrame(rows) if df.empty: return df df["affinity"] = pd.to_numeric(df["affinity"], errors="coerce") return df # Adenosine A2A receptor (target_id=3) df = get_pharmacology_table(3) print(f"Adenosine A2A receptor — {len(df)} total interactions") # Pivot by action type for action in ["Agonist", "Antagonist", "Allosteric modulator"]: subset = df[df["action"] == action].dropna(subset=["affinity"]) subset = subset.sort_values("affinity", ascending=False) print(f"\n{action}s with affinity data (n={len(subset)}):") cols = ["ligand_name", "ligand_type", "affinity_param", "affinity", "approved"] print(subset[cols].head(5).to_string(index=False)) df.to_csv("A2A_pharmacology.csv", index=False) print(f"\nSaved A2A_pharmacology.csv ({len(df)} interactions)")
Workflow 2: Multi-Target Selectivity Heatmap
Goal: For a set of ligands, query their affinity across a receptor panel and visualize as a heatmap.
import requests, time import pandas as pd import matplotlib.pyplot as plt import numpy as np GTOPDB_API = "https://www.guidetopharmacology.org/services" def get_ligand_selectivity(ligand_id: int, species: str = "Human") -> dict: """Return {target_name: affinity} for a ligand (best affinity per target).""" r = requests.get(f"{GTOPDB_API}/ligands/{ligand_id}/interactions", params={"species": species}, timeout=20) r.raise_for_status() targets = {} for ia in r.json(): name = ia.get("targetName", "") aff = ia.get("affinity") if name and aff is not None: try: val = float(aff) if name not in targets or val > targets[name]: targets[name] = val except (ValueError, TypeError): pass return targets # Typical antipsychotics: clozapine, haloperidol, olanzapine # Use small sample GtoPdb ligand IDs for illustration ligands = { "clozapine": 31, # GtoPdb ligand ID "haloperidol": 78, "olanzapine": 4, } all_data = {} for name, lid in ligands.items(): all_data[name] = get_ligand_selectivity(lid) time.sleep(0.2) # Build matrix: rows=ligands, columns=shared targets all_targets = sorted(set().union(*all_data.values())) matrix = pd.DataFrame(index=ligands.keys(), columns=all_targets, dtype=float) for lig, targets in all_data.items(): for tgt, aff in targets.items(): matrix.loc[lig, tgt] = aff # Keep only targets with data for at least 2 ligands matrix = matrix.dropna(axis=1, thresh=2) print(f"Selectivity matrix: {matrix.shape[0]} ligands × {matrix.shape[1]} targets") # Plot heatmap fig, ax = plt.subplots(figsize=(max(10, matrix.shape[1] * 0.5), 4)) im = ax.imshow(matrix.values.astype(float), aspect="auto", cmap="YlOrRd", vmin=5, vmax=10) ax.set_xticks(range(matrix.shape[1])) ax.set_xticklabels(matrix.columns, rotation=45, ha="right", fontsize=7) ax.set_yticks(range(matrix.shape[0])) ax.set_yticklabels(matrix.index) plt.colorbar(im, ax=ax, label="pAffinity (pKi / pIC50 / pEC50)") ax.set_title("GtoPdb Antipsychotic Selectivity Profile") plt.tight_layout() plt.savefig("antipsychotic_selectivity.png", dpi=150, bbox_inches="tight") print("Saved antipsychotic_selectivity.png")
Workflow 3: Approved Drug Target Coverage for a Family
Goal: Enumerate all members of a receptor family, count approved drugs per target, and rank by drug coverage.
import requests, time, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def approved_drug_coverage(family_id: int, species: str = "Human") -> pd.DataFrame: """Return approved drug counts and ligands for each target in a receptor family. Args: family_id: GtoPdb family ID (e.g., 694 for Adenosine receptors) species: 'Human', 'Mouse', 'Rat' """ # Get all targets in the family r = requests.get(f"{GTOPDB_API}/targets", params={"familyId": family_id}, timeout=20) r.raise_for_status() targets = r.json() rows = [] for t in targets: tid = t["targetId"] time.sleep(0.2) r2 = requests.get(f"{GTOPDB_API}/targets/{tid}/interactions", params={"species": species}, timeout=20) if not r2.ok: continue interactions = r2.json() approved = [ia for ia in interactions if ia.get("approvedDrug")] drug_names = list({ia["ligandName"] for ia in approved})[:5] rows.append({ "target_id": tid, "target_name": t.get("name"), "hgnc_symbol": t.get("hgncSymbol"), "n_interactions": len(interactions), "n_approved_drugs": len(approved), "approved_drugs": ", ".join(drug_names), }) df = pd.DataFrame(rows).sort_values("n_approved_drugs", ascending=False) return df # Opioid receptor family (family_id varies; search for it) r = requests.get(f"{GTOPDB_API}/families", timeout=15) families = r.json() opioid = next((f for f in families if "opioid" in f.get("name", "").lower()), None) if opioid: print(f"Opioid family: {opioid['name']} (ID={opioid['familyId']})") df = approved_drug_coverage(opioid["familyId"]) print(df[["target_name", "n_approved_drugs", "approved_drugs"]].to_string(index=False)) df.to_csv("opioid_approved_drugs.csv", index=False) print(f"\nSaved opioid_approved_drugs.csv")
Key Parameters
| Parameter | Function/Endpoint | Default | Range / Options | Effect |
|---|---|---|---|---|
| , | — | Partial string (case-insensitive) | Substring match on target or ligand name |
| | — | , , , , , , | Filter targets by receptor class |
| | — | Integer family ID | Return all targets belonging to a receptor family |
| | — | HGNC symbol string (e.g., ) | Exact match on HGNC gene symbol |
| , | | , , | Filter interactions to a specific species |
| | — | , | Filter ligands to FDA/EMA approved drugs |
| | — | , , , , , , | Filter by pharmacological action type |
| | — | , , , | Return only interactions with this affinity type |
| | — | Same as for targets | Filter interactions by target class |
Best Practices
-
Resolve target IDs before batch queries: GtoPdb uses integer target IDs. Always start with a
search to get the correctGET /targets?name=...
rather than hard-coding IDs across analyses, as family assignments and IDs can change between database releases.targetId -
Filter interactions by species for quantitative analyses: The same target may have interactions from multiple species. For drug discovery (human pharmacology), always pass
. Cross-species data is useful for selectivity validation but should be flagged separately.species=Human -
Use
before ranking: Many interaction records have qualitative action annotations (e.g., "Agonist" without a Ki value). Always filter to records with numeric affinity before computing potency rankings.dropna(subset=["affinity"]) -
Check
flag to separate endogenous ligands from drugs: Endogenous peptides, neurotransmitters, and lipids will appear in interaction tables. Useendogenous
to focus on drug/tool compound interactions in SAR analyses.df[~df["endogenous"]] -
Cross-reference with ChEMBL via
: Ligand records includechembl_id
. Use this to enrich GtoPdb affinity data with larger bioactivity datasets from ChEMBL usingchemblId
.chembl-database-bioactivitylig = get_ligand_details(ligand_id) chembl_id = lig.get("chemblId") # e.g., 'CHEMBL192' # Then query ChEMBL for full bioactivity profile
Common Recipes
Recipe: Get All Approved Drugs for a Target by HGNC Symbol
When to use: Quick lookup of marketed drugs targeting a specific receptor given only the gene name.
import requests GTOPDB_API = "https://www.guidetopharmacology.org/services" def approved_drugs_for_gene(hgnc_symbol: str, species: str = "Human") -> list[dict]: """Return approved drugs for a target identified by HGNC gene symbol.""" # Step 1: find the target r = requests.get(f"{GTOPDB_API}/targets", params={"geneSymbol": hgnc_symbol}, timeout=15) r.raise_for_status() targets = r.json() human_targets = [t for t in targets if t.get("species", "Human") == "Human"] if not human_targets: print(f"No human target found for {hgnc_symbol}") return [] target_id = human_targets[0]["targetId"] target_name = human_targets[0]["name"] # Step 2: get interactions r2 = requests.get(f"{GTOPDB_API}/targets/{target_id}/interactions", params={"species": species}, timeout=20) r2.raise_for_status() approved = [ {"ligand_name": ia["ligandName"], "action": ia.get("action"), "affinity_param": ia.get("affinityParameter"), "affinity": ia.get("affinity")} for ia in r2.json() if ia.get("approvedDrug") ] print(f"{target_name} (ID={target_id}): {len(approved)} approved drugs") return approved drugs = approved_drugs_for_gene("DRD2") # Dopamine D2 receptor for d in drugs[:6]: aff = f"{d['affinity_param']}={d['affinity']}" if d['affinity'] else "no affinity" print(f" {d['ligand_name']:20s} {d['action']:15s} {aff}")
Recipe: Compare Endogenous vs Drug Affinity at a Receptor
When to use: Assess how drug potency compares to the endogenous agonist at a given receptor.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" def compare_endogenous_vs_drugs(target_id: int, species: str = "Human") -> pd.DataFrame: """Compare endogenous ligand affinities to approved drug affinities.""" r = requests.get(f"{GTOPDB_API}/targets/{target_id}/interactions", params={"species": species}, timeout=20) r.raise_for_status() rows = [] for ia in r.json(): aff = ia.get("affinity") if aff is None: continue try: rows.append({ "ligand": ia["ligandName"], "category": "Endogenous" if ia.get("endogenous") else ("Approved drug" if ia.get("approvedDrug") else "Research compound"), "action": ia.get("action"), "affinity_param": ia.get("affinityParameter"), "affinity": float(aff), }) except (ValueError, TypeError): pass df = pd.DataFrame(rows) if df.empty: return df return df.sort_values(["category", "affinity"], ascending=[True, False]) # Beta-2 adrenoceptor (target_id=24) df = compare_endogenous_vs_drugs(24) print("Beta-2 adrenoceptor — Endogenous vs approved drug affinities:") for cat, group in df.groupby("category"): print(f"\n{cat} (n={len(group)}):") print(group[["ligand", "action", "affinity_param", "affinity"]].head(5).to_string(index=False))
Recipe: Export All GPCR-Approved Drug Interactions to CSV
When to use: Build a comprehensive dataset of all approved GPCR drugs with quantitative affinity for pharmacological analysis.
import requests, pandas as pd GTOPDB_API = "https://www.guidetopharmacology.org/services" # Get all interactions filtered to GPCR targets and approved drugs r = requests.get(f"{GTOPDB_API}/interactions", params={"targetType": "GPCR", "species": "Human"}, timeout=60) r.raise_for_status() interactions = r.json() rows = [] for ia in interactions: if not ia.get("approvedDrug"): continue rows.append({ "target_id": ia.get("targetId"), "target_name": ia.get("targetName"), "ligand_id": ia.get("ligandId"), "ligand_name": ia.get("ligandName"), "action": ia.get("action"), "affinity_param": ia.get("affinityParameter"), "affinity": ia.get("affinity"), "endogenous": ia.get("endogenous", False), }) df = pd.DataFrame(rows) df_clean = df.dropna(subset=["affinity"]) df_clean["affinity"] = pd.to_numeric(df_clean["affinity"], errors="coerce") df_clean = df_clean.dropna(subset=["affinity"]).sort_values("affinity", ascending=False) df_clean.to_csv("gpcr_approved_drugs.csv", index=False) print(f"GPCR approved drug interactions: {len(df_clean)} with affinity data") print(f"Unique targets: {df_clean['target_id'].nunique()}") print(f"Unique drugs: {df_clean['ligand_name'].nunique()}") print(df_clean.head(5)[["target_name", "ligand_name", "action", "affinity_param", "affinity"]].to_string(index=False))
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
Empty list from | Exact name mismatch; GtoPdb uses official IUPHAR nomenclature | Try a shorter substring (e.g., instead of ); use HGNC symbol with param |
times out | Large result set (all GPCRs is 90K+ records) | Add filters (, , ) to reduce result set; increase timeout to 120s |
Interactions return affinity for many records | Many interactions are qualitative (presence/absence, not Ki values) | Use to work only with quantitative records; expect ~40% have numeric values |
| Ligand search returns unexpected results | parameter does substring match; common words match multiple ligands | Filter results by or flag after retrieval; use if known |
| Target found but no interactions returned | Rare target with no curated interactions or wrong species | Check param — some targets have only Rat/Mouse data; try without species filter |
| GtoPdb server temporarily unavailable | Retry after 30s; GtoPdb is academic infrastructure and has occasional downtime |
| Duplicate interactions for same ligand-target pair | Multiple assay entries per interaction (different labs, assay conditions) | Deduplicate by keeping the highest affinity value: |
Related Skills
— Larger bioactivity dataset for SAR studies; complement GtoPdb curated potency data with ChEMBL's broader coveragechembl-database-bioactivity
— Translate GtoPdbunichem-database
orchemblId
fields to cross-database identifierspubchemCid
— Retrieve 3D binding structures for receptor-ligand pairs identified in GtoPdbpdb-database
— Integrate GtoPdb pharmacology data with genetic evidence and disease associations via Open Targetsopentargets-database
References
- Guide to Pharmacology REST API — Official web services documentation with all endpoint descriptions and example queries
- GtoPdb home page — Interactive database browser and target/ligand search
- Alexander et al., Br J Pharmacol 2023 — Concise Guide to Pharmacology 2023/24 — the data content reference for GtoPdb
- Harding et al., Nucleic Acids Res 2022 — GtoPdb database paper describing the data model, curation process, and API