MolHarbour
MolHarbour is a unofficial Python wrapper for the Molport REST API. It allows you to search for chemical compounds and retrieve information about them. Additionally, MolHarbour unifies the Molport API variables names and verifies the response data using wonderful Pydantic models.
This library is not affiliated with Molport in any way. Molport is a registered trademark of Molport SIA.
The project was initiated as a part of my master's thesis and and is based on refactored scripts which I wrote to retrive commercial availablity of compounds in chembl database.
Installation
From PyPI
pip install molharbor
From source
pip install git+https://github.com/asiomchen/molharbor
Quickstart
Authentication
To start using MolHarbour, you need to create an instance of the Molport class and log in to the Molport API using your username and password or API key.
from molharbor import Molport
molport = Molport()
molport.login(username="john.spade", password="fasdga34a3")
or API key
molport.login(api_key="16072de6-d318-4324-a82c-08c7dfe64d5d")
Compound search
You can search for compounds using the search method. All the search types are supported( via SearchType enum).
Additionally, you can specify the maximum number of results to return using the max_results parameter, and the minimum similarity threshold using the similarity parameter (it is used only for similarity search).
Exact search
from molharbor import SearchType
molport.find("O=C(O)c1ccccc1", search_type=SearchType.EXACT)
[
[
MolportCompound(
smiles="OC(=O)c1ccccc1",
molport_id="Molport-000-871-563",
link="https://www.molport.com/shop/compound/Molport-000-871-563",
),
MolportCompound(
smiles="[2H]c1c([2H])c([2H])c(c([2H])c1[2H])C(O)=O",
molport_id="Molport-003-927-939",
link="https://www.molport.com/shop/compound/Molport-003-927-939",
),
MolportCompound(
smiles="O[13C](=O)c1ccccc1",
molport_id="Molport-003-929-055",
link="https://www.molport.com/shop/compound/Molport-003-929-055",
),
MolportCompound(
smiles="OC(=O)[13c]1[13cH][13cH][13cH][13cH][13cH]1",
molport_id="Molport-046-688-787",
link="https://www.molport.com/shop/compound/Molport-046-688-787",
),
]
]
Similarity search
molport.find("O=C(O)c1ccccc1", search_type=SearchType.SIMILARITY, max_results=5)
[
[
MolportCompound(
smiles="OC(=O)c1ccccc1",
molport_id="Molport-000-871-563",
link="https://www.molport.com/shop/compound/Molport-000-871-563",
),
MolportCompound(
smiles="[2H]c1c([2H])c([2H])c(c([2H])c1[2H])C(O)=O",
molport_id="Molport-003-927-939",
link="https://www.molport.com/shop/compound/Molport-003-927-939",
),
MolportCompound(
smiles="O[13C](=O)c1ccccc1",
molport_id="Molport-003-929-055",
link="https://www.molport.com/shop/compound/Molport-003-929-055",
),
MolportCompound(
smiles="[Zn++].[O-]C(=O)c1ccccc1.[O-]C(=O)c1ccccc1",
molport_id="Molport-003-986-949",
link="https://www.molport.com/shop/compound/Molport-003-986-949",
),
MolportCompound(
smiles="OC(=O)[13c]1[13cH][13cH][13cH][13cH][13cH]1",
molport_id="Molport-046-688-787",
link="https://www.molport.com/shop/compound/Molport-046-688-787",
),
]
]
Superstructure search
molport.find("O=C(O)c1ccccc1", search_type=SearchType.SUPERSTRUCTURE, max_results=5)
[
[
MolportCompound(
smiles="CC=O",
molport_id="Molport-001-783-184",
link="https://www.molport.com/shop/compound/Molport-001-783-184",
),
MolportCompound(
smiles="OCc1ccccc1",
molport_id="Molport-001-783-216",
link="https://www.molport.com/shop/compound/Molport-001-783-216",
),
MolportCompound(
smiles="C=O",
molport_id="Molport-001-785-627",
link="https://www.molport.com/shop/compound/Molport-001-785-627",
),
MolportCompound(
smiles="CCO",
molport_id="Molport-001-785-844",
link="https://www.molport.com/shop/compound/Molport-001-785-844",
),
MolportCompound(
smiles="O",
molport_id="Molport-003-926-090",
link="https://www.molport.com/shop/compound/Molport-003-926-090",
),
]
]
Substructure search
molport.find("O=C(O)c1ccccc1", search_type=SearchType.SUBSTRUCTURE, max_results=5)
[
[
MolportCompound(
smiles="OC(=O)c1ccc2[nH]c(S)nc2c1",
molport_id="Molport-000-004-519",
link="https://www.molport.com/shop/compound/Molport-000-004-519",
),
MolportCompound(
smiles="OC(=O)c1cc(C#N)c(Cl)cc1Cl",
molport_id="Molport-051-434-827",
link="https://www.molport.com/shop/compound/Molport-051-434-827",
),
MolportCompound(
smiles="OC(=O)c1ccc(cc1)-c1ccc(cc1)-c1ccc(cc1)N(c1ccc(cc1)-c1ccc(cc1)-c1ccc(cc1)C(O)=O)c1ccc(cc1)-c1ccc(cc1)-c1ccc(cc1)C(O)=O",
molport_id="Molport-051-434-831",
link="https://www.molport.com/shop/compound/Molport-051-434-831",
),
MolportCompound(
smiles="COC(=O)[C@]1(C[C@H](OC(C)=O)[C@@H](NC(C)=O)[C@@H](O1)[C@H](OC(C)=O)[C@@H](COC(C)=O)OC(C)=O)O[C@H]1[C@@H](OC(=O)c2ccccc2)[C@@H](COC(=O)c2ccccc2)O[C@@H](Oc2ccc(OC)cc2)[C@@H]1OC(=O)c1ccccc1",
molport_id="Molport-051-434-926",
link="https://www.molport.com/shop/compound/Molport-051-434-926",
),
MolportCompound(
smiles="[Na+].[Na+].OC(=O)CN(CC([O-])=O)Cc1cc2c(Oc3cc(O)c(CN(CC(O)=O)CC([O-])=O)cc3C22OC(=O)c3ccccc23)cc1O",
molport_id="Molport-051-435-130",
link="https://www.molport.com/shop/compound/Molport-051-435-130",
),
]
]
Raw response manipulation
MolHarbour design to simplify commonn tasks so .find() method returns a list of MolportCompound objects (which itself is a dataclass object with smiles, molport_id and link field).
However, you can access the raw response using the return_response parameter. Returned Response object inherits from Pydantic BaseModel and contains all the fields from the Molport API response with type validation provided by Pydantic.
All the fields have the same name as in Molport API docs, only lowercase and the spaces are replaced with underscores( e.g. Shipment Type -> shipment_type)
from molharbor import SearchType
molport.find(
"O=C(O)c1ccccc1",
search_type=SearchType.SUBSTRUCTURE,
max_results=1,
return_response=False,
)
[
[
MolportCompound(
smiles="OC(=O)c1cc(C#N)c(Cl)cc1Cl",
molport_id="Molport-051-434-827",
link="https://www.molport.com/shop/compound/Molport-051-434-827",
)
]
]
vs
molport.find("O=C(O)c1ccccc1",
search_type=SearchType.SUBSTRUCTURE,
max_results=1,
return_response=True)
[Response(result=Result(status=1, message='Substructure search completed!'), data=Data(molecules=[Molecule(id=45........
Suppliers search
Having a Molport ID, you can search for suppliers using the get_suppliers method. Similar to the find() method, you can receive either a raw Pydantic response or a processed list of SupplierOffer models. Each offer represents one available packing from a supplier catalogue.
offers = molport.get_suppliers("Molport-001-794-639")
Or you could use id values of MolportCompound objects returned by find() method
result = molport.find("C[C@H](CS)C(=O)N1CCC[C@H]1C(O)=O", search_type=SearchType.EXACT, max_results=1)[0]
result
MolportCompound(smiles='C[C@H](CS)C(=O)N1CCC[C@H]1C(O)=O', molport_id='Molport-001-794-639', link=...
offers = molport.get_suppliers(result.molport_id)
Processed supplier offers
The returned models contain the supplier, catalogue, and packing fields from the MolPort response with Pydantic validation.
first_offer = offers[0]
first_offer.supplier_name
first_offer.price
first_offer.model_dump()
Applications that use pandas can construct a dataframe without making it a MolHarbor dependency:
import pandas as pd
df = pd.DataFrame(offer.model_dump() for offer in offers)
Raw response
molport.get_suppliers("Molport-000-871-563", return_response=True)
ResponseSupplier(result=Result(status=1, message='Molecule found!'), data=DataSupplier(molecule=Molecule2(id=871563, molport_id='Molport-000-871-563', smiles='OC(=O)c1ccccc1', .....
Contributing
Contributions are welcome!
We use uv for dependency management. To install the dependencies for development, run:
uv sync
Please make sure to update tests as appropriate. We use ruff for code formatting and linting. Please make sure to run it before opening a pull request.
Additionally, pre-commit hooks are set up to run ruff before each commit. To install them, run:
pre-commit install
Thank you for your contributions!
Metadata
Release files for molharbor 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| molharbor-0.1.6.tar.gz | 82.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| molharbor-0.1.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 96.5 kB
Release files / molharbor-0.1.6.tar.gz
| Download URL | molharbor-0.1.6.tar.gz |
|---|---|
| Size | 82.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f5aacf52f71f5a41239b24235aad8139d5859f8a9a1181ee51d5290f91efbc0
|
|
BLAKE2b-256 checksum How to use checksums |
94d2af48160dec381b41f311492162eb91f07080ce2bbc05a3695c3ec74f0bb9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.
Transparency logRelease files / molharbor-0.1.6-py3-none-any.whl
| Download URL | molharbor-0.1.6-py3-none-any.whl |
|---|---|
| Size | 14.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1992cd122fab7a6d7f00dbde0998cf95e5f2c39233e1f36093f1b841412b9079
|
|
BLAKE2b-256 checksum How to use checksums |
74d272389147a9895ed16bb8d2dd090ce18100c9eaabf82724395e1db101b1a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.
Transparency log