API Key Generator
Create copy-ready API keys with readable prefixes for live keys, test keys, internal apps, and integrations.
Use unique prefixes for live/test keys so logs and support screenshots are easier to read.
Designing API keys that hold up in production
An API key is a bearer credential: whoever holds the string can act as its owner, with no password, no second factor and — unless you build one — no expiry. That single property drives every decision below. A key is not proof of identity, it is proof of possession, and it should be designed for a world where it will eventually end up somewhere it was not meant to be.
How much randomness is enough
The only number that matters is entropy, and it comes from the alphabet and the length together. Each alphabet contributes a fixed amount per character:
- Base62 (A–Z, a–z, 0–9) — about 5.95 bits per character
- URL-safe (base64url, 64 symbols) — exactly 6 bits per character
- Hex (0–9, a–f) — exactly 4 bits per character
Aim for at least 128 bits in the random portion, which is the same security margin as an AES-128 key and is comfortably beyond brute force. In practice that means 22 base62 characters, 22 URL-safe characters, or 32 hex characters. This page defaults to a longer value than the minimum because the cost of extra characters is zero and it leaves headroom if you later truncate or prefix the key.
Hex is the weakest per character, so a hex key needs to be noticeably longer to reach the same strength. A 32-character hex key and a 32-character base62 key look the same length in a config file, but the base62 one carries 190 bits against the hex key's 128.
Why prefixes earn their space
A prefix costs a few characters and pays for itself repeatedly. Stripe's sk_live_ and sk_test_, GitHub's ghp_, and similar conventions exist for four practical reasons:
- Support triage. When someone pastes a key into a ticket or a screenshot, you can see at a glance that it is a test key and not panic — or see that it is a live key and revoke it immediately.
- Secret scanning. A distinctive, greppable prefix is what lets scanners find leaked keys in public repositories. A bare random string is indistinguishable from any other random string;
acme_live_is not. - Wrong-environment mistakes. Most production incidents involving keys are not attacks, they are a test key deployed to production or the reverse. A visible environment marker turns a silent failure into an obvious one.
- Database lookup. If you store keys hashed — and you should — a non-secret prefix gives you something to index on, so verification is a single indexed lookup rather than a scan.
Keep prefixes short, lowercase, and separated by an underscore. Put the environment in the prefix, not in a separate field somebody can forget to check.
Store a hash, not the key
Your database should never hold a usable API key. Store a hash and compare hashes at verification time, exactly as you would with a password — with one important difference.
Passwords need a deliberately slow hash such as bcrypt or Argon2, because human-chosen passwords have low entropy and the slowness is what makes guessing impractical. A 128-bit random API key has no such weakness: there is nothing to guess. A single round of SHA-256 is appropriate and is fast enough to run on every request without adding latency. Using bcrypt on API keys is a common and costly mistake — it can add tens of milliseconds to every authenticated call for no security gain.
The practical pattern is to store three columns: the non-secret prefix for lookup, the SHA-256 hash of the full key, and a last-four or short display fragment so the owner can recognize which key is which in a list.
Show it once
Display the full key exactly once, at creation, with a copy button and a clear warning that it will not be shown again. If a user loses it, issue a new one and revoke the old one. This is not user-hostile; it is the only behavior consistent with not storing the key, and every serious API provider now works this way.
A checksum makes leaks detectable
A useful refinement, popularized by GitHub, is to append a short checksum of the random portion to the end of the key. A secret scanner that finds a candidate string can then verify the checksum locally and know with high confidence that it is a real key, without calling your API at all. It costs four or five characters and it dramatically reduces false positives in automated leak detection.
One key per integration, scoped to what it needs
Issue a separate key for each integration, script, and environment rather than one key shared across everything. Two things follow from this that are hard to get any other way: you can revoke a compromised key without breaking every other integration, and your logs tell you which system made which call.
Scope keys to the narrowest permission set that works. A key that only reads invoices should not be able to issue refunds. When a key does leak, its scope is the difference between an inconvenience and an incident.
Rotation without downtime
Design for two valid keys at once from the beginning. The rotation sequence is then straightforward: issue a new key, deploy it to the consumer, confirm from your logs that traffic has moved to the new key, then revoke the old one. Without the overlap, rotation means a window of failed requests, which is why teams that cannot do it cleanly tend not to do it at all.
Add an expiry date to new keys and surface it in your dashboard. A key with no expiry is a key that will still be valid in five years, long after the contractor who generated it has moved on.
Never put a key in a URL
Query strings are logged by web servers, proxies, CDNs and analytics tools, they appear in browser history, and they can leak to third parties through the Referer header. Send keys in an Authorization header instead. This is the single most common way keys end up in places nobody intended.
Anything shipped to a client is public
A key embedded in a mobile app, a desktop binary, or a JavaScript bundle can be extracted. Obfuscation delays that by minutes, not months. If a client genuinely needs to call an API, put a server of your own in between that holds the real key, or use a token flow that issues short-lived, narrowly scoped credentials per user. Treat any key that has ever been shipped to a client as already published.
Rate limit per key
Attach rate limits and quotas to the key rather than to the IP address. This contains the damage from a leaked key, gives you a signal when one starts behaving unusually, and stops a single misbehaving integration from degrading service for everyone else. A sudden change in a key's request pattern is often the first evidence that it has been compromised.
Related password tools
FAQ
How long should an API key be?
Long enough for at least 128 bits of randomness. That is 22 base62 characters, 22 URL-safe characters, or 32 hex characters. Below roughly 80 bits a key becomes worth attacking; above 128 there is no practical benefit, only longer strings.
Should API keys have prefixes?
Yes. A prefix tells you at a glance whether a key is live or test, gives secret scanners something greppable to find in public repositories, and provides a non-secret value to index on when you store keys hashed. Keep it short and lowercase, and put the environment in it.
Is base62 better than hex?
Per character, yes — base62 carries about 5.95 bits against hex's 4. A 32-character base62 key holds roughly 190 bits; the same length in hex holds 128. Hex is still fine, it just needs to be longer to reach the same strength. Use URL-safe if the key will travel through systems that dislike mixed case.
How should I store API keys in my database?
Store a SHA-256 hash of the key, a short non-secret prefix to index on, and a display fragment such as the last four characters. Never store the key itself — if your database is read, every key in it is live.
Should I use bcrypt or Argon2 on API keys?
No, and this is a common expensive mistake. Slow hashes exist to make guessing low-entropy human passwords impractical. A 128-bit random key has nothing to guess, so a single round of SHA-256 gives the same security and runs fast enough to use on every request. Bcrypt here adds latency to every authenticated call and buys nothing.
Can I show the key again later?
Not if you are storing it correctly. Display it once at creation with a copy button and a clear warning, then only ever show the prefix and last few characters. If someone loses a key, issue a replacement and revoke the old one.
How do I rotate a key without breaking the integration?
Support two valid keys at once. Issue the new key, deploy it to the consumer, watch your logs until traffic has moved over, then revoke the old one. Build this in from the start — teams that cannot rotate without downtime usually end up never rotating.
Is it safe to put an API key in a URL?
No. Query strings are written to web server, proxy and CDN logs, saved in browser history, and can leak to other sites through the Referer header. Send the key in an Authorization header instead. URLs are the most common route by which keys end up somewhere unintended.
Can I embed a key in my mobile app or front-end JavaScript?
Anything shipped to a client can be extracted, and obfuscation buys minutes rather than months. Put your own server in front of the API so the real key stays server-side, or use a flow that issues short-lived per-user tokens. Treat any key that has shipped to a client as already public.
What is the checksum some providers append to keys?
A few characters derived from the random portion, so that a secret scanner finding a candidate string can confirm locally that it is a genuine key without calling your API. It costs almost nothing and makes automated leak detection far more reliable.
Are the keys generated here stored or transmitted?
No. They are produced in your browser by the Web Crypto API's getRandomValues, which draws from your operating system's cryptographic random source. Nothing reaches StashGrid. For a production key it is still reasonable to generate it on the machine that will hold it.