How Stripe Generates API Keys: Reverse Engineering the Pattern

Published March 9, 2026 · 9 min read

Stripe's API key format has become the de facto standard for modern APIs. The sk_live_ prefix is instantly recognizable, and dozens of companies — from OpenAI to Resend — have adopted similar patterns. But what exactly is the structure behind a Stripe key? How much entropy does it contain? And how can you implement the same pattern for your own API?

This article reverse-engineers the Stripe API key format by analyzing publicly documented keys, examining the prefix taxonomy, calculating the entropy, and providing production-ready code to generate identical-style keys.

Anatomy of a Stripe API Key

A Stripe API key consists of three parts:

sk_live_EXAMPLE_DO_NOT_USE_1234567890abcd
|__|____|____________________________________________|
type env  random portion (base62)
  1. Type prefix (sk or pk): identifies whether the key is a secret key or publishable key
  2. Environment (_live_ or _test_): identifies the Stripe environment
  3. Random portion: a cryptographically random string using base62 characters (A-Z, a-z, 0-9)

The Complete Prefix Taxonomy

Stripe uses a systematic prefix scheme that has expanded over the years:

PrefixTypeVisibilityUse Case
sk_live_Secret keyServer onlyProduction API calls
sk_test_Secret keyServer onlyTest/sandbox API calls
pk_live_Publishable keyClient safeStripe.js, mobile SDKs
pk_test_Publishable keyClient safeTest client integration
rk_live_Restricted keyServer onlyLimited-permission keys
rk_test_Restricted keyServer onlyTest restricted keys
whsec_Webhook secretServer onlyWebhook signature verification

This prefix system provides three immediate benefits:

Entropy Analysis

The random portion of a Stripe key uses base62 encoding (uppercase letters, lowercase letters, and digits). Based on publicly documented Stripe keys, the random portion is typically 24-32 characters long.

For a 24-character base62 random portion:

For a 32-character base62 random portion:

Both values exceed the 128-bit minimum for cryptographic security. At 143 bits, brute-forcing the key at one trillion guesses per second would take approximately 3.5 x 10^19 years — about 2.5 billion times the age of the universe.

Stripe's key entropy sits comfortably between AES-128 (128 bits) and AES-256 (256 bits). This is more than sufficient for API authentication, especially when combined with rate limiting and monitoring.

How Stripe Likely Generates Keys

While Stripe has not published their exact key generation code, we can infer the process based on the output format and industry best practices:

  1. Generate 24-32 bytes of random data using a CSPRNG (likely /dev/urandom or equivalent on their infrastructure)
  2. Encode the random bytes into base62 characters
  3. Prepend the appropriate prefix (sk_live_, pk_test_, etc.)
  4. Store a SHA-256 hash of the complete key in the database
  5. Display the full key to the user exactly once
  6. Register the key prefix with GitHub's secret scanning partnership program

The key is never stored in plaintext. When a user makes an API call, Stripe hashes the provided key and compares it against stored hashes.

Building Stripe-Style Keys: JavaScript

function generateStripeStyleKey(type = 'sk', env = 'live', length = 24) {
  const prefix = `${type}_${env}_`;
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  const bytes = new Uint8Array(length);
  crypto.getRandomValues(bytes);

  let random = '';
  for (let i = 0; i < length; i++) {
    random += chars[bytes[i] % chars.length];
  }

  return prefix + random;
}

// Usage
generateStripeStyleKey('sk', 'live');  // sk_live_EXAMPLE_DO_NOT_USE_1a2b
generateStripeStyleKey('pk', 'test');  // pk_test_EXAMPLE_DO_NOT_USE_3c4d
generateStripeStyleKey('rk', 'live');  // rk_live_EXAMPLE_DO_NOT_USE_5e6f

Building Stripe-Style Keys: Python

import secrets
import string

def generate_stripe_style_key(
    key_type: str = 'sk',
    env: str = 'live',
    length: int = 24
) -> str:
    prefix = f'{key_type}_{env}_'
    chars = string.ascii_letters + string.digits
    random_part = ''.join(secrets.choice(chars) for _ in range(length))
    return prefix + random_part

# Usage
print(generate_stripe_style_key())
# sk_live_EXAMPLE_DO_NOT_USE_1a2b3c

Building Stripe-Style Keys: Go

package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
)

func generateStripeStyleKey(keyType, env string, length int) string {
    prefix := fmt.Sprintf("%s_%s_", keyType, env)
    chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

    result := make([]byte, length)
    for i := range result {
        n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(chars))))
        result[i] = chars[n.Int64()]
    }

    return prefix + string(result)
}

Server-Side Key Management

Generating the key is only half the story. Here is how to manage Stripe-style keys in production:

1. Hash Before Storing

import { createHash } from 'node:crypto';

function hashKey(apiKey) {
  return createHash('sha256').update(apiKey).digest('hex');
}

// Store hashKey(fullKey) in your database
// Display fullKey to user exactly once

2. Validate Incoming Keys

async function validateApiKey(providedKey) {
  const hash = hashKey(providedKey);
  const record = await db.apiKeys.findOne({ hash });

  if (!record) return { valid: false };
  if (record.revoked) return { valid: false, reason: 'revoked' };
  if (record.expiresAt < Date.now()) return { valid: false, reason: 'expired' };

  return { valid: true, userId: record.userId, permissions: record.permissions };
}

3. Support Key Rotation

Allow multiple active keys per user so they can rotate keys without downtime. Stripe supports this by letting users create multiple keys and revoke old ones independently.

Who Else Uses This Pattern?

Stripe's prefix pattern has been widely adopted:

CompanyPrefixFormat
OpenAIsk-proj-Base62, ~48 chars random
Resendre_Base62, ~32 chars random
Clerksk_live_Base62, ~48 chars random
GitHubghp_, gho_Base62, ~36 chars random
Supabasesbp_Base62, ~40 chars random
Vercelvc_Base62, variable length

The pattern works because it is simple, self-documenting, and compatible with automated secret detection systems.

Generate Stripe-Style Keys Instantly

Try our free API key generator — select "Prefixed" format, enter your prefix (like sk_live_), and generate keys with the same structure Stripe uses. Everything runs in your browser with crypto.getRandomValues().

Recommended Resources

To build production-grade key management like Stripe, Real-World Cryptography covers the hashing, entropy, and CSPRNG concepts behind it. For securing your API against key-based attacks, The Web Application Hacker's Handbook is essential.

SPUNK LLC Network

API Sites

Key Management

More from SPUNK LLC