Claude Code's Hidden Usage API

16 January 2026 #bash #claude

Related Posts

Expecting Claude Code Usage (13 Jan 2026)

In a previous project, I automated running the /usage slash command in Claude Code’s CLI using an expect script. As I discussed in that earlier post, this was actually a bad idea, since starting up a new session appears to burn some tokens every time. Running this often while working with Claude Code is a good way to quickly waste usage quota, so I decided I needed to find a different way.

Since the CLI has a built-in way of telling you how much usage you have remaining (that aforementioned /usage command), I figured there had to be some endpoint in the Anthropic API that takes your subscription’s OAuth token and returns your quota status. If we could find out what call it’s making, we could just make that call ourselves and see the response.

OAuth Token

First, we need the token. On Linux/Windows it seems like it’s stored in ~/.claude/[.]credentials.json, but I’m on macOS which uses the keychain. It’s a little trickier than just reading from a JSON file, but we can use the following query to get what we need.

CREDS=$(security find-generic-password \
        -s "Claude Code-credentials" \
        -a "caleb" \
        -w 2>/dev/null)

I haven’t interacted with the keychain much before, but I figured out these options mean the following:

This doesn’t just give us the token directly, it returns some JSON which we need to parse to get the key we want.

ACCESS_TOKEN=$(echo "$CREDS" | node -e "
  const data = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
  console.log(data.claudeAiOauth.accessToken);
")

Calling JavaScript from Bash?? I know, heretical. But in this case, since claude is an npm package, we know the user must have node installed; we can’t make the same assumptions about other tools like jq. As much as it pains me, it’s arguably the most reasonable choice.

API Call

Next, we find out what API call to make. One way to do this would be to use some MITM network sniffer like Charles or Proxyman, but I didn’t really feel like setting all that up. Instead, I pointed claude at its own cli.js source code, and after a few minutes it came back with the necessary URL and headers to make this work.

curl -s \
  -H "Content-Type: application/json" \
  -H "User-Agent: claude-code/2.0.55" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "anthropic-beta: oauth-2025-04-20" \
  "https://api.anthropic.com/api/oauth/usage"

Note that if you’re missing some headers (such as the User-Agent or anthropic-beta ones) the endpoint will give you a confusing error message like “OAuth authentication is not supported at this time.”

With the right headers, you’ll get a response with a JSON payload like so:

{
  "five_hour": {
    "utilization": 54.0,
    "resets_at": "2026-01-14T07:00:00.248722+00:00"
  },
  "seven_day": {
    "utilization": 31.0,
    "resets_at": "2026-01-19T03:00:00.248750+00:00"
  },
  "seven_day_oauth_apps": null,
  "seven_day_opus": null,
  "seven_day_sonnet": null,
  "iguana_necktie": null,
  "extra_usage": {
    "is_enabled": false,
    "monthly_limit": null,
    "used_credits": null,
    "utilization": null
  }
}

Now we can track our remaining usage without burning some of our quota each time!

P.S. If someone at Anthropic is reading this, I would love to know the story behind the iguana_necktie key1.

  1. One theory can be found in the comments on this Reddit post (return)