When I first started working with hydrogen bonding in protein-ligand docking, I kept getting the terminology backwards and the whole scoring function looked wrong because I was flagging acceptors as donors on half my queries.
Hydrogen bonding is everywhere in medicinal chemistry and structural biology, but the distinction between donor and acceptor trips people up constantly. I remember running a virtual screen for a kinase target where the ATP-site water network was making or breaking binding affinity. The program kept reporting zero H-bonds when I knew there had to be three based on the crystal structure. Turns out I had manually flipped the atom types in the input file. The donor and acceptor labels were reversed across the board, so the scoring engine was only looking for bonds in the wrong direction. It took me about four hours to realize the error and re-run the whole pipeline. A hydrogen bond donor is the atom carrying the hydrogen that participates in the bond. It is usually nitrogen or oxygen with at least one attached hydrogen. The key point is that the hydrogen itself is what bridges to the acceptor. In SMILES notation or a PDB file, a donor is typically identified by an N-H or O-H group. Some programs also count C-H donors in specific contexts, like the aromatic edge-to-face interactions you see in protein cores, but those are weak and most docking software ignores them entirely. An acceptor is the atom with lone pair electrons that pulls the hydrogen toward it. Oxygen and nitrogen are the standard acceptors, but sulfur and halogens can act as acceptors in certain geometries. The critical detail that beginners miss is that not every lone pair counts. An amide oxygen is a strong acceptor because its lone pairs are not delocalized away from the bonding region. A pyridine nitrogen is a good acceptor. But a quaternary ammonium nitrogen has no lone pair at all, so it cannot accept a hydrogen bond despite being positively charged.
Here is how I actually work through a structure to assign donor and acceptor status. I open the PDB file, locate the ligand, and walk through each heavy atom. For every nitrogen or oxygen, I ask two questions. First, does it have a hydrogen attached? If yes, it is a donor. Second, does it have available lone pairs? If yes, it is an acceptor. An atom can be both, which is common for hydroxyl groups and primary amines. A water molecule is the textbook example of a dual-purpose participant because each oxygen has two hydrogens and two lone pairs. The complication that nobody warns you about comes from tautomeric states. A histidine imidazole ring can shift its hydrogens between the two nitrogens depending on pH and local environment. At physiological pH around 7.4, the delta-nitrogen and epsilon-nitrogen can each be protonated independently. This means the same residue can present different donor and acceptor patterns in different protein environments. I learned this the hard way when a series of beta-lactamase inhibitors showed erratic SAR because the catalytic serine's hydrogen bonding partner switched tautomers between the free enzyme and the acyl-enzyme complex. The crystal structures had different histidine protonation states and the docking program could not account for that without explicit manual correction. Another thing that matters in practice is geometry. A hydrogen bond is not just about having the right atom types. The donor-hydrogen-acceptor angle needs to be roughly linear, ideally above 120 degrees. The distance between donor and acceptor should fall below 3.5 angstroms for a meaningful interaction. Most scoring functions enforce these thresholds automatically. If you are building your own interaction maps or validating docking results manually, you need to check both distance and angle because a favorable atom pair at poor geometry contributes almost nothing to binding energy.
I use a simple script-based approach to generate donor and acceptor lists before any docking run. I parse the mol2 or sdf file with RDKit and output a CSV with atom index, element type, hydrogen count, and acceptor flags. This takes roughly two minutes for a typical ligand library and saves me from wasting computation time on incorrect bond assignments. Without it, I was spending maybe twenty minutes per compound manually checking atom types in Chimera or PyMOL, which added up fast across hundreds of compounds. There are edge cases where the standard rules break down. Phosphoryl groups on serine or threonine have four oxygens but only two carry formal negative charge at physiological pH. The non-charged oxygens still participate in hydrogen bonds, but their acceptor strength differs significantly. Guanidine groups on arginine are special because the positive charge delocalizes across three nitrogens, making all of them reasonable acceptors while the NH2 group serves as a very strong donor. Carboxylate anions on aspartate and glutamate can accept multiple hydrogen bonds simultaneously, which is why they often anchor water molecules in binding pockets. One practical pitfall involves halogen bonds being confused with hydrogen bonds. A chlorine atom adjacent to a carbonyl can sometimes mimic acceptor geometry in low-resolution structures. X-ray data at 2.5 angstroms resolution might make this distinction unreliable. I recently worked on a project where the initial model placed a chloride ion in a pocket that turned out to be a weak halogen bond acceptor site. The real biology involved an asparagine side chain acting as a donor. Re-refining the model with correct atom typing changed the entire interpretation of the binding mode.
Get the Full Details

If you want to explore H Bond Donor Vs Acceptor assignments systematically, I recommend starting with RDKit's built-in functions. The GetDonors and GetAcceptors methods handle most standard cases correctly. For non-standard residues or covalent inhibitors, you may need to manually override atom properties. Glide's receptor preparation tool handles this well if you are using Schrödinger. AutoDock Vina relies on Gasteiger charge calculations that sometimes misassign acceptors on charged heterocycles, so I always double-check those manually. The real value of understanding donor and acceptor chemistry comes from noticing patterns across multiple structures. Strong binders usually optimize both the number and geometry of hydrogen bonds rather than maximizing count alone. Three well-placed hydrogen bonds with proper angles beat six mediocre ones every time. This is why fragment-based drug discovery focuses on high-affinity water displacement rather than adding bulk hydrogen bonding groups that never form properly in the final binding pose.