Skip to content

Username

Sign in with a username instead of an email, with configurable validation and normalization. Mirrors the TS username() plugin.

Enable

python
from better_auth import BetterAuth
from better_auth.plugins_ext import UsernamePlugin

auth = BetterAuth(
    secret="a-strong-32-character-minimum-secret",
    plugins=[UsernamePlugin(min_username_length=3, max_username_length=30)],
)

Options

OptionTypeDefaultDescription
min_username_lengthint3Minimum length.
max_username_lengthint30Maximum length.
username_validatorcallable | NoneNone(username) -> bool extra format check.
display_username_validatorcallable | NoneNoneValidator for displayUsername.
username_normalizationcallable | bool | NoneNoneNormalizer applied on write (default lowercases); False disables.
display_username_normalizationcallable | boolFalseNormalizer for displayUsername.
validation_orderdict | NoneNoneRun validation before or after normalization.
schemadict | NoneNoneField-name overrides for the added columns.

Endpoints

MethodPath
POST/sign-in/username
POST/is-username-available

Schema

TableAdded columns
userusername (unique), displayUsername

Notes

  • /sign-in/username equalizes timing — a wrong username still runs a dummy password hash — and never leaks EMAIL_NOT_VERIFIED before a correct password.
  • Validation errors are 400s on /sign-up/email and /update-user (HTTP before-hooks) and 422s on /sign-in/username and /is-username-available, matching TS.

MIT licensed · API-compatible with better-auth