Secure Random String Generation in JavaScript (Beyond Math.random)
Learn how to generate secure random strings in JavaScript using crypto.getRandomValues and crypto.randomBytes for passwords, API keys, and tokens.
Secure random strings power passwords, API keys, session tokens, verification codes, and many other security-critical features. This guide explains how to generate cryptographically secure random strings in JavaScript, going far beyond simple Math.random() snippets. For a complete solution, check out our Random String Generator tool.
The Problem with Math.random()
If you search for "random string JavaScript", you will still find many examples that look like this:
function generateToken(length) {
let token = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let index = 0; index < length; index += 1) {
const charIndex = Math.floor(Math.random() * characters.length);
token += characters[charIndex];
}
return token;
}This kind of function feels random, but it is not strong enough for anything related to security. The problem is not the loop or the character set, it is the use of Math.random(), which was never designed to be a cryptographically secure random number generator.
Math.random() is fine for UI effects, demos, and simple random number generation, but it can be predictable in ways that matter for attackers. A determined attacker who can observe enough outputs and knows the underlying algorithm may be able to reconstruct the internal state and guess future values. For a refresher on the basics, see our guide on random number generation.
Using Cryptographically Secure APIs
For any security-sensitive string you should always use a cryptographically secure pseudo-random number generator (CSPRNG). In modern JavaScript that means using crypto.getRandomValues() in the browser or crypto.randomBytes() in Node.js.
Browser Implementation: Web Crypto API
Here is a safe pattern for generating random strings in the browser using crypto.getRandomValues():
function generateSecureToken(length) {
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const alphabetLength = alphabet.length;
const randomValues = new Uint8Array(length);
window.crypto.getRandomValues(randomValues);
let token = '';
for (let index = 0; index < randomValues.length; index += 1) {
const charIndex = randomValues[index] % alphabetLength;
token += alphabet[charIndex];
}
return token;
}
console.log(generateSecureToken(32));This approach reads high-entropy random bytes from the browser's cryptographic API, then maps each byte into the desired character set. You can easily change the alphabet to include only digits, add symbols for stronger passwords, or remove ambiguous characters like 0 and O. This is the same principle used in our UUID generator.
Node.js Implementation
In Node.js you can use the built-in crypto.randomBytes() function to implement the same idea on the server side:
import crypto from 'crypto';
function generateSecureToken(length) {
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const alphabetLength = alphabet.length;
const randomBytes = crypto.randomBytes(length);
let token = '';
for (let index = 0; index < randomBytes.length; index += 1) {
const charIndex = randomBytes[index] % alphabetLength;
token += alphabet[charIndex];
}
return token;
}
console.log(generateSecureToken(32));Best Practices for Security Tokens
Once you have a secure primitive, you can adapt it to many different use cases. For passwords you might favor longer strings and include symbols, while for API tokens you may prefer URL-safe characters only. You can also generate multiple tokens at once for batch operations.
Even with a strong CSPRNG there is always a theoretical chance of collision, but for reasonably long strings (for example 32 random characters from a large alphabet) the probability is astronomically small. If you need absolute guarantees, you can combine random strings with uniqueness checks in your database or add contextual information like user IDs and timestamps.
In addition to generating secure values, you should also follow best practices for storage and rotation. Passwords should be hashed using modern password hashing functions like Argon2 or bcrypt, and API keys or session tokens should be revocable and rotated periodically. For more on backend security, see how we handle PDF generation on the server side.
Conclusion
If you want to experiment with these patterns without writing all the boilerplate yourself, try the JavaScript Random String Generator tool on jsgenerator.com. It lets you tweak length and character sets, uses cryptographic randomness under the hood, and shows ready-to-paste snippets for both browser and Node.js environments.
Frequently Asked Questions
Is Math.random() secure for passwords?
No, Math.random() is not cryptographically secure and can be predicted. For security, use the Web Crypto API or Node.js crypto module.
How to generate a secure random string in JavaScript?
Use window.crypto.getRandomValues() in the browser or crypto.randomBytes() in Node.js to get high-entropy random bytes, then map them to your desired character set.
What is a CSPRNG in JavaScript?
CSPRNG stands for Cryptographically Secure Pseudo-Random Number Generator. In JS, it is implemented through the crypto API.
Try the JavaScript Random String Generator
Generate cryptographically secure random strings for passwords, API keys, and session tokens, then copy production-ready JavaScript snippets for browser and Node.js.
Open the JavaScript Random String Generator tool