DevPik Logo
random string generatorpassword generatorAPI keyscrypto.getRandomValuesentropysecure tokenssession tokensCSRFUUIDdeveloper securityWeb Crypto API

Random String Generation: Passwords, API Keys & Secure Tokens Explained

A practical guide to generating random strings for passwords, API keys, and tokens. Why Math.random() is dangerous, what crypto.getRandomValues() does differently, how much entropy you actually need, and an opinionated quick-reference for every common use case.

ByMuhammad TayyabPublished:11 min read
Back to Blog
Random String Generation: Passwords, API Keys & Secure Tokens Explained

Why Random Strings Matter More Than You Think

Every modern application runs on randomness. Your session cookie, your API key, your database primary key, your password reset link, your OAuth state parameter, your CSRF token — every one of these is some form of random string. When the randomness is good, none of them are guessable. When the randomness is bad, your entire security model collapses, often invisibly.

The painful part: most developers learn this the hard way. They write Math.random().toString(36).substring(2, 15) because Stack Overflow''s top answer says to, ship it to production, and only discover months later that an attacker has predicted every "random" token they''ve issued because Math.random() is not, and was never, secure.

This guide covers what you actually need to know about generating random strings for security purposes — the difference between secure and insecure RNGs, how long your strings need to be, and what to use for which job.

If you just want to generate one right now, use the Random String Generator — it uses the browser''s cryptographic RNG and shows you the entropy in bits.

The Two RNGs Every Developer Must Distinguish

Browsers ship with two random number generators, and the difference between them is the entire security argument.

`Math.random()` is fast, deterministic given an internal state, and explicitly not for security. The V8 engine implements it as xorshift128+, a pseudo-random generator that produces statistically uniform output but whose internal state can be recovered from a small number of consecutive outputs. Mozilla''s documentation says it plainly: "Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security."

`crypto.getRandomValues()` (and the higher-level crypto.randomUUID()) is the Web Crypto API''s CSRNG. It pulls from the operating system''s entropy source — /dev/urandom on Linux, BCryptGenRandom on Windows, SecRandomCopyBytes on macOS — the same source TLS uses for session keys. Outputs are unpredictable even to the system itself.

The trade-off is essentially zero. crypto.getRandomValues() is fast enough for any use case short of generating gigabytes of randomness per second, and the API is one line longer than Math.random(). There is no reason to use Math.random() for anything that matters.

javascript
// ❌ DON''T — predictable, attacker can recover state
const id = Math.random().toString(36).substring(2, 15);

