Javid
·14 min read

API Key Example: Real Formats, Safe Sample Keys, and Detection Regex

SelfDevKit secret generator showing generated API key examples with prefixes

Most people searching for an API key example want one of two things: to confirm that the string they are staring at is really a key, or to find a sample key they can drop into a README, a test fixture, or a config file without causing a security incident. This guide covers both. Real formats from Stripe, GitHub, AWS, and Google, the regex that matches each one, the official placeholder keys those providers publish, and how to fabricate your own convincing fake without getting your push blocked.

There is a third problem nobody warns you about. A realistic example key in a committed file can trip secret scanners, and a real key in a public repo can get auto-revoked within minutes. We cover that too.

What is an API key example?

An API key example is a sample credential string formatted the way a specific provider issues its keys, typically a short type prefix followed by 20 to 40 random characters. Documentation examples such as AWS's AKIAIOSFODNN7EXAMPLE are deliberately non-functional placeholders, so they illustrate the format without granting access to anything.

Table of contents

What an API key example actually looks like

A typical API key example looks like sk_test_BQokikJOvBiI2HlWgH4olfQ2: a short prefix that names the key type, a separator, then a long block of random characters. Break that string into its parts and every modern key follows the same three-piece anatomy.

sk_test_BQokikJOvBiI2HlWgH4olfQ2
│  │    │
│  │    └── random body: 24 characters of CSPRNG output
│  └─────── environment: test mode, not live
└────────── type: secret key (not publishable)

The prefix is the part developers underestimate. It is metadata, and it is machine-readable. A scanner seeing sk_live_ knows immediately which vendor to notify, which is exactly why providers added prefixes in the first place. If you want the full background on why keys are structured this way and how servers validate them, our guide on what an API key is covers the lifecycle end to end.

The random body is the actual secret. Everything else is a label.

API key examples from real providers

Here are the formats you will meet most often, with the length and the regex that matches each one. The example strings below are fabricated except where noted, so they will not authenticate against anything.

Provider Example key Total length Detection regex
Stripe (secret) sk_test_BQokikJOvBiI2HlWgH4olfQ2 32 sk_(test|live)_[0-9a-zA-Z]{24}
Stripe (publishable) pk_test_TYooMQauvdEDq54NiTphI7jx 32 pk_(test|live)_[0-9a-zA-Z]{24}
GitHub (classic PAT) ghp_QDVhNb9Kx2tRj7pLmA4sYzE6wU0fCvT3iOgH 40 ghp_[A-Za-z0-9]{36}
AWS (access key ID) AKIAIOSFODNN7EXAMPLE 20 AKIA[0-9A-Z]{16}
Google Cloud AIzaSyB1Qk9v7hTn3xJ2mPd8LrW4cZ6aF0sY5uE 39 AIza[0-9A-Za-z\-_]{35}
OpenAI (project key) sk-proj-9xQv2LkR7mTn4wYb8ZcH3aFdG6sJ1uPe varies sk-proj-[A-Za-z0-9_-]{20,}

A few things worth noticing. Stripe's secret and publishable keys are the same length and differ by two characters, which is why shipping the wrong one to the browser is such a common mistake. AWS splits the credential in two: the access key ID above is only half of it, paired with a 40-character secret access key that never appears in a URL or a header directly.

Google's format is the tidiest to match. Four fixed characters, 35 variable ones, always 39 total. That single regex is what TruffleHog and similar scanners use, and the Google Cloud API key documentation describes the key as an encrypted string tied to a project for quota and billing.

The unprefixed API key example

Plenty of smaller APIs skip prefixes entirely and issue a bare UUID:

1f9ba190-c513-471b-a573-b8d008bb52fe

Entropy-wise this is fine. A version 4 UUID carries 122 random bits, comfortably beyond brute force. The problem is detectability. A prefixless key is indistinguishable from a database primary key, a session ID, or a correlation ID, so no scanner can flag it when it leaks, and no provider can auto-revoke it. If you are issuing keys yourself and you like the UUID shape, prefix it anyway: myapp_sk_1f9ba190-c513-471b-a573-b8d008bb52fe costs you nothing and buys you detection. Our UUID generator guide covers the version differences if you need to pick one, and SelfDevKit's ID generator produces them offline.

The checksum hiding inside a GitHub key

A GitHub token is not just random characters after the prefix. The last six characters are a base62-encoded CRC32 checksum of the rest, which means most hand-typed fake tokens are structurally invalid.

GitHub's engineering team documented the format when they moved to prefixed tokens. Their words:

"A 32 bit checksum in the last 6 digits of each token strikes the optimal balance between keeping the random token portion at a consistent entropy and enough confidence in the checksum. We start the implementation with a CRC32 algorithm, a standard checksum algorithm. We then encode the result with a Base62 implementation, using leading zeros for padding as needed."

So a 40-character token decomposes like this:

ghp_QDVhNb9Kx2tRj7pLmA4sYzE6wU0fCvT3iOgH
│    │                              │
│    │                              └── 6 chars: base62 CRC32 checksum
│    └───────────────────────────────── 30 chars: random body
└────────────────────────────────────── 4 chars: prefix + separator

The prefixes are a family: ghp_ for personal access tokens, gho_ for OAuth tokens, ghu_ for user-to-server, ghs_ for server-to-server, and ghr_ for refresh tokens. GitHub reported that the prefix alone was expected to drop secret scanning false positives to 0.5 percent, and that the checksum "virtually eliminates false positives for secret scanning offline."

Here is the practical consequence, and it cuts both ways. A ghp_ string you invented for a blog post almost certainly fails the checksum, so it is safe to publish. A real leaked token passes it, so it is detected instantly and offline, without anyone needing to call GitHub's API to test it.

Safe sample keys you can paste into docs

The safest example API key is one the provider has published as a deliberate placeholder, because scanners already allowlist it. Two are worth memorizing.

AWS. The IAM access keys documentation states plainly:

"Access keys consist of two parts: an access key ID (for example, AKIAIOSFODNN7EXAMPLE) and a secret access key (for example, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY)."

Both strings contain the literal word EXAMPLE, which is not an accident. Gitleaks, GitGuardian, and friends match on that marker, so these values pass through pre-commit hooks without a fight.

Stripe. The Stripe API authentication docs note: "A sample test API key is included in all the examples here, so you can test any example right away. Do not submit any personally identifiable information in requests made with this key." Stripe's test-mode keys start with sk_test_ and only touch sandbox data, while live mode uses sk_live_ for full access and rk_live_ for restricted keys scoped to specific permissions.

For everything else, use a placeholder that could never be mistaken for a credential:

# Good: obviously a placeholder
curl https://api.example.com/v1/users \
  -H "x-api-key: YOUR_API_KEY"

# Also fine
API_KEY=<your-api-key>
API_KEY=your_api_key_here

# Risky: looks real, high entropy, scanners will flag it
API_KEY=k3Jd9Xq2LmR7wYb4ZcH8aFdG6sJ1uPeT

The x-api-key header shown above is the most common way to transmit a key, and it has its own quirks around casing and gateway errors. Our x-api-key header guide goes through them.

How to generate a fake API key for tests

To generate a realistic fake API key, produce 24 to 32 bytes from a cryptographically secure random source, encode them as base64url or hex, and prepend a prefix that matches the format you are imitating. Do not use Math.random() or a timestamp, even for fixtures.

That last point sounds paranoid for test data. It is not. Fixture keys have a habit of getting copied into a staging config, then into production, and a key derived from a predictable source is guessable forever. Generating fixtures with the same rigor as real keys costs one line of code.

Node.js

import { randomBytes } from 'crypto';

const fakeStripeKey = () => `sk_test_${randomBytes(18).toString('base64url')}`;
const fakeGithubToken = () => `ghp_${randomBytes(27).toString('base64url')}`;

