How to Secure Claude API Keys: A Practical Guide
Securing Claude API keys comes down to three things: keeping them out of places they can leak, limiting what each key can do if it does leak, and having a fast way to rotate or revoke them when something goes wrong. This applies whether you're calling Claude directly from Anthropic or routing through a proxy layer.
If you're here because a key ended up in a public GitHub repo, a client-side bundle, or a Slack message, the short answer is: revoke it immediately, issue a new one, audit usage logs for the leak window, and fix the underlying storage/deployment pattern so it doesn't happen again. The rest of this article covers how to build that process properly instead of doing it once in a panic.
Why Claude API keys are a real attack surface
An API key is effectively a bearer credential — whoever has it can make requests billed to your account, read whatever your system prompt or context exposes, and potentially exfiltrate data through tool calls if your integration has broad permissions. Unlike a leaked password, there's often no second factor protecting it. If it's in a request header, it works.
The common leak vectors are predictable:
- Hardcoded keys committed to version control
- Keys embedded in frontend/mobile code (visible via devtools or decompilation)
- Keys pasted into shared docs, tickets, or chat threads
- Overly broad keys shared across environments (dev, staging, prod all using the same credential)
- Long-lived keys that were never rotated after an employee left
None of these require sophisticated attacks. Most leaks are mundane mistakes that compound because there's no scoping or monitoring to catch them.
Never call Claude directly from the browser or mobile app
This is the single most important rule. If your API key is present in any client-side code — a web app, a mobile binary, a browser extension — it is public. There is no obfuscation technique that reliably hides a key from someone who opens devtools or runs strings on a binary.
The fix is architectural: put a server between your client and Claude. The client calls your backend, your backend holds the key and calls the API. This is true whether you're hitting Anthropic's API directly or a gateway service.
// Client (browser/mobile) — no key here
const res = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ message: userInput }),
});
// Your server — key lives only here, in an env var
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 1024,
messages: [{ role: "user", content: userInput }],
}),
});
Store keys in a secrets manager, not in code or .env files committed to git
Environment variables are fine at runtime, but the source of truth should be a secrets manager: AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, or even your CI/CD provider's encrypted secrets store. A few concrete practices:
- Add
.envto.gitignorebefore you add your first key, not after - Use
git-secretsor a pre-commit hook to scan for key patterns before commits go through - Rotate any key that has ever touched a public or semi-public repo, even a private one that later goes public
- Never paste keys into support tickets, Slack, or shared docs — use a secrets sharing tool with expiry if you must share one temporarily
If you're using a service like SubToAPI, keys follow the sub_live_... format, which makes them easy to pattern-match in secret-scanning tools — worth adding to your custom detection rules if your scanner doesn't already flag them.
Scope keys per environment and per application
One key for everything means one leak compromises everything. Instead:
- Issue separate keys for development, staging, and production
- Issue separate keys per application or service if you run multiple integrations (a customer support bot and an internal tool shouldn't share a credential)
- If your provider supports team seats, give each team member or service their own key rather than sharing one across a team
This makes revocation surgical. If the staging key leaks, you kill it without touching production traffic. SubToAPI's dashboard supports per-application API keys under one account, so you can scope credentials without juggling separate billing relationships — see the quickstart for how key creation works.
Rotate keys on a schedule, not just after incidents
Rotation shouldn't only happen reactively. A reasonable baseline:
- Rotate production keys every 90 days
- Rotate immediately when someone with key access leaves the team
- Rotate immediately after any suspected leak, even if you're not certain
Build rotation into your deployment process so it's not a manual, error-prone task. If your secrets manager supports automatic rotation with a Lambda or webhook, use it. If not, at minimum document the rotation steps so anyone on the team can execute them under pressure.
Monitor usage for anomalies
A leaked key often shows up in usage patterns before you notice it any other way: a spike in request volume, calls from unexpected IP ranges, or unusual token consumption at odd hours. Set up basic alerting on:
- Daily/hourly request volume thresholds
- Token usage per key
- Error rate spikes (often a sign someone is probing a stolen key)
This is one of the practical reasons to use a platform with built-in usage metadata rather than calling a raw API with no visibility layer. SubToAPI logs usage per key so you can catch anomalies without building your own logging pipeline — check /docs/messages for what's returned on each response.
Limit blast radius with least-privilege design
Beyond key storage, think about what a compromised key can actually do:
- If you use tool use or function calling, restrict tools to what the integration actually needs — don't expose a "delete record" tool to a customer-facing chatbot if it only needs "look up order status"
- Avoid putting sensitive data (customer PII, internal credentials) directly in system prompts if it can be avoided
- For streaming endpoints, make sure your server terminates connections properly rather than leaving long-lived sessions open indefinitely
None of this prevents a leak, but it limits what an attacker can extract or execute if one happens.
A minimal checklist
- Keys live only on servers, never in client code
- Keys stored in a secrets manager,
.gitignore'd, scanned for in pre-commit hooks - Separate keys per environment and per application
- Rotation on a schedule plus immediate rotation after any suspected leak
- Usage monitoring with alerts on volume and error-rate anomalies
- Least-privilege tool and data access per integration
If you want this stack ready without wiring together a secrets manager, per-key dashboards, and usage alerts yourself, SubToAPI gives you scoped sub_live_... keys, per-key usage metadata, and team seat management out of the box. Start with a free trial at /signup or see plans at /pricing.
Questions
What should I do immediately if a Claude API key leaks? Revoke or rotate the key right away, issue a new one, and check usage logs for the period it was exposed to look for unexpected requests or billing spikes.
Is it safe to put a Claude API key in a mobile app or browser extension? No. Client-side code is extractable by anyone with devtools or a decompiler. Always route requests through a server you control that holds the key.
How often should I rotate Claude API keys? A common baseline is every 90 days, plus immediate rotation whenever a team member with key access leaves or a leak is suspected.