The weekly cap stacked on the 5-hour window: two caps, one binary indicator

Anthropic tightened Claude Pro enforcement weeks ago by stacking a server-side weekly cap on top of the rolling 5-hour window. The Settings page still shows one continuous bar (the 5-hour bucket) and one binary label that only flips between “low” and “reset at X”. The weekly buckets, including the Opus-only one, are in the JSON the page itself fetches; they are just not rendered with a percent. That is why most Pro users do not realize they are at 78 percent on weekly until the next request 429s.

M
Matthew Diakonov
9 min read
4.9from Sourced from the live claude.ai usage endpoint
Field names from src/models.rs, lines 3-7
Verifiable in 30 seconds with one curl
Same JSON the Settings page itself fetches

The bigger shift: a weekly cap on top of the rolling 5-hour window

For most of 2024 and early 2025, the only Pro cap that mattered in practice was the rolling 5-hour window. People built mental models around 45 messages every five hours, the number drifted around in Help Center copy, and the in-app indicator hinted at it. In late 2025 Anthropic introduced a server-side weekly cap on top of the existing 5-hour window and tightened enforcement progressively over the next few months. By early 2026 the weekly bucket was binding for many heavy Pro users on Opus.

The shift is subtle because the Settings page UI did not change to match. The 5-hour bar still draws the same shape, and the auxiliary label still flips between “usage is low” and a reset notice. But the underlying JSON has new keys, and the rate limiter compares against all of them.

Mental model swap

The Settings page bar is at 42 percent, the auxiliary label says usage is low, so I have plenty of headroom. I will keep working with Opus on this refactor and check again in a few hours.

  • Implies one bucket: the 5-hour window
  • Implies the binary low/reset label covers all caps
  • Hides the seven_day_opus percent entirely
  • Easy to walk into a 429 with the 5-hour bar still half empty

The anchor fact: the JSON has all the percents

Hit GET /api/organizations/{org_uuid}/usage with your logged-in claude.ai cookies. This is the same endpoint the Settings page fetches to draw the bar. Verbatim shape:

claude.ai/api/organizations/{org_uuid}/usage

Three weighted utilization fractions, each with their own ISO 8601 reset timestamp. The Settings page renders one of them as a bar (5-hour) and elides the other two behind a binary label. The rate limiter sees all of them.

One struct, every bucket

ClaudeMeter deserializes every bucket into the same struct. When Anthropic adds another cap (it has happened twice in the last six months), the type system catches it as a parse error rather than silently misrendering:

claude-meter/src/models.rs

One Opus prompt, three buckets ticked

A single Opus completion increments the 5-hour bucket, the 7-day bucket, and the 7-day Opus bucket. The rate limiter trips on whichever of them hits 1.0 first.

five_hour and seven_day_opus update path

Youclaude.ai serverfive_hour bucketseven_day bucketseven_day_opus bucketRate limiterPOST /completions (Opus)increment by weightincrement by weightincrement by weight429 if any bucket >= 1.0GET /usage returns all bucketshighest utilization is the constraint

Why the in-app indicator only flips between low and reset

The Settings page indicator is a category badge layered on top of a single bar. The bar is rendered from five_hour.utilization (a continuous fraction), but the badge text collapses every other bucket into one of two states: roughly “usage is low” or “usage will reset at X”. The continuous percents on seven_day and seven_day_opus do not get a bar of their own.

The result is a UI in which two genuinely different states (78 percent on weekly, 5 percent on weekly) look identical to the user. The first will 429 your next prompt, the second will not. The bar gives no signal because the bar is the 5-hour bucket and the 5-hour bucket might be empty either way.

What feeds each weekly bucket

Inputs to the weekly utilization fractions

Prompt tokens
Attachments
Tool calls
Model picked
Peak-hour multiplier
Browser-chat usage
seven_day / seven_day_opus
Settings page bar (only 5-hour)
ClaudeMeter menu bar (every bucket)
429 at >= 1.0 on any bucket

Why pricing moved from tokens to quota

For a long time, Pro pricing copy was framed in tokens. You would see numbers like “roughly N million tokens per week”, and people would estimate from there. In late 2025 the wording moved to language about server-side utilization and rolling windows. That is not a marketing tweak. It reflects an actual change in how enforcement works. The cap is no longer a token estimate. It is a weighted utilization fraction with its own multipliers.

