JavaScript Password Generator

Generate cryptographically secure passwords in JavaScript using crypto.getRandomValues(), the same API this entire site's password generator is built on.

The Secure Way (Browser)

crypto.getRandomValues() is supported in every modern browser and fills a typed array with cryptographically secure random values from the OS.

javascript
function generatePassword(length = 20, options = {}) {
  const { upper = true, lower = true, digits = true, symbols = true } = options;
  const pools = [];
  if (upper)   pools.push('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
  if (lower)   pools.push('abcdefghijklmnopqrstuvwxyz');
  if (digits)  pools.push('0123456789');
  if (symbols) pools.push('!@#$%^&*()-_=+[]{}');

  if (pools.length === 0) throw new Error('At least one character type required');

  function secureIndex(max) {
    // Rejection sampling avoids modulo bias
    const arr = new Uint32Array(1);
    const limit = Math.floor(0x100000000 / max) * max;
    let value;
    do { crypto.getRandomValues(arr); value = arr[0]; } while (value >= limit);
    return value % max;
  }

  const fullPool = pools.join('');
  const required = pools.map(pool => pool[secureIndex(pool.length)]);
  const rest = Array.from({ length: length - required.length },
    () => fullPool[secureIndex(fullPool.length)]);

  const chars = required.concat(rest);
  // Fisher-Yates shuffle using the same secure source
  for (let i = chars.length - 1; i > 0; i--) {
    const j = secureIndex(i + 1);
    [chars[i], chars[j]] = [chars[j], chars[i]];
  }
  return chars.join('');
}

console.log(generatePassword(20));
// e.g. 'qP7$vRt2Xz!mQ9wLp#4v'

The Wrong Way (Don't Do This)

Never use Math.random() for passwords, tokens, or session identifiers. It is explicitly documented as not cryptographically secure and its output can be distinguished from true randomness.
javascript: insecure, do not use
// INSECURE: Math.random() is not cryptographically secure
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let password = '';
for (let i = 0; i < 16; i++) {
  password += chars[Math.floor(Math.random() * chars.length)];
}

Node.js (Without the Web Crypto API)

Node.js 19+ exposes crypto.getRandomValues() globally. On older versions, use the built-in crypto module's randomInt():

javascript (node.js)
const crypto = require('crypto');

function generatePassword(length = 20) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';
  let password = '';
  for (let i = 0; i < length; i++) {
    password += chars[crypto.randomInt(0, chars.length)]; // uniform, no bias
  }
  return password;
}

Common Mistakes

Frequently Asked Questions

The ECMAScript specification explicitly does not guarantee Math.random() is cryptographically secure. Browsers implement it with fast, non-cryptographic PRNGs whose internal state can potentially be inferred from observed output, making any password derived from it theoretically predictable.

Yes, as of Node.js 19 the Web Crypto API is available globally. On older versions, use the built-in crypto module's randomBytes() or randomInt(), which are equally secure.

Use rejection sampling: compute the largest multiple of your pool length that fits in the random number's range, and discard (redraw) any value at or above that threshold before applying the modulo. The example above implements this in secureIndex().

Prefer not to write the code?

Our password generator runs the exact same principle in your browser right now.

Use the Password Generator โ†’

Related