Random String Generator

Random strings from crypto.getRandomValues with rejection sampling, the entropy in bits, and the collision chance for the batch you asked for.

Enable JavaScript to customise; default output below.

base58 leaves out the characters that look alike; urlsafe is the base64url alphabet, safe in a path or a query string.

22 characters of alphanumeric is 131 bits, which is the usual floor for anything that grants access.

A label such as sk_ or user_. It is not a secret and it is left out of the entropy figure.

Live preview random-strings.txt
# 5 strings, 32 characters from 62
# 190.5 bits each
generated-in-your-browser

Output is valid and updates as you type.

The line most random strings get written as is Math.random().toString(36).slice(2). It is fast, it is four words long, and it is the wrong tool for anything that functions as a secret: Math.random is a pseudo-random generator seeded from whatever the engine felt like, and its future output is derivable from enough of its past output.

This uses crypto.getRandomValues, and it does the other thing that line gets wrong: it picks characters by rejection sampling rather than by taking a byte modulo the alphabet size. 256 does not divide by 62, so the modulo makes the first eight characters of the alphabet more likely than the rest.

Every string is generated in your browser when the page loads, and the entropy is stated in bits rather than described as secure.

How to use

  1. Pick the alphabet. urlsafe for anything going in a path or a query string, base58 for anything a human will read out, hex for identifiers.
  2. Set the length. 22 characters of alphanumeric is 131 bits.
  3. Add a prefix if you label your tokens, and read the collision figure before you use one as a database key.

Example

Five 32-character alphanumeric strings with an sk_ prefix:

sk_qz6aw2MeC39vWyGLNxkpkz94wj0HbLgL
sk_eRHErI4HbxQcKPBSRb585g1sH5Yf4qpM
sk_ah3pyPyDSIbFctstGk7HpQ3MyuMGMNOA
sk_2hvXqPFmTmpnGyrHGe7GBv62T8WyBHzP
sk_9pKyVXBpVQbgMJqvUgTzsdY3TWQmM2Nm

Alphabet                        62 characters (alphanumeric)
Length                          32
Entropy each                    190.5 bits
Keyspace                        2^190.5
Collision chance in this batch  under 1 in a trillion

Yours will differ. 190 bits is more than anything needs; 128 is the usual floor for a token that grants access, and at 62 characters that is 22 of them.

Pitfalls

Math.random is not random enough for a secret. It is a PRNG with a hidden seed and enough structure that its state can be recovered from its output. Use it for test fixtures and animation jitter. Not for tokens, not for password resets, not for anything a person should not be able to guess.

A modulo skews the distribution. byte % 62 maps 256 values onto 62, and because 256 = 4 × 62 + 8, the first eight characters get five chances and the rest get four. On a 32-character string that is a measurable bias, and rejection sampling costs nothing worth counting.

A prefix is not entropy. sk_live_ is on the front of every one of your keys and in your documentation. The figures here count the random part only, which is the only honest way to count them.

Length in characters is not length in bits. Sixteen hex characters is 64 bits and sixteen alphanumeric characters is 95, because the alphabet is larger. Read the bits, not the character count.

Check the collision figure for keys. A random string is safe as a primary key when the chance of drawing the same one twice across the whole table is negligible. At 64 bits and a million rows that chance is about one in thirty-seven million, which is fine. At 32 bits and a million rows a collision is a near certainty, because the chance grows with the square of the row count and eight hex characters is only four billion values.

Client-side generation means the value is in the browser. That is the point here, and it is a reason to be careful: a production secret should be generated where it will live, by the server or the CLI that owns it. This tool is for development keys, test fixtures, seeds and one-off identifiers.

Compatibility

crypto.getRandomValues is in every browser since around 2013, and it is the API backed by the platform’s own cryptographic random source. Nothing is uploaded and nothing is stored: the strings exist in your tab and in your clipboard.

The page recomputes on load, so what you see is yours and not the build’s. During the build there is no randomness available, so the compiled default output is a placeholder, which is the only correct thing to bake into a shared page.

Entropy is length × log2(alphabet), which is exact for a uniform draw and is the only meaningful measure of a random string. The collision figure uses the birthday approximation, n(n−1)/2 ÷ 2^bits, which is accurate while the probability is small.

urlsafe is the base64url alphabet: A-Z a-z 0-9 - _. It survives a path segment, a query string, a filename and a header without escaping.

Frequently asked questions

How long should a token be?
128 bits for anything that authenticates: 22 alphanumeric characters, 32 hex characters, or 22 base64url characters. Shorter is fine for a slug or a filename where guessing gains nothing.
Is this better than a UUID?
Different. A v4 UUID is 122 random bits in a fixed 36-character format, which is a sensible default and slightly wasteful in a URL. A 22-character alphanumeric string carries about the same entropy in 22 characters.
Why avoid 0, O, I and l?
Because somebody will read the string over the phone or type it off a screen. That is what base58 is for: it drops the four characters that get confused, at the cost of 0.1 bits per character.
Can I get the same strings again?
No. There is no seed field, deliberately: a seeded generator means anyone with the seed can reproduce every string you will ever generate. Save the output.
Are these safe as password reset tokens?
The values are strong enough at 128 bits or more. Whether the flow is safe depends on the expiry, the single use and the storage, none of which a string generator can give you. Generate reset tokens on the server that will verify them.
Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.