An API key has exactly one job: be unguessable. Everything else — the prefix, the encoding, the length — exists to make it easier to handle, revoke and recognise. This generator draws raw bytes from crypto.getRandomValues, your operating system's cryptographically secure pseudorandom number generator, then encodes them in whichever alphabet your system expects.
How many bits you actually need
Entropy is the only number that matters, and it is set by the number of random bytes drawn, not by how long the encoded string looks. Thirty-two random bytes are 256 bits of entropy whether you render them as 64 hex characters or 43 Base64 characters.
| Bits | Bytes | Verdict |
|---|---|---|
| 64 | 8 | Too weak for anything long-lived |
| 128 | 16 | The practical floor. Beyond reach of brute force |
| 256 | 32 | The sensible default for API keys and signing secrets |
| 512 | 64 | No additional security against brute force; useful only when a spec demands it |
| 1024 | 128 | Costs you bandwidth and log volume, buys nothing |
At 128 bits, an attacker running a trillion guesses per second needs longer than the age of the universe. The reason to prefer 256 is not that 128 is breakable — it is that 256 costs almost nothing and removes the argument entirely.
Encoding changes the length, not the strength
Each encoding packs a different number of bits into each character:
- Hex — 4 bits per character. Longest output, but unambiguous and easy to eyeball.
- Base64 — 6 bits per character. Compact, but contains
+and/, which break in URLs. - Base64URL — 6 bits per character, swapping
+/for-_. Safe in URLs, filenames and headers. - Base32 — 5 bits per character, uppercase only, no ambiguous glyphs. Choose it when a human must read the key aloud or type it from a screen.
- Base58 — omits
0,O,Iandlentirely, so transcription errors are far less likely.
Prefixes are worth adding
A prefix like sk_live_ costs nothing and pays for itself several times over. It lets secret scanners recognise the key with a high-confidence regex, it tells an engineer reading a log which system the key belongs to, and it makes production keys visually distinct from test keys. The convention is service, then environment, then a trailing underscore so the random body is easy to split off.
Store the hash, not the key
Show a generated key once, then store only a hash of it. Because the key already has full entropy, a fast hash such as SHA-256 is correct here — key stretching with bcrypt or Argon2 exists to compensate for low-entropy human passwords, and applying it to a 256-bit random value only slows your own authentication path. Keep a short prefix and the last four characters in plaintext so you can display sk_live_…7f2a in a dashboard without storing the secret.
Frequently asked questions
Is this generator actually secure?
The randomness comes from crypto.getRandomValues, which browsers implement using the operating system's CSPRNG — the same source /dev/urandom and BCryptGenRandom expose. It is suitable for production key material. What matters more is that generation happens in your browser: a server-side generator cannot prove to you which bytes it produced or whether it kept a copy.
Does a longer key make my API more secure?
Past about 128 bits, no. Brute force stops being the attack. Keys leak through commits, logs, screenshots and over-broad scopes, and a 1024-bit key leaks exactly as easily as a 128-bit one. Spend the effort on rotation, scoping and detection instead of length.
Should I use hex or Base64?
Base64URL if the key travels in URLs or headers and you want it compact. Hex if humans will compare keys by eye — the fixed 4-bits-per-character mapping makes truncation obvious. Base32 or Base58 if anyone will ever read the key aloud or retype it.
Can I generate keys for a specific provider's format?
Yes — the provider key format generator reproduces the shapes used by Stripe, GitHub, AWS, OpenAI and others, for testing detectors and fixtures. Those keys are format-accurate but not valid credentials.
How do I know this key was not logged somewhere?
Load this page, disconnect from the network, and generate a key. It still works, because there is no server involved. You can also watch your browser's network tab while generating — no request is made.