Querying ChEMBL for Target-Specific Bioactivity and Compound Data in Python

Python
ChEMBL
Cheminformatics
Author

Jay Chung

Published

July 5, 2026

chEMBL target query

Small, reusable Python utilities for pulling target-specific bioactivity and compound data from ChEMBL given a UniProt ID, and evaluating those compounds against Lipinski’s rule of five — adapted from TeachOpenCADD T001: Compound data acquisition (ChEMBL) and T002: Molecular filtering (Ro5).

Synthetic data representing pIC50 vs. molecular weight for EGFR inhibitors

Given a UniProt accession (e.g. P00533 for EGFR), it:

  1. Looks up the matching ChEMBL target(s)
  2. Fetches IC50 bioactivity data (human, exact measurements, binding assays)
  3. Filters to nM units and deduplicates by compound
  4. Fetches canonical SMILES for the resulting compounds
  5. Merges bioactivity + compound data and computes pIC50
  6. Optionally adds Lipinski’s rule of five (Ro5) property columns

… and returns a tidy pandas.DataFrame with columns:

| molecule_chembl_id | IC50 | units | smiles | pIC50 |

Adding Ro5 properties appends: molecular_weight, n_hba, n_hbd, logp, ro5_fulfilled.

Installation

git clone https://github.com/jaychung10010/chembl-target-query.git
cd chembl-target-query
pip install -r requirements.txt

Usage

A UniProt accession can map to multiple ChEMBL target entries (single protein, protein family, chimeric construct, protein-protein interaction, etc.), so the workflow is split into two steps — inspect, then extract. This avoids blocking input() prompts, so it works in any environment (plain scripts, Jupyter, agent-driven IDEs like Antigravity/Cursor where stdin isn’t interactive).

Code
from get_chembl_bioactivity_data import fetch_chembl_targets, get_chembl_bioactivity_data

# Step 1: see what ChEMBL targets match this UniProt ID
targets_df = fetch_chembl_targets("P00533")  # EGFR
print(targets_df)

Output:

Found 17 ChEMBL target(s) matching 'P00533':

        organism                                                                             pref_name target_chembl_id                  target_type
0   Homo sapiens                                                      Epidermal growth factor receptor        CHEMBL203               SINGLE PROTEIN
1   Homo sapiens                                                      Epidermal growth factor receptor        CHEMBL203               SINGLE PROTEIN
2   Homo sapiens                            Epidermal growth factor receptor and ErbB2 (HER1 and HER2)    CHEMBL2111431               PROTEIN FAMILY
3   Homo sapiens                                                      Epidermal growth factor receptor    CHEMBL2363049               PROTEIN FAMILY
4   Homo sapiens                            MER intracellular domain/EGFR extracellular domain chimera    CHEMBL3137284             CHIMERIC PROTEIN
5   Homo sapiens                                     Protein cereblon/Epidermal growth factor receptor    CHEMBL4523680  PROTEIN-PROTEIN INTERACTION
6   Homo sapiens                                                                           EGFR/PPP1CA    CHEMBL4523747  PROTEIN-PROTEIN INTERACTION
7   Homo sapiens           von Hippel-Lindau disease tumor suppressor/Epidermal growth factor receptor    CHEMBL4523998  PROTEIN-PROTEIN INTERACTION
8   Homo sapiens          Baculoviral IAP repeat-containing protein 2/Epidermal growth factor receptor    CHEMBL4802031  PROTEIN-PROTEIN INTERACTION
9   Homo sapiens                                                                             CCN2-EGFR    CHEMBL5465557  PROTEIN-PROTEIN INTERACTION
10  Homo sapiens  Microtubule-associated protein 1 light chain 3 beta/Epidermal growth factor receptor    CHEMBL6066839  PROTEIN-PROTEIN INTERACTION
11  Homo sapiens        Glucose-induced degradation protein 4 homolog/Epidermal growth factor receptor    CHEMBL6066845  PROTEIN-PROTEIN INTERACTION
12  Homo sapiens                     E3 ubiquitin-protein ligase Mdm2/Epidermal growth factor receptor    CHEMBL6193792  PROTEIN-PROTEIN INTERACTION
13  Homo sapiens                                                  UBR/Epidermal growth factor receptor    CHEMBL6193830  PROTEIN-PROTEIN INTERACTION
14  Homo sapiens       Protein zyg-11 homolog B/Protein zer-1 homolog/Epidermal growth factor receptor    CHEMBL6193837  PROTEIN-PROTEIN INTERACTION
15  Mus musculus                                     Protein cereblon/Epidermal growth factor receptor    CHEMBL6193841  PROTEIN-PROTEIN INTERACTION
16  Homo sapiens                   E3 ubiquitin-protein ligase RNF149/Epidermal growth factor receptor    CHEMBL6195769  PROTEIN-PROTEIN INTERACTION

