Skip to content
UsageRail

API key generator

Secure random API keys with a prefix and a checksum, made in your browser. Pick a format, copy, done.

About 190 bits of randomness, plus a prefix and a CRC32 checksum

2 to 10 lowercase letters or digits

Environment
How many

Your keys appear here.

Generated in your browser with crypto.getRandomValues. Nothing is sent anywhere.

Want your customers to create keys like these themselves? Try UsageRail free.

The check runs in your browser too.

What makes a good API key

An API key only has one job: prove that a request comes from a customer you issued it to. That puts three requirements on the format, and two nice-to-haves.

  • Unguessable. The random part has to come from a cryptographically secure random generator and carry at least 128 bits of entropy. The hex and base64url options carry 256 bits, and the 32-character base62 secret in the prefixed format about 190 (32 × log2 62). A UUID v4 has 122 random bits, a little under that bar, which is why UUIDs make better IDs than secrets.
  • Shown once. You show the full key when it's created and store only a hash. If someone reads your database, they get hashes, not working keys.
  • Revocable. Each key needs its own record, so you can revoke one key without touching a customer's other keys.
  • Recognizable (nice to have). A prefix tells your customer, your support team and secret scanners whose key it is and which environment it belongs to.
  • Self-checking (nice to have). A checksum lets your server reject a mistyped or made-up key without a database lookup.

API key format, explained

The prefixed format this generator uses looks like this:

text
acme_live_k7Gx2PqAHn3Lq8WvZr2Tb6Yd1Kx9Pe4Ms7Jc0Uf50Ysd8S
PartIn the exampleWhat it's for
PrefixacmeYour product. 2 to 10 lowercase letters or digits. Makes leaked keys easy to attribute and easy to scan for.
Environmentlivelive or test, so nobody ships a test key to production without noticing.
Key IDk7Gx2PqA8 characters. Stored in plain text and used to find the key's record, so the server never has to compare against every hash.
SecretHn3Lq8Wv…Jc0Uf532 random base62 characters, about 190 bits. This is the part that must stay secret.
Checksum0Ysd8S6 characters: the CRC32 of everything before it, encoded in base62 and padded with zeros.

The underscores matter too. They aren't base62 characters, so the parts never run together, and because underscores count as part of a word, double-clicking the key usually selects all of it.

The checksum is not a security feature: anyone can compute a CRC32. It stops honest mistakes and random noise. A key with one wrong character fails the check, so your server can answer 401 straight away instead of hitting the database, and a secret scanner can ignore strings that only look like keys. Try it in the checker above: paste a generated key, change one character, and the checksum no longer matches.

API key examples from well-known APIs

The same ideas show up in the keys you already use.

  • GitHub moved to prefixed tokens in April 2021: ghp_ for personal access tokens, gho_ for OAuth tokens, ghs_ for server-to-server tokens, and a few more. The last 6 characters are a CRC32 checksum encoded in base62, padded with leading zeros. GitHub said the prefixes alone would bring secret scanning's false positive rate down to 0.5%, and that the checksum lets it reject fake tokens offline.
  • Stripe puts the key type and the mode in the prefix: sk_live_ and sk_test_ for secret keys, rk_live_ for restricted keys, pk_live_ for publishable keys that are safe to put in front-end code. If you create a live secret key yourself, Stripe shows it once and can't reveal it again.

Both prefixes tell you at a glance who issued a token and what kind it is, and Stripe's also say whether it's live or test. A product prefix plus an environment label gives your own API keys the same property.

How to store and check API keys

  1. Generate the key on your server when the customer asks for one, using a secure random source.
  2. Show the full key once, with a copy button and a clear note that it won't be shown again.
  3. Store the key ID, a SHA-256 hash of the full key, the customer it belongs to, its status and an optional expiry date. Don't store the key itself, and keep it out of logs and error reports.
  4. On each request: check the format and checksum first, look up the record by key ID, compare hashes in constant time, then check status and expiry.
  5. To rotate, issue a new key and give the old one an expiry date a day or two out, so the customer can switch without downtime.

A fast hash like SHA-256 is fine here. Slow password hashes such as bcrypt exist because people choose guessable passwords. A key with 190 random bits can't be brute-forced however fast the hash is.

If you'd rather not build this part, UsageRail gives your customers a portal where they create, rotate and revoke keys in this format, and its SDK checks them inside your API process. The rate limiting guide covers what to do once a request has a valid key.

Generate an API key in code

Node.js, 32 random bytes as base64url:

js
import { randomBytes } from "node:crypto";

const apiKey = randomBytes(32).toString("base64url");

Python, the same thing with the standard library:

python
import secrets

api_key = secrets.token_urlsafe(32)

Both give you 256 bits of randomness. Add your own prefix in front (for example acme_live_) if you want keys people can recognize.

Is it safe to generate API keys in a browser?

Yes, as long as the page uses the browser's cryptographic random generator. This one calls crypto.getRandomValues (and crypto.randomUUID for UUIDs), which browsers back with the operating system's secure random source. The keys are created on your device and never sent to us; you can disconnect from the internet and the generator keeps working.

For keys your customers will use in production, though, generate them on your server at the moment a customer asks for one. That way the key exists in exactly one place before you hash it, and you never have to paste it anywhere.