Skip to content

Use Anthropic ratelimit headers as primary Claude scrape (Clawdmeter method)#39

Merged
BlockedPath merged 2 commits into
mainfrom
feat/claude-oauth-headers-scrape
May 25, 2026
Merged

Use Anthropic ratelimit headers as primary Claude scrape (Clawdmeter method)#39
BlockedPath merged 2 commits into
mainfrom
feat/claude-oauth-headers-scrape

Conversation

@BlockedPath

Copy link
Copy Markdown
Owner

Summary

Ported the cleaner scrape approach from the Clawdmeter repo that CodexMeter forked from. Instead of decrypting browser cookies and hitting claude.ai/api/.../usage, the new primary script POSTs a 1-token Haiku probe to the documented api.anthropic.com/v1/messages endpoint with the OAuth bearer Claude Code already keeps in the macOS Keychain, then reads the rate-limit headers Anthropic returns on every response:

  • anthropic-ratelimit-unified-5h-utilization (0.0–1.0 float)
  • anthropic-ratelimit-unified-5h-reset (epoch seconds)
  • anthropic-ratelimit-unified-7d-utilization
  • anthropic-ratelimit-unified-7d-reset

Why this is better

Cookie scrapes OAuth headers
Browser dependency Claude Desktop or Firefox signed in none
Cloudflare in the loop yes no
Endpoint undocumented claude.ai/api/.../usage documented /v1/messages
Failure surface cookie rotation, Safe Storage Keychain OAuth refresh handled by Claude Code
Cost per scrape $0 ~$0.0001 (1 Haiku token)

Changes

  • New scripts/claude-plan-usage-oauth-headers.py (the new primary). Falls through to the existing claude-plan-usage-desktop.py on any failure, which itself falls through to the Firefox script. Three-layer scrape chain.
  • LaunchAgent + install.sh point at the headers script as primary.
  • local_claude_activity_snapshot reorders to prefer the fresh plan-usage cache over the statusline hook. The hook lags reality because it only refreshes when Claude Code itself makes an API call — so a fresh-mtime hook file can still describe utilization from minutes ago.
  • Tests stub CLAUDE_LIMITS_FILE so they don't leak the developer's real ~/.claude/plan-limits.json state.
  • CLAUDE.md runbook updated with the new priority order and credit to Clawdmeter.

Test plan

  • pytest -q (11 passed)
  • ruff check daemon/ scripts/ tests/ clean
  • LaunchAgent reloaded, daemon serving fresh oauth-headers data: /health.scrape.source = "oauth_headers", /usage reports 5h 38% used · 7d 13% used matching what claude.ai shows
  • Fallback path: if --no-fallback is omitted, failures spawn claude-plan-usage-desktop.py automatically

🤖 Generated with Claude Code

…method)

The cookie-based scrapes work but depend on Claude Desktop or Firefox
staying signed in to claude.ai. Hermann Bjorgvin's Clawdmeter (which
Codexmeter forked from) ships a cleaner approach: hit the documented
/v1/messages endpoint with the OAuth bearer Claude Code already keeps
in the macOS Keychain, ignore the response body, and parse the
anthropic-ratelimit-unified-{5h,7d}-{utilization,reset} headers
Anthropic returns on every request. No browser, no Cloudflare wall,
no page-layout fragility.

- New scripts/claude-plan-usage-oauth-headers.py reads the OAuth token
  from `Claude Code-credentials` Keychain entry (or ~/.claude/.credentials.json
  on Linux), POSTs a 1-token Haiku probe to api.anthropic.com, and
  normalizes the rate-limit headers into the same plan-usage cache
  shape the daemon already consumes. Falls through to the desktop
  cookie script on any failure.
- LaunchAgent + install.sh switched to the headers script as primary.
  The cookie scrapers remain as fallbacks.
- local_claude_activity_snapshot reorders to prefer the fresh
  plan-usage cache over the statusline hook — the hook only updates
  when Claude Code itself makes an inference call, which can be
  minutes stale even when its file mtime is fresh.
- Tests now also stub CLAUDE_LIMITS_FILE so they don't read the real
  hook file from ~/.claude.
- CLAUDE.md runbook updated to describe the new priority order and
  credit Clawdmeter.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32e7c1d1b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/claude-plan-usage-oauth-headers.py Outdated
try_fallback() was invoking claude-plan-usage-desktop.py with no args,
which made the desktop script default to 'scrape' and overwrite
~/.config/codexmeter/claude-plan-usage.json whenever the OAuth path
failed — even when the user ran the oauth-headers script as 'print'
for troubleshooting. Forward the command verbatim so 'print' remains
non-mutating end-to-end.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@BlockedPath
BlockedPath merged commit 3da2faa into main May 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant