Glossary

crypto.getRandomValues

crypto.getRandomValues is the Web Crypto method that overwrites an integer typed array with cryptographically strong random values and returns the same array. It is defined by the W3C Web Cryptography specification and is the only member of the Crypto interface that also works on pages served without HTTPS. One call can fill at most 65,536 bytes.

How it works

You allocate the array first, and the method fills it in place. The browser draws from a pseudorandom generator that is seeded from operating system entropy, so the output is suitable for tokens, salts and initialization vectors. The specification sets no minimum entropy and tells implementations to do their best.

  • Allowed arrays: Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array and BigUint64Array.
  • Float32Array, Float64Array and plain arrays throw a TypeMismatchError.
  • The limit is on bytes, not elements: 65,536 for Uint8Array, 32,768 for Uint16Array, 16,384 for Uint32Array and 8,192 for BigUint64Array. One more element throws QuotaExceededError.
  • The return value is the array you passed, not a copy.
const a = new Uint8Array(16);
console.log(crypto.getRandomValues(a) === a, a.length);
console.log(Array.from(crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join('').length);
const big = new Uint8Array(65536); crypto.getRandomValues(big); console.log('65536 bytes ok');
for (const A of [Uint8Array, Uint16Array, Uint32Array, BigUint64Array]) {
  const max = 65536 / A.BYTES_PER_ELEMENT;
  try { crypto.getRandomValues(new A(max + 1)); } catch (e) { console.log(A.name, max + 1, e.name); }
}
try { crypto.getRandomValues(new Float32Array(1)); } catch (e) { console.log(e.name); }

Output from Node.js 22.22.0:

true 16
32
65536 bytes ok
Uint8Array 65537 QuotaExceededError
Uint16Array 32769 QuotaExceededError
Uint32Array 16385 QuotaExceededError
BigUint64Array 8193 QuotaExceededError
TypeMismatchError

How do you generate a random integer in a range securely?

Draw a Uint32 and reject values that would skew the result, instead of using a plain modulo. A 32-bit value has 4,294,967,296 possibilities, and 2 to the power 32 modulo 6 is 4, so a dice roll made with buf[0] % 6 favors the first four faces slightly. Rejection sampling removes the bias:

function randomInt(max) {
  const limit = 2 ** 32 - (2 ** 32 % max);
  const buf = new Uint32Array(1);
  do { crypto.getRandomValues(buf); } while (buf[0] >= limit);
  return buf[0] % max;
}

For max 6 the limit is 4294967292, so four values are discarded and the rest map evenly. The bias for small ranges is tiny, but it is easy to avoid, and it matters for large ranges.

Is Math.random safe for tokens?

No. Math.random is not designed to be unpredictable, and its algorithm is up to the engine. Use getRandomValues for session IDs, password reset tokens, API keys and anything an attacker would profit from guessing.

Common pitfalls

  • Requesting too many bytes: a 100,000-byte Uint8Array throws QuotaExceededError. Fill it in chunks of 65,536 bytes or less.
  • Using a float array: Float64Array throws TypeMismatchError. Fill a Uint32Array and divide if you need a fraction, and accept the 32-bit resolution.
  • Modulo bias: value % n is uneven when n does not divide 2 to the power of the bit width. Reject the tail as shown above.
  • Treating hex length as byte length: 16 random bytes become 32 hex characters, or 24 characters in Base64 with padding.
  • Deriving keys from it directly: the specification says not to generate keys with getRandomValues. Use generateKey in crypto.subtle instead.
  • Hand-rolled UUIDs: crypto.randomUUID returns a ready-made 36-character version 4 UUID, but only in secure contexts.

Related terms

  • crypto.subtle — the SubtleCrypto object where key generation belongs
  • UUID — a 128-bit identifier often built from random bytes
  • UUIDv4 — the random UUID variant that randomUUID produces
  • Nano ID — a compact ID generator that relies on secure random bytes
  • API key — a secret that should come from a secure random source
  • Base64 — a common way to print random bytes as text

See also