25 characters. Zero confusion.

An open standard for human-safe identifiers. Visually distinct in any typeface, at any size, for any reader — including those with dyslexia.

Every ambiguous character in an ID is a future support ticket. HardGuard25 removes the 11 letters that get misread, mis-dictated, and OCR'd wrong — and keeps 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.

Visually distinct

No confusable pairs — no more O vs 0, I vs 1, S vs 5, or B vs 8 in printed or dictated identifiers.

Dyslexia-aware

Mirror pairs (B/D, Q/P) and visually-similar shapes (E/3) are removed to reduce error rates for dyslexic readers.

OCR-friendly

Works reliably with OCR-A, Menlo, and other monospace typefaces on receipts, labels, and printed materials.

RemovedReason
OConfusable with 0 (zero)
IConfusable with 1 (one) and lowercase L
LConfusable with 1 (one) and uppercase I
BConfusable with 8; dyslexia mirror pair with D
SConfusable with 5
ZConfusable with 2
EConfusable with 3 for dyslexic readers; digits take priority
QConfusable with O in some typefaces; dyslexia mirror pair with P
VConfusable with U in many typefaces
TResembles a plus sign in some contexts
XCollides 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:

LengthUnique IDsSweet spot for
4390,625Small inventory, tickets
6244 millionMedium businesses
8152 billionLarge systems
1259.6 trillionInternal tokens
163.55 × 1022Cross-system identifiers
202.11 × 1027Public tokens

Install

Reference implementations are available in JavaScript, Python, and Go. Each includes generation, validation, normalization, and an optional Mod-25 check digit.

JavaScript

npm install @snapsynapse/hardguard25

import { generate, validate, normalize, checkDigit }
  from '@snapsynapse/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.

AC3H–7PUW–K2MN–PR4Y