Strong Password Regex
Validates that a password is at least 8 characters long and contains a lowercase letter, an uppercase letter, a digit, and a special character, using lookahead assertions.
Regex Pattern
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$Pattern Breakdown
Hover over a token to see what it does.
| Token | Meaning |
|---|---|
| (?=.*[a-z]) | Positive lookahead requiring at least one lowercase letter anywhere in the string. |
| (?=.*[A-Z]) | Positive lookahead requiring at least one uppercase letter anywhere in the string. |
| (?=.*\d) | Positive lookahead requiring at least one digit anywhere in the string. |
| (?=.*[!@#$%^&*]) | Positive lookahead requiring at least one special character from the given set. |
| [A-Za-z\d!@#$%^&*]{8,} | The actual match: 8 or more characters, each drawn from letters, digits, or the allowed special characters. |
| ^ | Anchors the checks to the start of the string. |
| $ | Anchors the match to the end of the string. |
Detailed Explanation
What it does
This pattern enforces a common 'strong password' policy: the password must be at least 8 characters, and must contain at least one lowercase letter, one uppercase letter, one digit, and one special character from a fixed set. Every character in the password must also come from an allowed set of letters, digits, and specials.
Why it works
Each `(?=...)` is a zero-width positive lookahead: it checks that a condition holds somewhere ahead in the string without consuming any characters, which is why four lookaheads can be stacked back to back at the same starting position. After all four conditions are confirmed to hold somewhere in the string, the final `[A-Za-z\d!@#$%^&*]{8,}` actually consumes and validates the whole string, ensuring both the composition rules and the character whitelist are satisfied together.
Common use cases
- Enforcing password complexity rules during account sign-up
- Client-side validation feedback before submitting a password change form
- Server-side defense-in-depth validation alongside a password strength meter
- Generating consistent password policy documentation for a security review
Edge cases
- A password with all required character classes but using a special character outside the allowed set, like a comma, fails the whitelist even though it 'feels' complex
- Very long passwords are still accepted since the length quantifier is unbounded ({8,}), which is desirable for passphrases
- Unicode letters (e.g. accented characters) are not matched by [A-Za-z], so passwords in other scripts may fail even if 'strong'
- A password consisting only of the four required categories repeated, like 'Aa1!Aa1!', passes even though it is highly predictable
Limitations
- Does not check against common password dictionaries or known-breached password lists
- Does not measure actual entropy, so it can approve weak-but-technically-compliant passwords like 'Passw0rd!'
- The special character set is fixed and does not include every symbol some systems allow (e.g. spaces, brackets, or Unicode symbols)
- Does not support Unicode letters outside the basic Latin alphabet without modification
Interactive Tester
Edit the pattern or text below — matching runs live in your browser.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass |
Language Variants
Production-ready examples in 12 languages.
const strongPasswordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;
function isStrongPassword(value) {
return strongPasswordPattern.test(value);
}
console.log(isStrongPassword("Passw0rd!")); // trueCommon Mistakes
Assuming Go's or Rust's standard regex engines support lookahead the same way JavaScript does.
Fix: RE2-based engines (Go's regexp, Rust's regex crate) don't support lookahead; compose the check from several simple regexes or manual character scans instead.
Forgetting that the character class at the end restricts the entire password, so a special character outside the allowed set causes a full rejection.
Fix: Expand the allowed character class (and the corresponding lookahead) to include every symbol your policy should accept.
Believing a regex-passing password is automatically secure.
Fix: Pair format validation with a breached-password check (e.g. against the Have I Been Pwned range API) and an entropy estimator like zxcvbn.
Performance Notes
- Each lookahead independently scans up to the full string with `.*`, so four lookaheads mean roughly four linear scans, which is still fast for realistic password lengths.
- Because lookaheads are zero-width, they don't consume input, so there's no backtracking interaction between them and the final matching group.
- The unbounded `{8,}` quantifier is safe here since it's a simple character class with no nested or overlapping quantifiers, so there's no catastrophic backtracking risk.
Browser Compatibility
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | Lookahead assertions are supported in all modern JavaScript engines. |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |