New to Rust? Grab our free Rust for Beginners eBook Get it free →
Node.js Password Generator: Generate a Secure Random Password
Build a secure random password generator in Node.js with crypto.randomInt(), configurable character groups, and a runnable test.

If you need a Node.js password generator for an account flow or internal tool, secure randomness and clear character-group rules matter more than a loop over Math.random(). This function uses crypto.randomInt() for secure random indexes and guarantees that every enabled group appears in the returned password.
What this password generator guarantees
The default call returns 16 characters with at least one lowercase letter, uppercase letter, number, and symbol, while impossible length requests throw an error rather than returning a weaker password.
Complete Node.js password generator
Save this file as password-generator.mjs, then let it select one character from each enabled group, fill the remaining positions from the combined alphabet, and shuffle the result so the required characters do not stay at the beginning.
import { randomInt } from 'node:crypto';
const LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';
const UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const NUMBERS = '0123456789';
const SYMBOLS = '!@#$%^&*_-+=';
export function generatePassword(length = 16, options = {}) {
const {
lowercase = true,
uppercase = true,
numbers = true,
symbols = true,
} = options;
const groups = [
lowercase ? LOWERCASE : '',
uppercase ? UPPERCASE : '',
numbers ? NUMBERS : '',
symbols ? SYMBOLS : '',
].filter(Boolean);
if (groups.length === 0) {
throw new RangeError('Select at least one character group');
}
if (!Number.isSafeInteger(length) || length < groups.length) {
throw new RangeError(`length must be an integer of at least ${groups.length}`);
}
const alphabet = groups.join('');
const password = groups.map((group) => group[randomInt(group.length)]);
while (password.length < length) {
password.push(alphabet[randomInt(alphabet.length)]);
}
for (let index = password.length - 1; index > 0; index -= 1) {
const swapIndex = randomInt(index + 1);
[password[index], password[swapIndex]] = [password[swapIndex], password[index]];
}
return password.join('');
}
const password = generatePassword();
console.log(password);
console.log({
length: password.length,
hasLowercase: /[a-z]/.test(password),
hasUppercase: /[A-Z]/.test(password),
hasNumber: /\d/.test(password),
hasSymbol: /[-!@#$%^&*_=+]/.test(password),
});
Run and test the generator
I ran the accompanying test on Node.js 24.18.0, and it checked 100 generated passwords plus the two invalid-option boundaries.
node password-generator.mjs

Every run returns a different string, so check the length and Boolean values rather than matching a fixed password value.
Why crypto.randomInt() matters
Math.random() is designed for general application randomness, not secret generation. Node.js documents crypto.randomInt() as avoiding modulo bias, so each index in the alphabet has an even chance of selection.
This distinction matters when the generated value will become an account password, reset secret, or credential. If you are building a login flow, pair the generated secret with JWT authentication in Node.js only where a signed token fits the request lifecycle.
Set the length and character groups
Pass a length as the first argument and enable or disable groups with the options object. A length of 20 with symbols disabled still includes lowercase letters, uppercase letters, and numbers.
const password = generatePassword(20, {
symbols: false,
});
console.log(password);
Use the online password generator when you need a browser-side password for yourself. Keep the Node.js function for a server-side flow where your application owns the generation step.
Do not store generated passwords as plain text
This function creates a password, not a storage system. It does not protect that password after generation or replace hashing, transport security, rate limits, and a password manager.
When you store a user password, hash it with a password hashing function such as bcrypt. The Node.js password hashing tutorial shows that separate storage step.
Next step
Run the test before moving the function into an account-creation or credential-reset route, then keep the character-group validation beside the generator.



