LLM Usage Normalizer

Paste a raw usage object from Anthropic Messages, OpenAI Responses or Chat Completions, or Gemini generateContent. Each field is named under that provider's own definition, rebuilt on one common basis, and every sum that would double-count is flagged with its arithmetic. Everything runs in your browser.

Input

Paste a usage object, or load an example.

Common basis

Optional cost

No prices ship with this page. Enter your own rates per million tokens, in any currency. Multipliers apply to the input rate. Leave a multiplier empty to bill that cache traffic at the input rate.

That button fills 0.1 for reads and 1.25 for writes, from the OpenAI prompt-caching guide's model table (read 2026-10-16: "1.25× the uncached input-token rate" for cache writes; reads at 0.1× on most of these models and 0.05× on GPT-6.1 Sol). Earlier OpenAI models have "No additional cache-write charge". Check the guide before you rely on it.

Enter an input rate and an output rate to see a cost.

Each provider's own definition

Anthropic Messages

  • input_tokens is only what comes after the last cache breakpoint. The input_tokens field represents only the tokens that come after the last cache breakpoint in your request, not all the input tokens you sent.
  • The total is a documented sum. total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens
  • The split cache write must add up. Note that the current cache_creation_input_tokens field equals the sum of the values in the cache_creation object.
  • Thinking is inside output_tokens: usage.output_tokens_details.thinking_tokens reports how many of the billed output tokens were internal reasoning.
  • For rate limits on most models, cache reads do not count toward input tokens per minute, so the ITPM line is input_tokens + cache_creation_input_tokens.

Sources: https://platform.claude.com/docs/en/build-with-claude/prompt-caching, https://platform.claude.com/docs/en/api/rate-limits, https://platform.claude.com/docs/en/build-with-claude/extended-thinking

OpenAI Responses and Chat Completions

  • input_tokens (Responses) and prompt_tokens (Chat) include cached and cache-written tokens. The prompt-caching guide computes ordinary input in its own code: const ordinaryInputTokens = inputTokens - cachedTokens - cacheWriteTokens;
  • Both APIs now report cache writes. Responses: "The number of input tokens that were written to the cache." Chat: "The unadjusted number of prompt tokens written to cache." This page quotes the word "unadjusted" and does not interpret it. A missing field is counted as 0 and labelled.
  • Reasoning is inside the output count, and output counts every generated token. Reported output token usage includes all tokens generated by the model, not only the text visible in a response. The Responses API reports this total as output_tokens, while the Chat Completions API reports it as completion_tokens.
  • The guide adds that formatting tokens are not necessarily itemized separately in usage, so output minus reasoning is labelled "non-reasoning output (may include formatting tokens)", never "visible text tokens".

Sources: https://developers.openai.com/api/docs/guides/prompt-caching, https://developers.openai.com/api/reference/resources/responses, https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create, https://developers.openai.com/api/docs/guides/token-counting, https://developers.openai.com/api/docs/guides/reasoning

Gemini generateContent (UsageMetadata)

  • promptTokenCount includes cached content. When cachedContent is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content.
  • The total is defined as a sum, and the definition was rewritten during October 2026 (the reference read on 2026-10-16 is marked "Last updated 2026-10-13 UTC"). Total token count for the generation request (prompt + tool-use prompt + thoughts + response candidates).
  • Thoughts are their own count, outside candidatesTokenCount, so total output is candidates plus thoughts. UsageMetadata documents no cache-write count.

Source: https://ai.google.dev/api/generate-content

This has happened in the wild

  • langfuse/langfuse#12306 (closed as not planned): an emitter wrote gen_ai.usage.input_tokens already including cache, and the consumer added cache read and cache write again. Its worked example: 5 + 128,955 + 1,253 = 130,213, shown as 260,421.
  • pydantic/pydantic-ai#4364 (closed as not planned): the same root cause, reported from the emitter side.
  • BerriAI/litellm#40006 (open): only the custom_cost_per_token path bills Anthropic cache reads twice; the issue says default model-map pricing is not affected.
  • BerriAI/litellm pull request #25517 (merged 2026-04-10): a Bedrock streaming double count, prompt_tokens 65339 instead of 32671.

This is an independent tool. It is not affiliated with or endorsed by Anthropic, OpenAI, Google, Langfuse, Pydantic or LiteLLM. Vendor and project names appear only to identify the formats and reports described.

Self test

Runs on load and on demand, against the same code that fills the table: every example's rows, each double-count finding firing on its trigger and staying silent otherwise, provider detection, the Gemini total check, input errors, and a positive control written to fail.

Not run yet.

Show every check
Self test results
CheckExpectedGotResult