Skip to content
AI Full-Stack Wiki

LLM Cost Cheat Sheet: Prices, Formulas, and Levers

A one-page reference for LLM costs: token prices at the time of writing, the cost formula with caching and batches, quick estimates, and the levers that cut a bill.

Difficulty: Beginner8 min readUpdated
On this page· Prices

Why this matters

Cost questions come up in every design review: "what will this feature cost per user?", "is caching worth it here?", "should this be a batch job?". This page has the numbers and formulas to answer them in minutes. Prices change; the table shows list prices at the time of writing, so check the official pricing page before committing to a budget.

Prices#

USD per million tokens, list prices at the time of writing:

ModelInputCache write (5 min)Cache readOutput
claude-opus-5-5$4.00$5.00$0.20$20.00
claude-sonnet-5-5$2.00$2.50$0.20$10.00
claude-haiku-4-5$1.00$1.25$0.10$5.00
  • Cache writes cost 1.25× input for the 5-minute lifetime and 2× input for the 1-hour lifetime.
  • Batches API: 50% off all token prices for asynchronous work.
  • Output costs five times input on these models, so answer length matters.

Where the money goes in one request#

  • Uncached input
  • Cached input reads
  • Output
What one LLM request costs, split into uncached input, cached input, and output tokens: caching a long shared prefix cuts this request's cost by more than half.
Show text description

One request to claude-opus-5-5 at list prices at the time of writing ($4 per million input tokens, $0.20 per million cached input tokens read, $20 per million output tokens). The cache write on the first request costs 1.25 times the input price and is not shown.

Cost per request in US dollars
RequestUncached inputCached inputOutputTotal
Without caching$0.0800$0.0000$0.0160$0.0960
With a cached 18,000-token prefix$0.0080$0.0036$0.0160$0.0276

The formula#

cost = ( uncached_input × input_price
       + cache_write × input_price × 1.25        (2 for the 1-hour cache)
       + cache_read × cache_read_price
       + output × output_price ) / 1,000,000
       × 0.5 if sent through the Batches API

usage.input_tokens in a response already excludes cached tokens, which are reported separately as cache_creation_input_tokens and cache_read_input_tokens.

lib/estimate.ts
export const PRICES = {
  "claude-opus-5-5": { input: 4, cacheRead: 0.2, output: 20 },
  "claude-sonnet-5-5": { input: 2, cacheRead: 0.2, output: 10 },
  "claude-haiku-4-5": { input: 1, cacheRead: 0.1, output: 5 },
} as const;
 
export interface Tokens {
  input?: number; // uncached input tokens
  cacheWrite?: number;
  cacheRead?: number;
  output?: number;
}
 
export function estimateUSD(model: keyof typeof PRICES, t: Tokens, opts: { cacheTtl?: "5m" | "1h"; batch?: boolean } = {}): number {
  const p = PRICES[model];
  const writeMultiplier = opts.cacheTtl === "1h" ? 2 : 1.25;
  const raw =
    (t.input ?? 0) * p.input + (t.cacheWrite ?? 0) * p.input * writeMultiplier + (t.cacheRead ?? 0) * p.cacheRead + (t.output ?? 0) * p.output;
  return (raw / 1_000_000) * (opts.batch ? 0.5 : 1);
}
estimate.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { estimateUSD } from "./lib/estimate.ts";
 
const close = (a: number, b: number) => assert.ok(Math.abs(a - b) < 1e-9, `${a} != ${b}`);
 
test("a typical chat turn", () => {
  // 2,000 new input tokens, 10,000 read from cache, 500 output tokens on Opus 5.5
  close(estimateUSD("claude-opus-5-5", { input: 2_000, cacheRead: 10_000, output: 500 }), 0.008 + 0.002 + 0.01);
});
 
test("cache writes and batches", () => {
  close(estimateUSD("claude-haiku-4-5", { cacheWrite: 1_000_000 }), 1.25);
  close(estimateUSD("claude-haiku-4-5", { cacheWrite: 1_000_000 }, { cacheTtl: "1h" }), 2);
  close(estimateUSD("claude-sonnet-5-5", { input: 1_000_000, output: 1_000_000 }, { batch: true }), 6);
});

Rules of thumb#

QuantityApproximation
English textAbout 4 characters, or 0.75 words, per token (count exactly with countTokens)
One page of proseAbout 500 to 700 tokens
CodeMore tokens per character than prose
A chat turn's inputGrows with the whole history: turn n resends turns 1 to n−1
Monthly costrequests per day × cost per request × 30

Levers, in the order to try them#

LeverTypical savingRisk
Prompt caching for stable prefixes50–90% of inputNone
Batches API for work that can wait50%Latency only
Shorter outputs (format instructions, max_tokens, lower effort)20–50% of outputLow
Less context (better retrieval, history trimming)VariesMedium
Model routing30–70%Needs evals

Common mistakes#

  • Estimating from input only. Output is often the larger share.
  • Forgetting history growth. Long chats cost more per turn unless cached or trimmed.
  • Using another provider's tokenizer. Count with the API you use.
  • No per-user limits. Costs are per request; abuse scales them.

Try it

Estimate a feature in five minutes

  1. Write down requests per day, input tokens (and how much is a stable prefix), and output tokens for one feature.
  2. Use estimateUSD for the cost per request without and with caching, and multiply to a monthly figure.
  3. Compare with the revenue or budget per user and decide whether you need limits.

Check your understanding

On these models, output tokens cost how much compared with input?
What does the Batches API change?
Does usage.input_tokens include cache reads?

Key takeaways

  • Cost = uncached input + cache writes + cache reads + output, each at its own price, halved for batches.
  • Output is the expensive side; history growth is the hidden one.
  • Try levers in order: caching, batching, shorter outputs, less context, then routing with evals.
  • Check current prices before committing to a budget.

Next steps#

Finished this article? Track it to see your progress on the roadmap.