Skip to content

Add cached input prices for 12 Claude models (refs #46) - #67

Open
xyzs996 wants to merge 1 commit into
simonw:mainfrom
xyzs996:anthropic-cached-input
Open

xyzs996 wants to merge 1 commit into
simonw:mainfrom
xyzs996:anthropic-cached-input

Conversation

@xyzs996

@xyzs996 xyzs996 commented Aug 22, 2026 •

Copy link
Copy Markdown

Refs #46. All 17 Anthropic entries currently have input_cached: null; this fills in 12 of them.

Source: the Cache Hits & Refreshes column of Anthropic's own pricing table, https://platform.claude.com/docs/en/about-claude/pricing, read 2026-08-22. Every value below is quoted from that column, and every one is also exactly 0.1 × input — the multiplier documented in the prompt-caching section of the same page ("Cache read (hit) — 0.1x base input price").

id input input_cached
claude-3.5-haiku 0.8 0.08
claude-4.5-haiku 1 0.1
claude-sonnet-4.5 3 0.3
claude-sonnet-5 2 0.2
claude-opus-4 15 1.5
claude-opus-4-1 15 1.5
claude-opus-4-5 5 0.5
claude-opus-4-6 5 0.5
claude-opus-4-7 5 0.5
claude-opus-4-8 5 0.5
claude-fable-5 10 1
claude-mythos-5 10 1

Left as null on purpose: claude-3.7-sonnet, claude-3.5-sonnet, claude-3-opus, claude-3-haiku, claude-sonnet-4.5-200k. These are no longer in that per-model table, so there's no live vendor page to quote for them. The 0.1x rule has held for every one of them since prompt caching shipped, so if you'd rather have 0.3 / 0.3 / 1.5 / 0.025 / 0.6 in there on the strength of the documented multiplier, say the word and I'll push a second commit. I didn't want to put a derived number into a file whose whole value is that it's quoted.

python3 scripts/build.py runs clean: current-v1.json picks up 12 more non-null input_cached values and is otherwise byte-identical.

Two things I noticed while checking, happy to send either as its own PR:

  • Claude Opus 5 ($5 in / $25 out / $0.50 cached) and Claude Sonnet 4.6 ($3 / $15 / $0.30) are on the current pricing page but missing from data/anthropic.json.
  • Anthropic also publishes cache write prices (1.25x input for the 5-minute TTL, 2x for the 1-hour). No idea whether a write column is in scope here — mentioning it because for short-lived caches the write price is the one that decides whether caching pays off at all.

Why I bothered with this column. For coding-agent workloads input_cached isn't a footnote, it's the answer. hungson175 measured one agent's real token mix over 8.04B tokens and got 95.6% cache reads, 4.1% cache misses, 0.29% output. At that mix the effective price is almost entirely the column that's null here. I ran 60 models through it and list input price overstates the real bill by a median 6.5x (range 3.4x–7.9x); the ranking barely moves, but the absolute numbers do. null isn't wrong today — it just hides the number that matters most for that one (increasingly common) use case.

Refs simonw#46. Values are taken verbatim from the "Cache Hits & Refreshes"
column of Anthropic's own pricing table at
https://platform.claude.com/docs/en/about-claude/pricing (read 2026-08-22).

Every filled value is also 0.1x that model's base input price, which is the
documented multiplier on the same page: "Cache read (hit) | 0.1x base input
price".

Left as null: claude-3.7-sonnet, claude-3.5-sonnet, claude-3-opus,
claude-3-haiku and claude-sonnet-4.5-200k. Those no longer appear in that
per-model table, so there is no live vendor page to quote for them.
@xyzs996

xyzs996 commented Aug 24, 2026

Copy link
Copy Markdown
Author

Found something while checking this that I think upgrades it from "a column is blank" to "the comparison picks the wrong winner", so I want to put it in front of you before this sits any longer.

null doesn't read as unknown downstream — it reads as no discount:

// index.html:422 (and the sort comparator, :395/:398)
const cachedInputCost = model.input_cached || model.input;

So when a Claude model is compared against one that does have input_cached, the Claude side has its cached tokens billed at full input price — 10x the documented rate — and the same expression drives the sort, so the ranking is computed that way too.

At an agent-shaped mix (95.64% cache reads / 4.07% miss / 0.29% output, 10M tokens) 37 of the 289 Claude x cache-priced pairings currently sort the wrong way round. Worst offenders:

pairing site says actually
Claude Sonnet 5 vs Gemini 2.5 Pro >200k $20.23 vs $3.84 — Gemini wins 5.3x $3.02 vs $3.84 — Claude wins
Claude 4.5 Haiku vs Kimi K2 Thinking $10.12 vs $1.75 — Kimi wins 5.8x $1.51 vs $1.75 — Claude wins
Claude 3 Haiku vs Gemini 2.5 Flash $2.53 vs $0.48 — Gemini wins 5.3x $0.38 vs $0.48 — Claude wins

Fair caveat on scope: this only bites when the cached-tokens field is actually visible, and :366 only shows it if some selected model has non-null input_cached. So Claude-vs-Claude is unaffected — it's specifically the mixed comparison, which is the case the compare mode exists for.

Two ways to read that, and it's your call which:

  1. Merge this and the blanks stop lying. Doesn't fix the underlying ||.
  2. Treat null as unknown in the code — skip the model, or show the cached row as "n/a" instead of silently substituting input. Then a missing value can never quietly become a 10x number for any vendor, not just Anthropic. Happy to send that as a separate PR if you want it.

I'd lean on doing both, but (2) is the one that keeps this from recurring the next time a vendor ships before the data lands.

Offer from the original description still stands, no rush: the remaining five (claude-3.7-sonnet 0.3, claude-3.5-sonnet 0.3, claude-3-opus 1.5, claude-3-haiku 0.025, claude-sonnet-4.5-200k 0.6) are derived from the documented 0.1x rather than quoted from a live table, so I've deliberately left them null until you say which way you want it. The commit is ready either way.

This branch has not been deployed

No deployments
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