// ✅ DO — cryptographically secure
const buf = new Uint8Array(24);
crypto.getRandomValues(buf);
const id = btoa(String.fromCharCode(...buf))
  .replace(/\+/g, ''-'').replace(/\//g, ''_'').replace(/=/g, '''');

The Random String Family Tree

Not every random string is the same kind of thing. The right length, character set, and structure depend on what the string represents.

Passwords are random strings that humans (or password managers) need to type, paste, and occasionally read aloud. Length beats complexity every time — XKCD''s "correct horse battery staple" pointed this out a decade ago and nothing has changed since. A 16-character mixed-case-plus-symbol password has roughly 105 bits of entropy; that''s strong enough that a brute-force attack at one trillion guesses per second would take longer than the age of the universe. If a human will type it, exclude ambiguous characters like 0/O and 1/l/I.

API keys identify a calling application across requests. The industry baseline is 128 bits of entropy — about 22 alphanumeric characters or 32 hex characters. Stripe''s sk_live_* keys are 32 characters of base62 after the prefix. GitHub PATs are 40 hex characters. AWS access keys are 20 characters of base32. All give well over 100 bits of entropy.

Session tokens & bearer tokens are short-lived secrets that prove who a client is on subsequent requests. OWASP calls for at least 64 bits of entropy, recommends 128 bits. JWTs are signed but unencrypted by default — anyone holding one can read its payload, so don''t put secrets there. For pure session IDs (the random string in a cookie), 22+ alphanumeric characters does the job.

CSRF tokens & nonces have the same threat model as session tokens — needs to be unguessable, doesn''t need to be human-readable. 22 alphanumeric characters is plenty. The key property is that a fresh token is generated per session (or per request, in stricter setups).

UUIDs vs random strings: UUIDs (especially v4) are random strings with a specific 128-bit format and a version marker. Use them when something else expects a UUID format — database UUID columns, GraphQL ID fields, distributed systems where the format is contractually required. Use a free-form random string when format doesn''t matter and you want fewer characters or a custom alphabet. DevPik has a dedicated UUID Generator for the formatted case.

Entropy: The One Number That Matters

If you remember nothing else from this article, remember entropy. Entropy is measured in bits and tells you, exactly, how unpredictable a random string is.

The formula is length × log2(charset_size). So:

  • 8-character lowercase: 8 × log2(26) ≈ 38 bits. Crackable on a single GPU in hours.
  • 12-character alphanumeric: 12 × log2(62) ≈ 71 bits. Marginal — would take a well-funded attacker months.
  • 16-character mixed (all sets): 16 × log2(94) ≈ 105 bits. Safe against any current attacker.
  • 22-character alphanumeric: 22 × log2(62) ≈ 131 bits. Industry-standard "secure".
  • 32-character hex: 32 × log2(16) = 128 bits. The classic cryptographic threshold.

The standard threshold for "computationally infeasible to brute-force" is 80 bits. The standard threshold for "secure against a state-level attacker for the foreseeable future" is 128 bits. The DevPik Random String Generator shows entropy bits on every generation so you can pick a length deliberately rather than guessing.

API Key Best Practices

Generating the key is the easy part. Operating it well is what separates a robust system from a security incident.

Length: At least 22 alphanumeric characters (130+ bits). More is fine; more makes it harder to brute-force the keyspace if you ever leak a hash.

Character set: URL-safe base64 (A-Z a-z 0-9 - _) is the default. Avoid + and / (they need URL-encoding) and = padding. Hex is fine but takes more characters for the same entropy.

Prefix: Add a service-identifying prefix (Stripe''s sk_live_, GitHub''s ghp_). Why? Two reasons. First, GitHub''s secret scanner can recognize your keys in public repos and notify you. Second, when an engineer pastes a key into the wrong terminal, the prefix lets you immediately see what it is.

Storage: Hash the key in your database with bcrypt or Argon2. Show the full key to the user exactly once — at creation time. Never give users a way to retrieve an old key; they have to rotate. This way, a database leak doesn''t expose live keys.

Rotation: Build the rotation flow on day one. Issue every account two simultaneously valid keys; deprecate the old one a week later. If you don''t have a working rotation flow, you cannot respond to a leaked-key incident without taking the customer offline.

Logging: Never log full keys. Log a stable prefix (first 8 chars) plus the last 4. That gives ops enough to identify which key is making which request without putting the secret in your log retention.

Common Mistakes — A Hall of Shame

  1. Using `Math.random()` for any security-relevant value. Already covered. The single most common bug.
  1. Insufficient length. A 6-character random string is only 35 bits of entropy. That''s a billion possibilities — crackable on a GPU in seconds.
  1. Predictable character sets. Using only digits (Math.random() * 1000000 for an OTP) cuts entropy roughly 3x compared to alphanumeric. For OTPs that''s acceptable because they''re short-lived and rate-limited; for API keys it''s not.
  1. Encoding timestamps. ULIDs and KSUIDs do this on purpose for sortability, but a homemade scheme that prefixes a timestamp without enough random tail is guessable. If you generate two tokens for the same user in the same second, an attacker who sees one can dramatically narrow the search space for the other.
  1. Reusing session tokens after login. If you don''t rotate the session ID on privilege change (login, role change), session-fixation attacks become trivial.
  1. Putting secrets in JWT payloads. JWTs are signed but unencrypted. Anyone with the token can decode the payload. Use JWT Decoder to confirm what you''re actually sending; if you need to put sensitive data in the token, use an encrypted variant (JWE).
  1. Generating keys on the client and trusting them. A "random" string generated in a JavaScript bundle that the client controls is not random from the server''s perspective — the client could choose anything. Generate on the server, return to the client, and treat the returned value as the source of truth.

Quick Reference: What to Use When

Use caseLengthCharsetEntropy
User-typed password16 charsAll sets~105 bits
Generated password (in PW manager)24 charsAll sets~157 bits
API key32 charsAlphanumeric~190 bits
Session token22 charsURL-safe base64~131 bits
CSRF token22 charsURL-safe base64~131 bits
Email verification token32 charsURL-safe base64~191 bits
File upload ID16 charsAlphanumeric~95 bits
One-time code (OTP)6 digitsDigits~20 bits + rate limiting
Database primary keyUUID v4Hex + dashes122 bits

Generate Securely in One Click

The DevPik Random String Generator uses crypto.getRandomValues() for every output, shows entropy bits live, and includes presets for passwords, API keys, hex strings, tokens, and variable names. Bulk mode generates up to 100 strings at once for seeding test data or pre-issuing tokens. Need a UUID instead? The UUID Generator handles v4 generation with the same RNG.

Generate secure random strings, passwords, and API keys instantly with our free Random String Generator. Try our 49+ free developer tools.

🛠️ Try It Yourself

Put what you've learned into practice with our free tools:

Frequently Asked Questions

What is the safest way to generate a random string in JavaScript?
Use crypto.getRandomValues() — the Web Crypto API''s cryptographically secure RNG. It pulls from the OS entropy pool (the same source TLS uses) and is supported in every modern browser and Node.js 19+. Never use Math.random() for any security-related value; its output is predictable from a small number of samples.
How long should a random string be for security?
Aim for at least 80 bits of entropy for general unguessability and 128 bits for cryptographic safety against well-funded attackers. In practice that means: 16+ characters for human-typed passwords with mixed sets, 22+ alphanumeric characters for session/CSRF tokens, and 32+ characters for API keys.
What''s the difference between a random string and a UUID?
A UUID is a random string with a specific 128-bit format (8-4-4-4-12 hex with a version marker). Use a UUID when the consuming system expects that format — database UUID columns, GraphQL ID fields, etc. Use a free-form random string when format is your choice, you want shorter output, or you need a custom alphabet.
Is Math.random() ever okay to use?
For non-security purposes only — game logic, animation jitter, A/B-test bucketing where the bucket isn''t a secret, generating placeholder data. The moment the output influences who can access what, switch to crypto.getRandomValues().
How do I generate a random string in Node.js?
Use crypto.randomBytes(): `require(''crypto'').randomBytes(24).toString(''base64url'')` gives you a 32-character URL-safe random token. For UUIDs use crypto.randomUUID(). Both pull from the OS CSRNG.
What''s a secure password length in 2026?
16+ characters with mixed case, numbers, and symbols (~105 bits of entropy) is more than enough to defeat any current brute-force attacker. If a password manager is generating and storing it, go to 24+ characters for extra margin — there''s no usability cost.
Can I use the same random string for both an API key and a database primary key?
Don''t. API keys should be hashed at rest (so a database leak doesn''t expose live credentials); primary keys can''t be hashed because they need to be looked up directly. Generate them separately and store the hashed key in a column referenced by the primary key.
What is entropy in random string generation?
Entropy measures unpredictability in bits. A string with N bits of entropy could be any of 2^N possible values. Calculation: length × log2(charset_size). 80 bits is the baseline for ''hard to brute-force''; 128 bits is the cryptographic standard.
Muhammad Tayyab

Written by

Muhammad Tayyab

CEO & Founder at Mergemain

Muhammad Tayyab builds free, privacy-first developer tools at DevPik. He writes about AI trends, developer tools, and web technologies.

More Articles