Two consequences. First, calculators that estimate “I have N tokens left” are now unreliable, because the server-side weighting (peak-hour multiplier, attachment cost, tool-call cost, model class) drifts the conversion ratio. Second, the only number that maps cleanly to a 429 is the utilization float in the JSON. There is no published formula and no token count to back-derive.

Reproduce it yourself in one curl

You do not need a tool to see the gap. Open DevTools on claude.ai/settings/usage, copy the cookie header from the Network panel, and call the endpoint:

claude.ai/api/organizations/{org_uuid}/usage

The first time someone runs this and sees seven_day_opus at 0.91 while the bar on the Settings page sits at 0.42, the reaction is usually a flat “oh”.

The whole verification path, end to end

1

Open claude.ai/settings/usage with DevTools open

Switch to the Network tab, filter by XHR. Reload the page. You will see one request to /api/organizations/{your-org-uuid}/usage. Click it, look at the Preview panel.

2

Find every utilization key

five_hour and seven_day are always there. seven_day_opus appears on Pro and Max plans. extra_usage appears if you have purchased credits. Each has its own utilization float and resets_at timestamp.

3

Normalize the scale

Some buckets return 0.78, some return 78.0 in the same payload. Pick a scale and apply one clamp: u <= 1 ? u * 100 : u. ClaudeMeter does this in extension/popup.js lines 6 to 11.

4

Surface the highest one

Whichever bucket is highest is the one you will trip first. ClaudeMeter renders all buckets in the popup, with the one closest to 100 percent emphasized so it is impossible to miss.

5

Use resets_at to plan

If you are at 91 percent on seven_day_opus and resets_at says 5 days, switch to Sonnet for the next refactor pass. If five_hour is the bottleneck, plan a break instead. Different buckets imply different remediations.

Why the binary indicator misses 78 percent

Where the gap between UI and JSON shows up

  • The Settings page shows one bar (the 5-hour bucket) and one binary label. The seven_day and seven_day_opus percents do not appear on the page even though they are in the JSON the page itself fetched.
  • Pricing-page wording moved from token estimation to server-side quota in late 2025. Mental models built on the old token language no longer line up with the enforcement model.
  • The weekly cap is rolling, not calendar-week. resets_at slides forward as old messages age out, so the cap behaves like a hard ceiling even though it is technically a 7-day rolling boundary.
  • Tightening happened gradually. Many users did not notice until a refactor that finished fine in February failed in late March because seven_day_opus was now binding.
  • The 429 returned to the client does not name which bucket tripped. From the client side, hitting the 5-hour cap and hitting the Opus weekly cap are indistinguishable. The only way to disambiguate is to read the buckets directly.

Real-time menu-bar tracker vs in-app indicator

Both read the same endpoint. They render different slices of the response.

Featureclaude.ai Settings indicatorClaudeMeter (menu bar)
Caps shown5-hour bar only5-hour, 7-day, 7-day Opus, extra credits
Continuous percentonly on the 5-hour baryes, on every bucket
Refresh cadenceon Settings page reloadevery 60 seconds (live)
Surfaceclaude.ai/settings/usage (must navigate)macOS menu bar (always visible)
Resets countdownbinary low/reset label onlyhuman-readable on every bucket
Predicts which 429 will fire firstno (only 5-hour visible)yes (highest bucket wins)
Costincluded with Pro/Maxfree, MIT licensed
Source datasame endpoint, partial rendersame /api/organizations/{org}/usage endpoint

Numbers that matter

From the implementation. No invented benchmarks.

0weekly buckets visible in the JSON on Pro
0of those weekly buckets visible in the UI
0sClaudeMeter poll cadence
0cookies you have to paste

Common myths to drop

Myth: there is only one cap on ProMyth: the in-app label shows weekly stateMyth: weekly cap is calendar-weekMyth: ccusage tracks the weekly capMyth: 429s name which bucket trippedMyth: token counts equal server quota

What a real-time tracker actually shows

Three things on screen at once: the current utilization fraction for every bucket the API returns, a human-readable countdown to each bucket’s next age-out moment, and a flag on whichever bucket is closest to the cap. A typical menu-bar render looks like:

5h: 0% (2h 47m)
7d: 0% (5d 18h)
7d Opus: 0% (5d 18h)