Inspect the table above, then call get_chembl_bioactivity_data('P00533', target_index=<row>) with your chosen row index.
Code
# Step 2: extract bioactivity + compound data for the target you want
# (inspect targets_df above, then pick its row index)
df = get_chembl_bioactivity_data("P00533", target_index=0)
print(df.head())

Output:

molecule_chembl_id   IC50 units  \
0        CHEMBL63786  0.003    nM   
1        CHEMBL35820  0.006    nM   
2        CHEMBL53711  0.006    nM   
3        CHEMBL66031  0.008    nM   
4      CHEMBL5270693  0.008    nM   

                                              smiles      pIC50  
0                  Brc1cccc(Nc2ncnc3cc4ccccc4cc23)c1  11.522879  
1                CCOc1cc2ncnc(Nc3cccc(Br)c3)c2cc1OCC  11.221849  
2                 CN(C)c1cc2c(Nc3cccc(Br)c3)ncnc2cn1  11.221849  
3                Brc1cccc(Nc2ncnc3cc4[nH]cnc4cc23)c1  11.096910  
4  COc1cc(N2CCC(N(C)C)CC2)ccc1Nc1ncc(C(=O)Oc2cccc...  11.096910

Adding Lipinski’s rule of five (Ro5) properties:

Code
from get_chembl_bioactivity_data import add_ro5_properties

df = add_ro5_properties(df)
# adds: molecular_weight, n_hba, n_hbd, logp, ro5_fulfilled
print(df.head())

Output:

molecule_chembl_id   IC50 units  \
0        CHEMBL63786  0.003    nM   
1        CHEMBL35820  0.006    nM   
2        CHEMBL53711  0.006    nM   
3        CHEMBL66031  0.008    nM   
4      CHEMBL5270693  0.008    nM   

                                              smiles      pIC50  \
0                  Brc1cccc(Nc2ncnc3cc4ccccc4cc23)c1  11.522879   
1                CCOc1cc2ncnc(Nc3cccc(Br)c3)c2cc1OCC  11.221849   
2                 CN(C)c1cc2c(Nc3cccc(Br)c3)ncnc2cn1  11.221849   
3                Brc1cccc(Nc2ncnc3cc4[nH]cnc4cc23)c1  11.096910   
4  COc1cc(N2CCC(N(C)C)CC2)ccc1Nc1ncc(C(=O)Oc2cccc...  11.096910   

   molecular_weight  n_hba  n_hbd    logp  ro5_fulfilled  
0        349.021459      3      1  5.2891           True  
1        387.058239      5      1  4.9333           True  
2        343.043258      5      1  3.5969           True  
3        339.011957      4      2  4.0122           True  
4        562.269239      8      2  6.1267          False

Skipping target_index falls back to auto-selecting the first SINGLE PROTEIN + Homo sapiens match (printing a warning if none exists) — useful for unattended/batch runs over many targets:

Code
targets = ["P00533", "Q00534", "P07900"]  # example UniProt IDs
results = {uid: get_chembl_bioactivity_data(uid) for uid in targets}

API

fetch_chembl_targets(uniprot_id: str) -> pd.DataFrame

Queries and prints all ChEMBL targets matching a UniProt accession. Returns the DataFrame so you can inspect target_type, organism, and pref_name before choosing which row to extract.

get_chembl_bioactivity_data(uniprot_id, target_index=None, show_progress=True) -> pd.DataFrame

Runs the full extraction pipeline for the selected target and returns the merged, filtered bioactivity + compound DataFrame with pIC50 values.

convert_ic50_to_pic50(ic50_value: float) -> float

Converts an IC50 value in nM to pIC50 (9 - log10(IC50)).

calculate_ro5_properties(smiles: str) -> pd.Series

Computes molecular weight, H-bond acceptor/donor counts, logP, and Lipinski’s rule of five compliance (ro5_fulfilled, True if no more than one of the four Ro5 conditions is violated) for a single SMILES string.

add_ro5_properties(dataframe: pd.DataFrame, smiles_col: str = “smiles”) -> pd.DataFrame

Applies calculate_ro5_properties to every row of a DataFrame (e.g. the output of get_chembl_bioactivity_data) and returns a copy with the Ro5 columns appended.

Notes

  • Query speed depends heavily on how much bioactivity data exists for the target (a target can take from several seconds up to ~20 minutes) and on EBI server load — there’s no documented SLA for the public ChEMBL API.
  • This follows the exact filtering logic from TeachOpenCADD T001: IC50 measurements only, exact relation (=), binding assays (B), nM units, first-seen compound kept on duplicates.

Acknowledgments

Built on the chembl_webresource_client and adapted from the TeachOpenCADD platform (Volkamer Lab, Charité/FU Berlin).

License

MIT — see LICENSE.