Validate a strong password with regex
The classic "strong password" regex is everywhere. Here's how to write one — and the case for not using it at all.
The classic pattern
const STRONG_RE = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$/;
STRONG_RE.test("Hello1!"); // false (too short)
STRONG_RE.test("Hello123!"); // true
STRONG_RE.test("HELLO123!"); // false (no lowercase)
Four positive lookaheads check for: a lowercase letter, an uppercase letter, a digit, and a non-word non-whitespace character (a symbol). The .{8,} requires 8+ chars total.
How it works
Each (?=...) is a lookahead — it checks a condition without consuming characters. The engine sits at position 0, runs all four lookaheads against the rest of the input, then runs .{8,}$ to confirm length. If any lookahead fails, the match fails.
Order doesn't matter; lookaheads can be in any sequence.
Customizing
// 12+ chars
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{12,}$/
// Add max length 64
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,64}$/
// Require 2 digits
/^(?=.*[a-z])(?=.*[A-Z])(?=(?:.*\d){2})(?=.*[^\w\s]).{8,}$/
The case against complexity rules
NIST's 2017 guidelines (still current) recommend against arbitrary complexity rules. Their reasoning:
- Complexity rules cause users to pick predictable patterns:
Password1!,Welcome2024! - They make passwords harder to type on mobile, leading to writing them down or reusing them
- Length is a far stronger signal than character variety
NIST recommends: minimum 8 chars, allow up to at least 64, allow all printable ASCII (including spaces), check against a list of known-bad passwords, and don't require complexity rules.
Practical recommendation
If you must enforce complexity (legacy systems, compliance requirements), use the regex above. Otherwise:
- Minimum 8-12 characters
- Maximum at least 64
- Check against a breach list (
haveibeenpwnedAPI has a free, anonymized endpoint) - Encourage passphrases (4+ words from a wordlist beats most complex passwords)
Regex for password strength is solving the wrong problem.