Route your OpenClaw API requests through your Claude Max/Pro subscription instead of Extra Usage billing.
After Anthropic revoked subscription billing for third-party tools (April 4, 2026), OpenClaw requests are billed to Extra Usage. This proxy sits between OpenClaw and the Anthropic API, injecting Claude Code's billing identifier so requests use your existing subscription.
Zero cost increase. Full OpenClaw functionality. No code changes to OpenClaw.
The proxy performs bidirectional request/response processing:
Outbound (request to API):
- Billing Header -- Injects an 84-character Claude Code billing identifier into the system prompt
- Token Swap -- Replaces OpenClaw's auth token with your Claude Code OAuth token
- Sanitization -- Replaces trigger phrases that Anthropic's streaming classifier detects (8 default patterns)
Inbound (response to OpenClaw): 4. Reverse Mapping -- Restores original tool names, file paths, and identifiers so OpenClaw sees its real terms
This ensures Anthropic sees a "Claude Code" request while OpenClaw sees its original tool names and paths.
- Node.js 18+
- Claude Max or Pro subscription
- Claude Code CLI installed and authenticated
- OpenClaw installed and running
npm install -g @anthropic-ai/claude-codeThen authenticate with your Claude account:
claude auth loginThis opens a browser window to sign in with your Claude Max/Pro account. Once authenticated, credentials are stored at ~/.claude/.credentials.json. The proxy reads from this file.
Verify it worked:
claude auth status
# Should show: loggedIn: true, subscriptionType: max (or pro)# 1. Clone
git clone https://github.com/zacdcook/openclaw-billing-proxy
cd openclaw-billing-proxy
# 2. Run setup (auto-detects your config)
node setup.js
# 3. Start the proxy
node proxy.js
# 4. Update OpenClaw config
# In ~/.openclaw/openclaw.json, change:
# "baseUrl": "https://api.anthropic.com"
# to:
# "baseUrl": "http://127.0.0.1:18801"
# 5. Restart your OpenClaw gatewayThe config.json file (generated by setup or created manually):
{
"port": 18801,
"credentialsPath": "~/.claude/.credentials.json",
"replacements": [
["OpenClaw", "OCPlatform"],
["openclaw", "ocplatform"],
["sessions_spawn", "create_task"],
["sessions_list", "list_tasks"],
["sessions_history", "get_history"],
["sessions_send", "send_to_task"],
["sessions_yield", "yield_task"],
["running inside", "running on"]
],
"reverseMap": [
["OCPlatform", "OpenClaw"],
["ocplatform", "openclaw"],
["create_task", "sessions_spawn"],
["list_tasks", "sessions_list"],
["get_history", "sessions_history"],
["send_to_task", "sessions_send"],
["yield_task", "sessions_yield"]
]
}replacements -- Applied to outbound requests. Each [find, replace] pair does a raw string replacement on the request body before forwarding to the API.
reverseMap -- Applied to inbound responses. Each [sanitized, original] pair restores terms back to their original form before returning to OpenClaw. This ensures tool names, file paths, and identifiers work correctly.
Important: Use space-free replacements for lowercase openclaw. Replacing .openclaw/ with .assistant platform/ (with a space) breaks filesystem paths in tool calls. Use ocplatform or similar instead.
If your OpenClaw version has additional sessions_* tools (they add new ones across versions), add them to both replacements and reverseMap:
{
"replacements": [
["sessions_new_tool", "new_task_tool"]
],
"reverseMap": [
["new_task_tool", "sessions_new_tool"]
]
}If you have a custom assistant name that Anthropic blocks (test by checking if requests fail with the name present but pass without it), add it the same way.
sudo tee /etc/systemd/system/openclaw-proxy.service << EOF
[Unit]
Description=OpenClaw Billing Proxy
After=network.target
[Service]
ExecStart=/usr/bin/node /path/to/proxy.js
Restart=always
User=YOUR_USER
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable openclaw-proxy
sudo systemctl start openclaw-proxyAdd to your gateway.cmd before the gateway launch:
start "Billing Proxy" /min node "C:\path\to\proxy.js"
timeout /t 2 /nobreak >nulpm2 start proxy.js --name openclaw-proxy
pm2 saveClaude Code's OAuth token expires every ~24 hours. The proxy reads the token fresh from disk on each request. To refresh:
- Easiest: Open Claude Code CLI briefly -- it auto-refreshes on startup
- Automated: Set up a cron that runs
claude -p "ping" --max-turns 1 --no-session-persistencedaily (triggers auth refresh)
curl http://127.0.0.1:18801/healthReturns token status, request count, uptime, subscription type, and pattern counts.
Anthropic uses two mechanisms to detect third-party tools:
-
Billing Header -- The API checks the system prompt for
x-anthropic-billing-header. Without it, OAuth requests go to Extra Usage. This is a simple string match on 84 characters injected by Claude Code's SDK. -
Streaming Classifier -- Anthropic's classifier scans the request for specific trigger phrases. The verified triggers are:
OpenClaw(the platform name -- case insensitive)sessions_spawn,sessions_list,sessions_history,sessions_send,sessions_yield,sessions_yield_interrupt,sessions_store(OpenClaw session management tools -- new tools are added across versions)HEARTBEAT_OK(OpenClaw heartbeat ack identifier injected in system prompt)running inside+ platform name (the self-declaration phrase OpenClaw injects)
If detected, the response is refused with
stop_reason: "refusal"or a billing error.
What is NOT detected: Assistant names, workspace filenames (AGENTS.md, SOUL.md), config paths (.openclaw/), plugin names (lossless-claw), individual non-session tool names (exec, lcm_grep, gateway, cron, etc.), bot names, or runtime references. Only the patterns above trigger rejection.
Without reverse mapping, the model sees sanitized paths in its context (e.g., .ocplatform/workspace/scripts/) and uses them for tool calls. But the actual filesystem has .openclaw/. The reverse mapping translates API responses back to original terms before OpenClaw processes them, ensuring:
- Tool names match OpenClaw's tool registry
- File paths match the actual filesystem
- Session management commands use correct identifiers
Run the diagnostic script to identify issues:
node troubleshoot.jsThis tests 8 layers independently (credentials, token, API, billing header, trigger detection, proxy health, end-to-end) and tells you exactly what to fix.
"Could not find credentials file"
- Run
claude auth loginto authenticate (opens browser) - On Mac, the file may be at
~/.claude/credentials.json(no dot prefix) -- the proxy checks both - If the file exists but is empty (0 bytes), run
claude auth logout && claude auth login - If still empty on Mac, run
claude -p "test" --max-turns 1to force a credential write to disk
Proxy returns 400
- The API is rejecting the request due to unsanitized trigger terms
- Your OpenClaw version may have
sessions_*tools not in the default list - Run
node setup.jsto auto-detect your tools, or manually add patterns toconfig.json - Check the proxy console output for the error message
"Third-party apps now draw from your extra usage"
- Same cause as 400 -- trigger terms not fully sanitized
- Disable Extra Usage in your Claude settings to verify subscription billing
- If it was working and stopped, new trigger terms may have appeared in your conversation history -- restart the OpenClaw gateway to clear the session
429 Rate Limit
- Normal if you have active Claude Code sessions sharing the rate bucket
- Wait a few minutes and try again
- Not a proxy issue
Token Expired
- Open Claude Code CLI briefly -- it auto-refreshes on startup
- Or run:
claude -p "ping" --max-turns 1 --no-session-persistence
Tool execution fails / wrong file paths
- If the model references
.ocplatform/instead of.openclaw/, yourreverseMapis missing entries - Ensure every
replacementsentry has a matchingreverseMapentry - Use space-free replacements (e.g.,
ocplatform, NOTassistant platform) to avoid breaking filesystem paths
Empty credentials file on Mac
- Some Claude Code versions store tokens in macOS Keychain instead of a file
- Run
claude -p "test" --max-turns 1to force credential write - Check Keychain:
security find-generic-password -s "claude" -w 2>/dev/null
Change baseUrl back to https://api.anthropic.com in openclaw.json and restart the gateway. Enable Extra Usage in your Claude settings if needed.
This is an unofficial workaround. Anthropic may change their detection at any time. Use at your own risk. This proxy does not modify OpenClaw or Claude Code -- it's a transparent HTTP middleman.
MIT