If you pay for Claude Pro or Max and also script things against Claude from your own code, you might be double-paying. Anthropic keeps subscription billing and API credits as completely separate accounts — and the regular anthropic SDK only knows about the API one. But there's an officially-supported path that lets the Claude Agent SDK bill against your subscription instead. Here's how it works in Python and TypeScript.
A small companion repo with the full setup, both languages side by side, and worked examples:
👉 github.com/avivshaked/prototype-with-claude-max
Here's the mental model.
The two-token mental model
Anthropic keeps two separate billing relationships:
| Auth | What it is | Where you pay |
|---|---|---|
ANTHROPIC_API_KEY |
Console API key | Pay-as-you-go API credits |
CLAUDE_CODE_OAUTH_TOKEN |
OAuth token from claude setup-token
|
Your Pro/Max subscription |
The regular anthropic SDK only knows about the first one. The Agent SDK (claude-agent-sdk for Python, @anthropic-ai/claude-agent-sdk for TypeScript) wraps the Claude Code CLI, which natively understands both — and on the OAuth path, every call lands on your subscription quota.
The hello-world
Generate the token:
npm install -g @anthropic-ai/claude-code
claude setup-token # opens a browser, returns a 1-year token
Drop it into .env:
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...
Then in Python:
import asyncio, os, sys
from dotenv import load_dotenv
load_dotenv()
if os.environ.get("ANTHROPIC_API_KEY"):
sys.exit("ANTHROPIC_API_KEY is set — it would shadow your OAuth token. unset it.")
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
async def main():
async for msg in query(
prompt="Say hello in one short sentence.",
options=ClaudeAgentOptions(allowed_tools=[]),
):
if isinstance(msg, AssistantMessage):
for block in msg.content:
if isinstance(block, TextBlock):
print(block.text)
asyncio.run(main())
That's it. Bills against your Max subscription, not API credits. The repo has the same thing in TypeScript, plus a WebSearch + token-by-token streaming example.
The gotcha worth knowing about
Auth precedence on the SDK is:
- cloud creds → 2.
ANTHROPIC_AUTH_TOKEN→ 3.ANTHROPIC_API_KEY→ 4.apiKeyHelper→ 5.CLAUDE_CODE_OAUTH_TOKEN→ 6. interactive/login
If you have ANTHROPIC_API_KEY exported from another project (and you almost certainly do), it silently wins over your OAuth token. You'll be billing API credits while thinking you're using your subscription.
unset ANTHROPIC_API_KEY
The repo includes a check_auth.py / check-auth.ts script that tells you exactly which auth method is winning, so you can diagnose instead of guessing.
⚠️ Personal use only
This works because the OAuth token is licensed for individual use through Claude Code and the Agent SDK. Do not ship a multi-user app on it:
- You'd run everyone's traffic through one person's quota — you'd hit rate limits in seconds at any real load.
- It likely violates Anthropic's terms. Pro/Max plans are for individual use, and as of April 2026 Anthropic actively blocks third-party harnesses that try to bridge subscription auth into other tools.
- A leaked token = anyone can drain your subscription until you rotate it.
For production, you swap the auth method, not the SDK — the Agent SDK itself is production-grade. Point at ANTHROPIC_API_KEY from console.anthropic.com and you're good.
The repo
Top-level README with the full story, plus per-language READMEs for Python and TypeScript with setup instructions, three worked examples each (hello, check_auth, news with streaming + WebSearch), and a troubleshooting table.
Repo: avivshaked/prototype-with-claude-max
If you've been double-paying for Anthropic, this fixes it for personal scripts in about 5 minutes.
Top comments (0)