Skip to content

Username Regex (Letters, Digits, _ and -)

Allow usernames of 3 to 16 characters made of letters, digits, underscores and hyphens, always starting with a letter.

JavaScript
127 characters

One case per line; the m flag makes ^ and the end anchor work line by line.

Link optionspattern only

The address bar holds the pattern, flags and replacement, so Copy link shares them. Your test text stays out of it unless you include it (up to 2,000 characters), because it may be private. Nothing is sent to a server.

Matches

7matches

The first is “alice”, at position 0.

Groups
none
Characters matched
53 of 127
What the pattern meansHover or tap a part to see it in the pattern and what it matched
How this works: Method, 5 sources, Checked against 1 worked example,

How this works

Method

Your pattern runs in your own browser’s JavaScript engine, in a background worker that is stopped after 1.5 seconds, so a pattern that backtracks catastrophically can’t freeze the page. The explanation comes from our own parser of the ECMAScript pattern grammar, checked against the engine; what each part matched is found by wrapping that part in one more group and running the pattern again. Conversions to other flavours only rewrite the syntax and list what their documentation says works differently.

How it’s tested

One worked example for this page is checked by automated tests before every release: given the inputs, the tool must show the expected answer.

Changes

  • First published, with a library of 19 common patterns and their test cases.

How we make toolsReport a mistake

Worked example

Take alice, the first case in the tester. Reading the pattern left to right, each part takes its share of the text:

  1. ^The start of the text (matches a position, no characters)
  2. [A-Za-z]One character: A–Z or a–z matches a
  3. [A-Za-z0-9_-]{2,15}Two to 15 characters, each A–Z, a–z, 0–9, “_” or “-” matches lice
  4. $The end of the text (matches a position, no characters)

How the username regex works

The pattern has two parts. \[A-Za-z]\ is the first character, which must be a letter, so a username can never be mistaken for a number or begin with punctuation. \[A-Za-z0-9_-]{2,15}\ is everything after it: letters, digits, underscores and hyphens, between 2 and 15 more, which makes 3 to 16 characters in all. The hyphen is last inside the brackets, where it means a literal hyphen rather than a range.

Choose the limits for your product, not from habit. A minimum of 3 avoids one-letter names that are hard to search for; a maximum keeps names fitting in the interface. Change \{2,15}\ to \{2,29}\ and you allow up to 30 characters. If you also want to ban two separators in a row ("a__b") or a separator at the end, add a negative lookahead such as \(?!.*[_-]{2})\ after the caret.

Many sites now accept names in any script. With the u flag, \^\p{L}[\p{L}\p{N}_-]{2,15}\ plus the end anchor allows "josé", "Zoë" and "Ελένη": \\p{L}\ is any letter and \\p{N}\ any number. Unicode brings its own problems, though: letters that look alike across scripts (a Latin a and a Cyrillic а) let one person impersonate another. Normalise names to NFC, compare them case-insensitively, and consider limiting each name to one script.

  • RFC 8265 defines how to prepare and compare internationalised usernames, applying Unicode Normalization Form C and, in one profile, mapping capitals to lower case. Source: RFC 8265: PRECIS usernames and passwords.
  • In JavaScript, \p{…} Unicode property escapes such as \p{L} only work with the u or v flag; without one, \p is just the letter p. Source: MDN: Unicode character class escape.

Test cases

Every case runs as an automated test of this page’s pattern, so the table can’t drift from what the pattern really does.

Test cases for the Username regex
TextResultWhy
alicePassesplain letters
bob_smithPasseswith an underscore
dev-ops42Passeshyphen and digits after the first letter
Z3r0Passesmixed case is allowed
jo_2026Passesshort and ends in digits
abcPassesthree characters, the minimum
SixteenCharsLongPassessixteen characters, the maximum
2coolFailsstarts with a digit
abFailstoo short
this_name_is_way_too_longFailsover 16 characters
john.doeFailsdots aren’t allowed
joséFailsé isn’t A–Z: see the Unicode version
_hiddenFailsstarts with an underscore
space nameFailscontains a space

What it doesn’t check

  • Case is not handled: Alice and alice both pass, so compare usernames in lower case when checking for duplicates.
  • It doesn’t block reserved names such as admin, root or support; keep a separate list for those.
  • The ASCII version rejects accented and non-Latin names, which can feel unwelcoming to many visitors.
  • Without the u flag, the length limits count UTF-16 code units, so in the Unicode version always add the u flag.

The same pattern in other languages

Converted automatically from the JavaScript version; the tester above always runs JavaScript.

The pattern in Python, PCRE, Go, Java and .NET
FlavourPatternNotes
Python^[A-Za-z][A-Za-z0-9_\-]{2,15}\ZPython's re has no \p{L}; in str patterns [^\W\d_] matches any letter, or install the third-party regex module for \p{…}.
PCRE^[A-Za-z][A-Za-z0-9_\-]{2,15}\z
Go^[A-Za-z][A-Za-z0-9_\-]{2,15}$
Java^[A-Za-z][A-Za-z0-9_\-]{2,15}\zJava supports \p{L} directly; add Pattern.UNICODE_CHARACTER_CLASS if you also want \w and \d to cover non-ASCII characters.
.NET^[A-Za-z][A-Za-z0-9_\-]{2,15}\z

Sources

Frequently Asked Questions

What characters should a username allow?

Letters and digits, plus one or two separators such as underscore and hyphen, are safe in URLs and easy to type. Starting with a letter avoids names that look like numbers or IDs.

How do I allow accented or non-English usernames?

Use Unicode property escapes for letters and numbers with the u flag. Then normalise the name to NFC and compare it case-insensitively so visually identical names can’t be registered twice.

How do I stop usernames ending with an underscore?

Change the last part so the final character must be a letter or digit, or add a negative lookahead that rejects a separator before the end. Test both forms in the tester above.