Python

import secrets

def fake_api_key(prefix: str = "live_", nbytes: int = 32) -> str:
    return f"{prefix}{secrets.token_urlsafe(nbytes)}"

Go

import (
    "crypto/rand"
    "encoding/base64"
)

func fakeAPIKey(prefix string) string {
    b := make([]byte, 24)
    rand.Read(b)
    return prefix + base64.RawURLEncoding.EncodeToString(b)
}

Shell

echo "live_$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-48)"

If you would rather not write throwaway scripts, SelfDevKit's secret generator produces these locally. The API Key preset outputs three 48-character alphanumeric keys with a live_ prefix at a time, and there are presets for webhook secrets (whsec_ plus 64 hex characters), OAuth client secrets, 256-bit encryption keys, and database passwords.

SelfDevKit secret generator producing API key examples, webhook secrets, and encryption keys

Everything is generated on your machine with no network call, which matters more than it sounds. Pasting "generate an API key" into a web tool means a server you do not control has seen a string you are about to trust with production access. For signing secrets specifically, our JWT secret key generator guide explains why key length has to match the algorithm, and the password generator guide breaks down how character count translates into real entropy.

Where the example key goes in your project

Example keys belong in files that are committed; real keys belong in files that are not. The cleanest pattern is a committed .env.example that documents every variable with a placeholder, alongside a git-ignored .env that holds the real values.

# .env.example  (committed to git)
STRIPE_SECRET_KEY=sk_test_your_key_here
OPENAI_API_KEY=sk-proj-your_key_here
INTERNAL_API_KEY=your_api_key_here
# .env  (listed in .gitignore, never committed)
STRIPE_SECRET_KEY=sk_test_BQokikJOvBiI2HlWgH4olfQ2

In CI, the example never appears at all. The value comes from the platform's secret store:

# .github/workflows/deploy.yml
- name: Run integration tests
  env:
    API_KEY: ${{ secrets.API_KEY }}
  run: npm test

And in an OpenAPI spec, the placeholder belongs in an example field, never in a default that a code generator might bake into the client it emits:

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
  schemas:
    ApiCredentials:
      type: object
      properties:
        apiKey:
          type: string
          example: sk_test_your_key_here # rendered in docs only

One gotcha that costs people an afternoon: reading a key from a file with $(cat key.txt) keeps the trailing newline, which the server sees as part of the credential and rejects. If a key that looks correct keeps returning 401, paste it into a text inspector and check the character count against the expected length in the table above. Thirty-three characters where thirty-two are expected is a newline.

Why a realistic example key can break your build

A convincing fake key committed to a repository can trigger secret scanning push protection and block your push outright. This is the failure mode nobody mentions when they tell you to use "realistic test data."

GitHub's secret scanning runs automatically and for free on public repositories, checking the entire Git history on every branch for known credential patterns. Push protection takes it a step further and rejects the push before the secret ever lands. It only runs patterns the scanner can identify with high confidence, which is precisely why the GitHub checksum and the Stripe prefix exist.

The other direction is worse. When a real partner secret is detected, GitHub's docs state: "When a partner secret is detected, we notify the provider so they can take action, such as revoking the credential." Push a live OpenAI or Stripe key to a public repo and it can be dead before you finish reading the alert email. That is the system working correctly, but it does mean a copy-paste accident becomes a production outage.

If your repo legitimately needs realistic-looking keys in fixtures, allowlist the paths rather than weakening the scan:

# .gitleaks.toml
[allowlist]
description = "Documentation examples and test fixtures"
paths = [
  '''\.env\.example$''',
  '''docs/examples/.*''',
  '''tests/fixtures/.*''',
]
regexes = [
  '''AKIAIOSFODNN7EXAMPLE''',
  '''your_api_key_here''',
]

Scoping the exception to specific paths keeps the rest of the codebase protected. Disabling the rule globally because one fixture file is noisy is how real keys slip through six months later.

