How It Works
Overview
Section titled “Overview”SaltyKeys.js works in two phases:
- Key generation — done once, offline, by you in the browser console
- Key retrieval — done at runtime in your pen, by anyone who loads it
The core idea is context-binding: the salted key is tied to the CodePen pen ID, so it can only be decoded successfully when the pen ID matches.
Phase 1 — Key generation
Section titled “Phase 1 — Key generation”When you call generateSaltedKey('my-api-key'), SaltyKeys:
- Calls
getPenId()to read the current pen’s ID from the URL (e.g.XWbpNvY) - Builds a compound string:
— where"my-api-key:XWbpNvY:1746000000000:a1b2c3d4"
1746000000000is the current timestamp anda1b2c3d4is a random nonce - Unicode-safe Base64 encodes the compound string (
btoa+encodeURIComponent) - Reverses the resulting string character by character
The output is a string that looks like scrambled Base64. This becomes your salted key.
Phase 2 — Key retrieval
Section titled “Phase 2 — Key retrieval”When your pen’s code calls getApiKey(saltedKey), SaltyKeys:
- Calls
getPenId()to read the current pen’s ID - Reverses the salted key string
- Base64 decodes it (
atob+decodeURIComponent) - Splits on
":"to get[apiKey, penId, timestamp, nonce] - Compares the decoded
penIdto the current pen’s ID - Returns the
apiKeyonly if they match; otherwise returnsnull
The pen ID check
Section titled “The pen ID check”The pen ID comparison is the mechanism that prevents casual key extraction:
Salted key generated in pen "AbCdEf" ↓Loaded in pen "AbCdEf" → PEN ID MATCHES → returns original API key ✓Loaded in pen "XyZ123" → PEN ID MISMATCH → returns null ✗If someone copies your salted key and pastes it into a different pen, getApiKey() returns null and the API key is never exposed.
URL extraction and the iframe fallback
Section titled “URL extraction and the iframe fallback”getPenId() uses a two-step strategy:
- Direct URL — tests
window.location.hrefagainst the configured regex - Canonical link — if the direct match fails (as happens in embedded iframe views), reads the
hrefof<link rel="canonical">and tests that instead
CodePen serves content from two domains: codepen.io (editor and full-page views) and cdpn.io (short URLs and embeds). The default urlPattern covers both.
Obfuscation layers
Section titled “Obfuscation layers”| Layer | Technique | Purpose |
|---|---|---|
| 1 | Compound string with colon delimiters | Embeds pen ID, timestamp, nonce |
| 2 | Unicode-safe Base64 (btoa after encodeURIComponent) | Obscures the raw string from casual inspection |
| 3 | String reversal | Makes the Base64 look non-standard at a glance |
Caching
Section titled “Caching”After the first successful call to getPenId(), the result is stored in a private class field (#cachedPenId). Subsequent calls skip the URL/DOM lookup and return the cached value directly. This is controlled by SaltyKeys.config.cacheEnabled.
Unicode safety
Section titled “Unicode safety”The built-in helpers _safeEncode and _safeDecode wrap btoa/atob with encodeURIComponent/decodeURIComponent to handle characters outside the Latin-1 range. API keys and pen IDs are typically ASCII, but the safeguard is there.