How to use this Random String Generator
Choose the desired string length and how many strings you want to create. Then select which
character groups should be included, such as lowercase letters, uppercase letters, numbers,
and symbols. Click Generate Strings to create the result instantly.
- Set the string length.
- Set how many strings to generate.
- Choose the character groups to include.
- Click Generate Strings.
- Copy or download the output if needed.
Common uses
- Testing forms and validation flows
- Mock data and placeholders
- Example IDs and demo content
- Development and QA workflows
- Quick non-sensitive sample values
What this tool can control
- String length
- Number of results
- Lowercase letters
- Uppercase letters
- Numbers and symbols
These strings are safe for real secrets
Unlike most quick "random string" tools, this one does not use
Math.random(). It draws every character from
crypto.getRandomValues() — a cryptographically secure random number
generator (CSPRNG) — and maps those raw values onto your chosen alphabet with a
rejection-sampling helper (randomIndex()) that keeps the result perfectly
uniform. Because the output is both unpredictable and uniform,
it is suitable for security-sensitive values: session tokens, cryptographic salts,
temporary passwords, and API keys, as well as ordinary test data.
That combination matters. Unpredictability without uniformity still leaks strength, and
uniformity without unpredictability (as with a seeded pseudo-random generator) is guessable.
You need both, and the sections below explain exactly how this tool achieves each.
Modulo bias: the trap that "looks random" but isn't
crypto.getRandomValues() hands you raw values — think of bytes in the range
0–255. The obvious way to turn a byte into an index into a 62-character
alphabet (A–Z, a–z, 0–9) is
byte % 62. That is where the bias creeps in.
The 256 possible byte values do not divide evenly into 62 buckets:
256 = 4 × 62 + 8, remainder 8. So the first 8 characters of
the alphabet can be produced by 5 different byte values each (probability
5/256), while the other 54 characters map from only 4 byte values each
(4/256). Those first 8 characters are 25% more likely to
appear. Spread across a whole string, that skew makes the output non-uniform and quietly
shaves off entropy — the string is weaker than its length suggests. The
danger is that it still looks perfectly random to the eye, which is precisely why
this bug survives in so much security code.
How rejection sampling removes the bias
The fix is not to squeeze every random value into a bucket, but to throw some
away. Find the largest multiple of n (your alphabet size) that fits
inside the random value's range, then draw a value: if it lands below that multiple, use it;
if it falls into the leftover "remainder" zone above it, discard it and draw
again. Every value you keep maps to exactly one of the n buckets, so
all characters end up equally likely — genuinely uniform, with no bias to shave off entropy.
That is what this tool's randomIndex() function does. It works over 32-bit
values from crypto.getRandomValues(), computes
limit = Math.floor(232 / n) * n, and keeps redrawing until the value
is below limit before taking value % n. The only cost is
occasionally spending an extra draw — a negligible price for a distribution that is exactly
even.
CSPRNG versus a plain PRNG
The reason security tokens must never come from Math.random() comes down to
predictability. crypto.getRandomValues() is a
CSPRNG: an attacker who observes some of its output cannot compute what
came before or what comes next. Math.random() is an ordinary
PRNG — fast and statistically fine for dice and shuffles, but its internal
state (an xorshift128+ variant in V8) can be reconstructed from a handful of
outputs, after which the whole stream is predictable.
A string built from a predictable generator has no real secrecy even if it passes every
statistical randomness test, because "looks random" and "is unguessable" are different
properties. This tool uses the CSPRNG for exactly that reason; a casual, non-secret random
value where predictability is harmless is a fine job for the
Random Number Generator instead.
How much entropy does your string actually have?
A string of length L drawn from an alphabet of n symbols carries
L × log2(n) bits of entropy — but only if every
symbol is chosen uniformly and independently, which requires both a CSPRNG and the absence
of modulo bias. Miss either and the real entropy is lower than the formula claims. A
worked example: 16 characters over a 62-symbol alphabet gives
16 × log2(62) ≈ 16 × 5.954 ≈ 95 bits, comfortably
strong for a token.
Excluding look-alike characters (0/O,
1/l/I) improves readability, but it shrinks
n and therefore the entropy per character — so add a little length to
compensate. To hit a target strength, invert the formula:
length = ceil(target_bits / log2(n)). For 128 bits over a 62-symbol
alphabet that is ceil(128 / 5.954) = 22 characters.
Frequently Asked Questions
Are these strings safe for tokens, API keys, or passwords?
Yes. This tool uses crypto.getRandomValues(), a cryptographically secure
generator, and maps its output onto your alphabet with rejection sampling so there is
no modulo bias. The result is both unpredictable and uniform, which is what
security-sensitive values require. Pick a length that gives you enough entropy for the
use case.
What is modulo bias, and why does "rand % n" matter?
If you fold raw random bytes onto an alphabet with byte % n and 256 is not
a multiple of n, some characters come up more often than others. For a
62-character set, 256 = 4 × 62 + 8, so the first 8 characters occur with
probability 5/256 versus 4/256 for the rest — a real skew that
weakens the string even though it still looks random.
How does rejection sampling remove the bias?
It discards the values that would cause the skew. The generator computes the largest
multiple of n that fits the random range, and any draw landing in the
leftover remainder zone above it is thrown away and redrawn. Every value that is kept
maps to exactly one bucket, so all characters are equally likely.
Is crypto.getRandomValues() better than Math.random()?
For anything secret, yes. crypto.getRandomValues() is a CSPRNG — its
output cannot be predicted from past values. Math.random() is an ordinary
PRNG whose internal state can be reconstructed from a few outputs, so it must never
produce tokens or keys. This tool uses the CSPRNG.
How much entropy does my string have?
A length-L string over an n-symbol alphabet carries
L × log2(n) bits, provided the characters are uniform and
independent. For example, 16 characters over a 62-symbol alphabet is about
16 × 5.954 ≈ 95 bits — plenty for a token.
Should I exclude look-alike characters like 0/O and 1/l?
It is a trade-off. Removing them makes strings easier to read aloud or transcribe, but
it shrinks the alphabet and so lowers the entropy per character. If you exclude them,
add a little length to compensate — use
length = ceil(target_bits / log2(n)) for the smaller
n.