Originally published on Extenify.
LLM cost per user is the number that tells you whether your AI feature earns money or quietly burns it. Your OpenAI, Claude or Gemini invoice shows the monthly total, but not that one user ran 4,000 summaries while the median user ran 30. Every response already reports its token usage, so you can build the per-user view yourself.
Provider dashboards stop at the API key
Provider reporting follows your account structure. Anthropic's Usage and Cost Admin API, for example, groups spend by API key, workspace, model and service tier. That helps you check an invoice, but a typical AI extension or SaaS backend sends every user's request through one server and one key.
The per-user fields that do exist are for abuse detection, not billing:
- OpenAI's
safety_identifierhelps OpenAI spot users who break its usage policies. - Anthropic's
metadata.user_idis an external user ID Anthropic may use to detect abuse.
Send a hashed ID in both, but don't expect a cost report from them. The answer is the same one developers landed on back in 2023: log the user, model and token counts for each call in your own database.
The three providers count input tokens differently
Each provider returns a usage object, but "input" means something different in each:
| OpenAI (Responses) | Claude (Messages) | Gemini (generateContent) | |
|---|---|---|---|
| Input field | input_tokens | input_tokens | promptTokenCount |
| Includes cached tokens? | Yes | No | Yes |
| Cache reads | input_tokens_details.cached_tokens | cache_read_input_tokens | cachedContentTokenCount |
| Reasoning | inside output_tokens | inside output_tokens | thoughtsTokenCount, separate |
Two consequences:
- Normalize before you price. For OpenAI, uncached input is
input_tokensminus cache reads and cache writes. For Claude, total input is cache reads plus cache writes plusinput_tokens. - Thinking is billed as output on all three. A response can cost money even if it returns no visible text. For Gemini, add
thoughtsTokenCountto the output count yourself.
A compact normalizer that maps everything into one shape:
const n = (v) => v ?? 0; export function toTokens(provider, u) { if (provider === 'anthropic') { return { fresh: u.input_tokens, cacheRead: n(u.cache_read_input_tokens), cacheWrite: n(u.cache_creation_input_tokens), out: u.output_tokens }; } if (provider === 'openai') { const read = n(u.input_tokens_details?.cached_tokens); const write = n(u.input_tokens_details?.cache_write_tokens); return { fresh: u.input_tokens - read - write, cacheRead: read, cacheWrite: write, out: u.output_tokens }; } // gemini const read = n(u.cachedContentTokenCount); return { fresh: u.promptTokenCount - read, cacheRead: read, cacheWrite: 0, out: n(u.candidatesTokenCount) + n(u.thoughtsTokenCount) }; } Streaming is covered too. OpenAI puts usage on the response.completed event, Claude's message_delta counts are cumulative (keep the last one, don't add them), and Gemini's streamed chunks carry usageMetadata (keep the last). Write the record in a finally block so a cancelled stream still gets charged to the right user.
Price every request with a dated rate
Token counts only turn into dollars through a price table, and two details matter:
- Prices have start dates. The original guide's example: Gemini 3.8 Flash is $0.75 / $3.75 per million input/output tokens through December 31, 2026, and $1.50 / $7.50 from January 1, 2027. Store each model's prices as periods and pick the one in force on the request date.
- Some models switch tiers on long prompts. Above a size threshold, the whole request is billed at a higher rate, so check total input before choosing the rate.
Store the result as integer micro-dollars per request. Summing millions of floats drifts; summing integers doesn't.
Here's why per-request pricing matters. Take a page summary with 6,000 input tokens (4,000 cached) and 500 output tokens. At October 2026 prices it costs about $0.0094 on gpt-6.1-sol and about $0.0037 on Gemini 3.8 Flash. At 40 a day for 30 days, that one user costs roughly $11.28 a month on the first model and $4.41 on the second, until the Gemini price doubles in January. If your plan is $5, that line is your whole margin.
One ledger row per call, then one query
Each row needs: a server-verified user ID (never a value the extension sends, since anyone can edit extension code), feature name, provider, model, timestamp, normalized tokens, cost in micro-dollars, and status (completed, incomplete, cancelled). Index on { userId, at }.
From there, a monthly group-by-user followed by a percentile step (MongoDB 7.0+ has $percentile) gives you what you need. Read the results in this order:
- Average cost per active user vs. revenue per user. That's your gross margin on the AI feature.
- Median vs. p99. If the p99 user costs 50 times the median, a flat plan is subsidizing a handful of people.
- Cost by feature. An expensive feature that few people use is a good candidate for a smaller model.
- Free vs. paid. Free users with no limit can cost more than paying users bring in.
Budget in dollars, not requests
Request quotas protect you from bursts, not from cost: one 200,000-token page costs far more than a short paragraph. Before each call, check the user's month-to-date spend against a dollar limit (at scale, keep a running counter instead of summing every time). Then act on what the ledger shows: send simple tasks to cheaper models, cache shared system prompts, alert on spikes, and add a new price period the day a price change is announced.
Once a month, compare ledger totals with each provider's own reporting. A gap of more than a few percent usually means a code path, such as a background job, that calls the model without writing a row.
Key takeaways
- Provider dashboards break spend down by key, project and model, never by your end users. You have to log that yourself.
- OpenAI and Gemini input counts include cached tokens; Claude's don't. Normalize first.
- Reasoning and thinking tokens are billed as output everywhere.
- Price each call with the rate in force that day, and store integer micro-dollars.
- Watch p99 vs. median, and enforce monthly dollar budgets per user.
The full guide to tracking LLM cost per user across OpenAI, Claude and Gemini includes the complete price table, ledger code and MongoDB aggregation. And if you want the other half of the unit economics, weekly users and ratings for your extension, Extenify's browser extension analytics dashboard tracks them daily on Chrome, Edge and Firefox.
What does your AI feature's p99 user cost compared with the median, and what did you change once you found out?