Finding API keys in your codebase with regex

To audit a codebase for hardcoded keys, run the provider regex patterns against your source tree, then filter by entropy to catch the unprefixed ones. Start with a combined alternation:

(sk|pk|rk)_(test|live)_[0-9a-zA-Z]{24}|gh[pousr]_[A-Za-z0-9]{36}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z\-_]{35}

Dropped into grep -rEn or a scanner config, this catches the four highest-value formats in one pass. Prefixed keys are the easy half of the job.

The hard half is everything else. A bare 32-character hex string could be an API key, a session token, a commit SHA, or a checksum, and no pattern distinguishes them reliably. That is where entropy heuristics come in, and where false positives multiply. Build the pattern incrementally against real samples rather than trusting a regex you copied from a gist.

SelfDevKit regex validator testing an API key detection pattern with live match highlighting

SelfDevKit's regex validator highlights matches as you type, so you can paste a handful of real and fake keys and watch which ones the pattern catches before you commit it to a CI job. Our guide to testing regex covers building a proper test corpus of positive and negative cases, which matters a lot here: a detection pattern that misses one key format is worse than no pattern, because it creates false confidence.

If you already store keys server-side, hash them before comparison so a database dump does not hand over working credentials. A plain SHA-256 is appropriate here because keys are high-entropy by construction, unlike passwords. Our SHA-256 generator guide walks through the details, and the hash generator computes digests locally.

Frequently asked questions

Are the API key examples in documentation real?

No. Values like AKIAIOSFODNN7EXAMPLE and Stripe's documented sample test key are deliberate placeholders that never authenticate against a real account. Stripe's sample test key does reach their sandbox, so treat it as functional-but-harmless rather than fully inert, and never send real data through it.

Can I invent my own API key example for a blog post or README?

Yes, and it is usually the better option. Use an obvious placeholder like YOUR_API_KEY where the format does not matter, and generate a random string with a matching prefix where it does. Avoid strings that look like a valid credential in a committed file unless you have allowlisted the path in your secret scanner.

What is the difference between a test API key and a live API key?

The prefix, and the data behind it. Test keys such as sk_test_ hit a sandbox where nothing is billed and no real records change; live keys such as sk_live_ operate on production. Both share the same length and character set, so a mismatch is easy to make and easy to miss. Keep them in separate environment files.

How can I tell whether a random string is an API key?

Check the prefix first against the table above, then the length. AIza plus 35 characters is a Google key; AKIA plus 16 is an AWS access key ID; ghp_ plus 36 is a GitHub token. If there is no prefix, look at what surrounds it. A high-entropy string assigned to a variable named token, key, or secret should be treated as live until proven otherwise.

Try it yourself

Whether you need a placeholder for a README or a real credential for production, the generation step should never involve a website you do not control. SelfDevKit's secret generator creates API keys, webhook secrets, JWT signing secrets, and encryption keys entirely offline, with prefixes that match the conventions above.

Download SelfDevKit for 50+ developer tools that run on your machine, not someone else's server.

Related Articles

What Is an API Key? How They Work, Look, and Stay Secure
DEVELOPER TOOLS

What Is an API Key? How They Work, Look, and Stay Secure

What is an API key? A plain-English guide to how API keys work, what they look like, how to send them, and how to generate and store them securely.

Read →
x-api-key: The API Key Header Explained, With Code and Gotchas
DEVELOPER TOOLS

x-api-key: The API Key Header Explained, With Code and Gotchas

x-api-key is the de facto header for API key auth. How to send it, validate it, fix CORS and AWS 403 errors, and why header casing bites you.

Read →
JWT Secret Key Generator: How to Create Secure Signing Keys
DEVELOPER TOOLS

JWT Secret Key Generator: How to Create Secure Signing Keys

Learn how to generate a JWT secret key that actually meets RFC 7518 requirements, plus the format decisions developers always get wrong.

Read →