25 characters. Less confusion.
An open standard for human-safe identifiers, designed to exclude common visual confusables in dyslexia-sensitive and other human workflows.
Ambiguous characters can become support problems. HardGuard25 removes 11 letters associated with predictable visual, dictation, and OCR confusion while keeping all ten digits so versioning stays natural.
Why these 25 characters?
Standard alphanumerics give you 36 characters (0–9, A–Z). That creates real problems when a human reads, transcribes, or dictates a code out loud. HardGuard25 keeps all ten digits and fifteen carefully chosen letters, removing eleven sources of confusion. Design principle: when a letter and a digit compete for the same visual slot, the digit always wins.
Reduced confusables
Common digit-letter pairs such as O vs 0, I vs 1, S vs 5, and B vs 8 are excluded from printed or dictated identifiers.
Dyslexia-aware
Ambiguous shapes and mirror-prone pairs, including Q/P and E/3, are removed to reduce transcription risk for dyslexic readers.
OCR-conscious
Designed for use with OCR-A, Menlo, and other monospace typefaces on receipts, labels, and printed materials. Comparative OCR performance has not yet been benchmarked.
| Removed | Reason |
|---|---|
| O | Confusable with 0 (zero) |
| I | Confusable with 1 (one) and lowercase L |
| L | Confusable with 1 (one) and uppercase I |
| B | Confusable with 8; dyslexia mirror pair with D |
| S | Confusable with 5 |
| Z | Confusable with 2 |
| E | Confusable with 3 for dyslexic readers; digits take priority |
| Q | Confusable with O in some typefaces; dyslexia mirror pair with P |
| V | Confusable with U in many typefaces |
| T | Resembles a plus sign in some contexts |
| X | Collides with multiplication operator; varies by locale |
Entropy and length
Each HardGuard25 character carries log2(25) ≈ 4.64 bits of entropy. Pick a length for your risk profile:
| Length | Unique IDs | Sweet spot for |
|---|---|---|
| 4 | 390,625 | Small inventory, tickets |
| 6 | 244 million | Medium businesses |
| 8 | 152 billion | Large systems |
| 12 | 59.6 trillion | Internal tokens |
| 16 | 3.55 × 1022 | Cross-system identifiers |
| 20 | 2.11 × 1027 | Public tokens |
Install
Reference implementations are available in JavaScript, Python, and Go. Each includes generation, validation, normalization, and an optional Mod-25 check digit. For adopter guidance, read the implementation guide or the assistant guide. The plain-text guide has a SHA-256 sidecar for verification.
JavaScript
npm install hardguard25
import { generate, validate, normalize, checkDigit }
from 'hardguard25';
generate(8); // "AC3H7PUW"
generate(8, { checkDigit: true }); // + 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) # + check char
validate("AC3H-7PUW") # True
normalize("ac3h-7puw") # "AC3H7PUW"
Go
import "github.com/snapsynapse/hardguard25/go"
id, _ := hardguard25.Generate(8)
id, _ = hardguard25.GenerateWithCheck(8)
ok := hardguard25.Validate("AC3H-7PUW")
s, _ := hardguard25.Normalize("ac3h-7puw")
No library needed
# Alphabet 0123456789ACDFGHJKMNPRUWY # Regex ^[0-9ACDFGHJKMNPRUWY]+$ # Normalization: trim, strip separators, # uppercase, reject anything outside the set.
The alphabet is the standard. If you just need the character set, use it directly.
Try it live
The interactive generator produces real HardGuard25 codes in the browser — pick a length, quantity, grouping, case, and optional check digit.