About this snippet

Click Generate Password and the field fills with a new 16-character password drawn from uppercase and lowercase letters, digits and ten symbols. The copy button beside the field puts the password on the clipboard and turns green for a moment to confirm it worked.

Every character is picked with crypto.getRandomValues, the browser's cryptographically secure random number generator. Math.random is not suitable here, because MDN warns that it does not provide cryptographically secure random numbers. The randomIndex function also throws away the few 32-bit values at the very top of the range, so each of the 72 characters has exactly the same chance of being chosen. Sixteen characters from 72 gives about 98.7 bits of entropy.

To change the rules, edit the length constant or the chars string, for example to drop symbols that a site does not accept. The Clipboard API only works on secure pages, meaning HTTPS or localhost, so when writing to the clipboard fails the script selects the password instead and it can be copied with Ctrl+C or Cmd+C.

Size
3.0 KB
Uses
HTML, CSS, JavaScript
Loads
Nothing external
Views
563
<div class="pw-generator">
  <div class="pw-display">
    <input type="text" id="password" readonly placeholder="Generated Password" aria-label="Generated password">
    <button id="copyPass" type="button" aria-label="Copy password">
      <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
    </button>
  </div>
  <button id="genBtn" type="button" class="gen-btn">Generate Password</button>
</div>
.pw-generator {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  max-width: 350px;
  margin: 0 auto;
  background: #fff;
  padding: 30px;
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.05);
}
.pw-display {
  display: flex;
  background: #f3f4f6;
  padding: 5px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #e5e7eb;
}
#password {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  padding: 10px;
  font-family: monospace;
  font-size: 1.1rem;
  color: #1f2937;
  outline: none;
}
#copyPass {
  background: white;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  width: 40px;
  cursor: pointer;
  color: #4b5563;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.2s, border-color 0.2s;
}
#copyPass:hover {
  color: #2563eb;
  border-color: #3b82f6;
}
#copyPass.copied {
  color: #15803d;
  border-color: #15803d;
}
.gen-btn {
  width: 100%;
  padding: 12px;
  background: #2563eb;
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}
.gen-btn:hover {
  background: #1d4ed8;
}
const passwordInput = document.getElementById("password");
const genBtn = document.getElementById("genBtn");
const copyBtn = document.getElementById("copyPass");

const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
const length = 16;

function randomIndex(max) {
  const limit = Math.floor(2 ** 32 / max) * max;
  const value = new Uint32Array(1);
  do {
    crypto.getRandomValues(value);
  } while (value[0] >= limit);
  return value[0] % max;
}

function generatePassword() {
  let password = "";
  for (let i = 0; i < length; i++) {
    password += chars[randomIndex(chars.length)];
  }
  passwordInput.value = password;
}

genBtn.addEventListener("click", generatePassword);

copyBtn.addEventListener("click", async () => {
  if (!passwordInput.value) return;
  try {
    await navigator.clipboard.writeText(passwordInput.value);
    copyBtn.classList.add("copied");
    copyBtn.setAttribute("aria-label", "Copied");
    setTimeout(() => {
      copyBtn.classList.remove("copied");
      copyBtn.setAttribute("aria-label", "Copy password");
    }, 1500);
  } catch (error) {
    passwordInput.focus();
    passwordInput.select();
  }
});
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save