Skip to content

SMILES Notation Explained

10 min read · updated August 11, 2026

SMILES is a line notation for a molecular graph: a depth-first walk over the atoms, written as text. It has a real grammar, and most of the confusion around it comes from three features — implicit hydrogens, aromaticity and canonicalisation — that each hide a decision the toolkit made for you.

Atoms, and the organic subset

David Weininger introduced SMILES in a 1988 paper in the Journal of Chemical Information and Computer Sciences; the community specification maintained since is OpenSMILES, which is the document to check when two implementations disagree.

An atom in brackets is fully specified: [Fe+2], [13CH4], [NH4+], [O-]. Inside brackets you write isotope, element, chirality, hydrogen count, charge, in that order, and nothing is inferred.

The organic subset — B, C, N, O, P, S, F, Cl, Br, I — may be written bare, and then hydrogens are filled in to reach the lowest normal valence. C is methane, not a bare carbon atom. O is water. CCO is ethanol, because the two carbons take three and two hydrogens respectively and the oxygen takes one. This is convenient and it is the source of a whole class of silent errors: a generative model that emits N where you meant a nitrogen radical has written ammonia, and nothing in the string looks wrong.

Bonds are - single, = double, # triple and : aromatic; single bonds between adjacent atoms are almost always left implicit. Lowercase letters mark aromatic atoms, so benzene is c1ccccc1 and could equally be written in Kekulé form as C1=CC=CC=C1. Both parse to the same molecule in any toolkit that perceives aromaticity, which is not quite the same as saying every toolkit agrees on which rings are aromatic.

Branches and ring closures

A branch is written in parentheses and the walk resumes afterwards. Acetic acid is CC(=O)O: methyl carbon, carbonyl carbon, a branch to the double-bonded oxygen, then back to the carbonyl carbon to continue to the hydroxyl oxygen.

A ring is written by breaking one bond and marking both ends with the same digit. In c1ccccc1 the two 1 labels are the two halves of the bond that closes the ring. Digits are reused freely once closed, which is why a steroid can be written with only the digits 1 to 4, and why a ring-closure digit above 9 must be written %10 rather than as two characters.

Disconnected components are separated by . — a salt is one SMILES string with a period in it, for instance [Na+].[Cl-]. That single character is responsible for an enormous share of real data-cleaning work, because a dataset of “molecules” scraped from a vendor catalogue is full of multi-component strings whose largest fragment is the thing you actually meant.

Worked: writing aspirin

Acetylsalicylic acid is a benzene ring carrying an acetyl ester and a carboxylic acid on adjacent positions. Build the string by walking it.

start at the acetyl methyl                    C
add the ester carbonyl carbon                CC
branch to its double-bonded oxygen           CC(=O)
continue to the ester oxygen                 CC(=O)O
attach the aromatic ring, opening ring 1     CC(=O)Oc1
walk four more aromatic carbons              CC(=O)Oc1ccc
...to the sixth, closing later               CC(=O)Oc1cccc
close the ring on the ortho carbon           CC(=O)Oc1ccccc1
add the carboxylic acid on that carbon       CC(=O)Oc1ccccc1C(=O)O

The final string is CC(=O)Oc1ccccc1C(=O)O. Note that the ortho relationship — the two substituents being on neighbouring ring atoms — is carried entirely by where the ring-closure digit falls. Move the 1 and you have written a different isomer with a string that still parses.

There are many valid SMILES for this molecule. Starting the walk at the carboxylic acid gives OC(=O)c1ccccc1OC(C)=O, the same graph. That multiplicity is exactly what canonicalisation exists to remove.

Stereochemistry

Tetrahedral chirality is written @ or @@ inside the atom brackets. The convention is positional, not R/S: looking from the first neighbour listed towards the chiral atom, the remaining neighbours in the order they are written appear anticlockwise for @ and clockwise for @@. L-alanine is N[C@@H](C)C(=O)O and D-alanine is N[C@H](C)C(=O)O. Because the tag depends on written order, rewriting the string with a different traversal flips the symbol while describing the same enantiomer — which is disorienting the first time and completely consistent.

Double-bond geometry uses / and \\ on the single bonds flanking the double bond: F/C=C/F is the trans isomer and F/C=C\\F is cis. The slashes describe the bonds around the double bond, so an unpaired slash is meaningless and a good parser will say so.

Unspecified stereo is a third state, distinct from both configurations. A dataset where 40% of the molecules have no stereo tags is not a dataset of flat molecules; it is a dataset where the stereochemistry was not recorded, and a model trained on it is learning from an under-determined label.

Canonical SMILES is toolkit-local

A canonical SMILES is produced by numbering the atoms with a deterministic algorithm and then always starting the walk from the same place. Weininger’s CANGEN uses a Morgan-style refinement with tie-breaking rules; RDKit and other toolkits use their own.

The consequence trips up almost every new pipeline: RDKit’s canonical SMILES for a molecule and another toolkit’s canonical SMILES for the same molecule are generally different strings, and even two RDKit versions can differ if the canonicalisation code changed. Canonical means “stable within this implementation”, not “universal”. If you need a cross-toolkit identity key, use the InChIKey — a 27-character hash whose first 14 characters encode the skeletal connectivity and the next block the stereochemistry and isotopes. Deduplicating a dataset by canonical SMILES string equality across two sources is a reliable way to keep duplicates.

Traps that bite pipelines

  • Aromaticity models differ. RDKit’s default perception is not Daylight’s. Rings such as azulene and various pyranones are treated differently, so a lowercase-aromatic string round-tripped through two toolkits can change form.
  • Parsing succeeds where sanitisation fails. In RDKit, Chem.MolFromSmiles returns None for a valence violation such as C(C)(C)(C)(C)C — five bonds on a neutral carbon. Always check for None; a generative model will hand you these.
  • SMARTS is a different language. Query features such as [#6;R] or [!C] are SMARTS, not SMILES, and feeding a SMARTS pattern to a SMILES parser mostly fails quietly rather than loudly.
  • Tokenisation is not character-level. A model reading SMILES must treat Cl and Br as single tokens and keep bracket atoms intact; splitting on characters turns chlorine into a carbon followed by an unparseable letter.
  • InChI is not a replacement for SMILES. It is a normalised identifier: excellent for equality tests, poor as a model input, because it is layered, verbose and far less learnable. Compute over SMILES and key on the InChIKey.