Standard ID alphabets include characters that look identical at normal reading sizes. O and 0. I and 1 and l. S and 5. B and 8. For dyslexic readers, d and b, q and p. Every one of these is a support ticket, a failed lookup, or a phone call where someone spells the same code three times.
Crockford Base32 has been the go-to fix since 2002, but it only removes 4 characters. HardGuard25 removes 11: the digit lookalikes, the dyslexia mirror pairs, and operator lookalikes like T (+) and X (*) that break spreadsheets and URLs.
The alphabet:
0 1 2 3 4 5 6 7 8 9 A C D F G H J K M N P R U W Y
The rule: when a letter and a digit compete for the same visual slot, the digit always wins.
Quickstart
JavaScript
npm install @snapsynapse/hardguard25
import { generate, validate, normalize, checkDigit } from '@snapsynapse/hardguard25';
generate(8); // "AC3H7PUW"
generate(8, { checkDigit: true }); // "AC3H7PUW" + check char
validate("AC3H-7PUW"); // true
normalize("ac3h-7puw"); // "AC3H7PUW"
Python
pip install hardguard25
from hardguard25 import generate, validate, normalize, check_digit
generate(8) # "AC3H7PUW"
generate(8, check_digit=True) # "AC3H7PUW" + check char
validate("AC3H-7PUW") # True
normalize("ac3h-7puw") # "AC3H7PUW"
Go
import "github.com/snapsynapse/hardguard25/go"
id, _ := hardguard25.Generate(8)
ok := hardguard25.Validate("AC3H-7PUW")
s := hardguard25.Normalize("ac3h-7puw")
No library needed? The alphabet is the standard. Use it directly: 0123456789ACDFGHJKMNPRUWY
Where it fits
Order numbers, tracking codes, license keys, patient IDs, booking references, device IDs, promo codes, QR payloads, one-time passcodes. If it gets printed on a label, read over the phone, entered by hand, or scanned by OCR, it should be HardGuard25.
How long should IDs be?
| Length | Unique IDs | Good for |
|---|---|---|
| 4 | 390,625 | Small inventory, tickets |
| 6 | 244 million | Medium businesses |
| 8 | 152 billion | Large systems |
| 16 | 3.55 x 10^22 | Cross-system identifiers |
Each character provides 4.64 bits of entropy.
When not to use it
Cryptographic keys (use proper key derivation), blockchain consensus (use domain-specific formats), systems requiring UUID guarantees (use UUIDv7 or ULID), or machine-only contexts where no human ever sees the ID.
Links
Spec is CC BY 4.0. Code is MIT.
What character set are you using for human-facing IDs? Curious how many people have hit the O/0 problem in production.
Top comments (0)