DevKitHub

API & Security

Random String and Token Generator

Generate tokens, API keys, IDs and test data from a named or custom alphabet, or as random bytes encoded as hex or base64url. Everything is made in your browser from its cryptographic random source, with the entropy shown.

0 lines

Made in your browser with crypto.getRandomValues, using rejection sampling so every character is equally likely. Nothing is transmitted or logged. For a production key, generating it on the machine that will use it is better still.

This tool runs entirely in your browser. Your input is never uploaded, stored or logged.

How it works

There are two ways to make a random token, and most frameworks use the second. One picks each character independently from an alphabet. The other draws random bytes and encodes them, as Python’s secrets.token_hex(32), Node’s crypto.randomBytes(32).toString('hex') and openssl rand -hex 32 do. For hex the two are equivalent: 32 random bytes are 64 hex characters and 256 bits either way. Base64url is not quite: 32 bytes encode to 43 characters, but 256 bits fill only 42 of them and four bits of the last, so the final character takes only 16 of the 64 values, while 43 characters chosen one at a time carry 258 bits. Random bytes mode shows the equivalent OpenSSL, Python and Node.js call.

Picking characters is where generators go wrong. The obvious code, a random byte modulo 62, is biased, because 256 = 4 × 62 + 8: bytes 248 to 255 wrap round onto the first eight characters of the alphabet, 0 to 7, which then come up five times in 256 instead of four, 25% more often than the rest. The average loss is small, yet a 32-character string made only of those eight characters is about 450 times likelier than it should be, and the min-entropy, the figure that matters to an attacker who guesses the likeliest values first, falls from 190.5 to 181.7 bits. This generator uses rejection sampling instead: a byte at or above 248 is discarded and another drawn, which costs about 3% more bytes. Base58 discards 24 of every 256 bytes and digits discard 6; hex and base64url, whose sizes divide 256, discard none, which is one reason frameworks prefer them. The bytes come only from crypto.getRandomValues.

Entropy is length × log2(alphabet size), which holds only because every position is uniform and independent. A prefix such as sk_test_ adds nothing, since it is identical on every key. Providers add one anyway so that a leaked key can be found: GitHub’s secret scanning partner programme asks for a unique prefix, high-entropy random data and a checksum, and notifies the provider when a matching string appears in a public repository so the key can be revoked. GitHub’s own tokens start ghp_ and similar, with an underscore so a double-click selects the whole token. This tool adds the prefix but not a checksum. With Secret on, it warns below 128 bits, the minimum RFC 6749 sets for OAuth tokens. It never removes repeats from a batch, because that would bias it; it warns when repeats are likely instead.

Common problems

Every example below is run against this tool in our test suite, so what it says here is what the tool actually does.

The character set has 1 distinct character. At least 2 are needed; with one, every value is the same and there is no randomness at all.

aaaa
Why:
The custom set is de-duplicated before use, so a set made of one repeated character, or one left with a single character after look-alikes are removed, has nothing to choose between.
Fix:
Enter at least two different characters, or choose one of the named sets.

The custom character set contains a space, a line break or a control character.

abc xyz
Why:
Characters pasted as a list with spaces between the groups. A space in a token is trimmed by forms and splits shell arguments, and a line break would split the output list, so they are refused rather than quietly used.
Fix:
Remove the spaces and list the characters with nothing between them.

A custom set of a-z produces only the letters a and z and hyphens.

Why:
The custom set is taken literally, not as a regular-expression class, so a-z is three characters: a, a hyphen and z. The tool warns when it sees a pattern like that.
Fix:
Type every character you want, or choose Letters or Letters and digits from the list.

In your own generator, the characters 0 to 7 come up more often than the rest.

Why:
byte % 62 folds the eight byte values from 248 to 255 back onto the first eight characters, so each of those appears 5 times in 256 and every other character 4 times.
Fix:
Discard any byte at or above the largest multiple of the alphabet size and draw again, or generate bytes and encode them as hex or base64url, which need no correction.

A Base64 token works in a header but breaks in a URL or a form.

Why:
Standard Base64 contains + and / and pads with =. In a query string or a form body + decodes as a space, / splits a path, and = has to be escaped.
Fix:
Use base64url, which replaces + and / with - and _ and drops the padding. Python’s token_urlsafe and Node’s base64url encoding produce it.

Frequently asked questions

How long should an API key or token be?
At least 128 bits of entropy, which RFC 6749 requires of OAuth tokens: 32 hex characters, or 22 characters of letters and digits or of base64url. 256 bits (32 random bytes, 64 hex or 43 base64url characters) is the common default, and it is what Python’s secrets module uses when no size is given. OWASP’s minimum for session IDs is 64 bits.
What is the difference between this and a password generator?
A password is typed or remembered by a person, so a password generator deals with symbols, site rules and characters that look alike. A token is handled by software: it needs a URL-safe alphabet, a fixed length and a known entropy, and is usually made from random bytes. For passwords, use the password generator.
Why do API keys start with a prefix like sk_live_ or ghp_?
So that a leaked key can be recognised. A distinctive prefix lets secret scanners match the key with few false positives, and GitHub’s partner programme reports a match in a public repository to the provider, who can revoke the key. It also tells a person which service and environment a key belongs to. It adds no entropy, so the random part has to reach the target on its own.
Can I use a UUID as an API key?
The UUID specification says not to. RFC 9562 states that UUIDs must not be used as security capabilities, meaning identifiers whose mere possession grants access. A version 4 UUID has 122 random bits and the time-based versions have far fewer. Use a random token of at least 16 bytes instead.
Are the strings generated on your server?
No. They are made in your browser with crypto.getRandomValues and are never transmitted, stored or logged. For a production key it is still better to generate it where it will be used, with the commands shown in random bytes mode, than to copy it through any web page.

Last updated