Where the randomness comes from
Every character is drawn with crypto.getRandomValues, the browser's cryptographically secure pseudo-random number generator (CSPRNG), which is seeded from the operating system. Math.random is never used: it is fast and fine for shuffling a playlist, but its output is predictable from a few observed values and it must not be used for secrets.
Selection is unbiased. Picking a character with random % alphabetSize slightly favours the first characters of the alphabet whenever the alphabet size does not divide the random range evenly. This generator uses rejection sampling, discarding values that would introduce that bias, so every character is equally likely.
How long is long enough
The strength of a random string is its entropy: length × log₂(alphabet size) bits. The status line shows it for the current settings.
| Use | Target | Example |
|---|---|---|
| Session ID, CSRF token | ≥ 128 bits | 22 characters of A–Z a–z 0–9 (62 symbols, 5.95 bits each) |
| API key or secret | ≥ 128 bits, 256 preferred | 32 hex characters = 128 bits; 43 Base64url characters = 256 bits |
| Password (human-typed) | ≥ 80 bits | 14 characters from the full 88-symbol set |
| Short verification code | Rate-limited, not entropy-based | 6 digits give only 20 bits: safe only with attempt limits |
A string with 128 bits of entropy has 3.4 × 1038 possibilities. Guessing it is not a realistic attack; leaking it through logs, URLs or version control is.
Passwords versus secrets
For anything a machine stores, longer is free: use 32 or more characters. For a password a person must type, prefer length over symbol variety; a 20-character string of letters and digits is stronger than 10 characters with every symbol, and it is easier to type on a phone. The skip ambiguous option removes 0 O o I l 1 | and quotes, which helps when the value will be read aloud or copied by hand.
If you generate a password here, store it in a password manager immediately. The page does not keep it, and there is no way to retrieve it later.
In code
JavaScript
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
const bytes = crypto.getRandomValues(new Uint8Array(32));
// Simple but slightly biased when 256 % alphabet.length !== 0:
const s = [...bytes].map(b => alphabet[b % alphabet.length]).join("");
// Node: unbiased helpers in node:crypto
import { randomBytes, randomInt } from "node:crypto";
randomBytes(32).toString("base64url"); // 43 chars, 256 bits
Python
import secrets, string
secrets.token_hex(16) # 32 hex chars, 128 bits
secrets.token_urlsafe(32) # 43 chars, 256 bits
"".join(secrets.choice(string.ascii_letters + string.digits) for _ in range(24))
Command line
openssl rand -hex 32
openssl rand -base64 32
head -c 32 /dev/urandom | base64
Privacy
Generation is entirely local. Nothing is transmitted, logged or stored, and reloading the page produces different values.