HardGuard25: A 25-character alphabet for human-readable unique IDs

2 min read

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?

LengthUnique IDsGood for
4390,625Small inventory, tickets
6244 millionMedium businesses
8152 billionLarge systems
163.55 x 10^22Cross-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.

Spec is CC BY 4.0. Code is MIT.