At a glance: the 5-hour bucket is fine, the weekly is meaningfully full, and the Opus weekly is the binding constraint. If the next prompt 429s, you know exactly which bucket triggered it (the highest one) and exactly which mitigation works (switch to Sonnet, not take a break). Neither of those decisions is possible from the binary in-app indicator.

Where ClaudeMeter fits, and where it does not

ClaudeMeter is one option. It happens to be the one we maintain, so it is the one this site documents in detail. It is a small Rust menu-bar app with a browser extension that forwards your existing claude.ai session to a localhost bridge, polls the usage endpoint every 60 seconds, and renders every bucket. Free, MIT licensed, no cookie paste.

It is not the only option. ccusage, ccburn, Claude-Code-Usage-Monitor, and a handful of other open-source tools cover adjacent surfaces (local token attribution per project, JSONL parsing, cost forecasting). For weekly-cap visibility specifically, you want a tool that reads the server endpoint rather than your local logs. Anything that ships its own clamp on five_hour.utilization and persists snapshots for later analysis is a fine choice.

The honest caveat

The endpoint is internal and undocumented. The field names have been stable for many months but Anthropic could rename, add, or remove buckets in any release. ClaudeMeter deserializes the response into a strict Rust struct in src/models.rs, so when the shape changes the menu bar surfaces a parse error and a release ships the same day. Until then, this is where the weekly cap lives, and these are the numbers the rate limiter compares against.

See every bucket, live

ClaudeMeter sits in your macOS menu bar, polls every 60 seconds, and shows the 5-hour, 7-day, and Opus-weekly percents at once. Free, MIT licensed, no cookie paste, reads the same JSON claude.ai/settings/usage reads.

Install ClaudeMeter

Frequently asked questions

What changed with the Claude Pro weekly cap?

Anthropic added a server-side weekly quota stacked on top of the existing rolling 5-hour window in late 2025 and tightened enforcement on it through early 2026. Before that, you could really only run yourself out on the 5-hour bucket. Now there are at least three weekly buckets visible in the API response: seven_day (overall), seven_day_opus (Opus-specific), and a third Sonnet-leaning bucket on some plans. Hitting any of them returns a 429 even if your 5-hour window is empty.

Why does the in-app indicator only flip between low and reset?

Because the indicator is a category badge, not a meter. The Settings page renders a bar from five_hour.utilization, and a small auxiliary label that says either roughly 'usage is low' or 'usage will reset at X'. The label has a binary feel because it collapses a continuous fraction into two states. The underlying number is continuous and it is in the JSON the page itself fetched. ClaudeMeter and a few other open-source tools surface the continuous number directly.

What does the server actually return for the weekly cap?

Hit GET https://claude.ai/api/organizations/{your-org-uuid}/usage. The response includes a seven_day object with utilization (a float) and resets_at (an ISO timestamp), plus seven_day_opus on Pro and Max plans, plus an extra_usage object if you have credits enabled. The fields use the same shape as five_hour, so anything you have already written to read the 5-hour bucket extends naturally to the weekly buckets.

How is the weekly cap different from the rolling 5-hour window?

The 5-hour window is rolling: at any moment it covers the last 5 hours of activity, weighted by prompt cost. The weekly cap as currently implemented behaves more like a 7-day rolling boundary too, with resets_at sliding forward as old messages age out. Practically, you almost never see seven_day fall, because seven days is long enough that even idle weekends barely move the boundary. That makes the weekly bucket look like a hard ceiling even though it is technically rolling.

Why do most Pro users not realize they are at 78 percent until they 429?

Two reasons. First, the in-app indicator does not show a percent on the weekly buckets, only on the 5-hour bucket. Second, pricing-page wording moved from token estimation to server-side quota in late 2025. People keep using the old mental model ('I get N tokens per week'), which the server is no longer enforcing in those terms. The actual cap is a weighted utilization fraction with no published formula. The only signal is the float in the JSON.

Does ccusage track the weekly cap?

No. ccusage and similar local-token tools (ccburn, Claude-Code-Usage-Monitor) read JSONL files under ~/.claude/projects, which only contain Claude Code traffic and only contain raw token counts. The weekly cap on the server is weighted by peak-hour multiplier, attachments, tool calls, and model class, and it folds in browser-chat usage which is not on disk anywhere. ccusage is excellent for local token attribution; it is not a faithful proxy for seven_day.utilization.

Seeing a different shape on the weekly buckets?

If your payload returns extra fields, a different scale, or a resets_at that does not slide, send it. We map every variant we see.