Skip to content

Repository files navigation

tokens-usage

Count tokens before sending a request or before persisting a provider response to your database. tokens-usage supports OpenAI, Anthropic, and Google so you can track context window usage with accurate counts, plan what fits in the next turn, and avoid unexpected API costs.

tokens-usage also supports AI SDK message formats (ModelMessage / UIMessage) as input. AI SDK is not a provider.

Uses the provider's official endpoint when available (mode: "endpoint" or "auto" with an API key). Otherwise, it uses local strategies (mode: "local").

Install

npm install tokens-usage

If you pass UIMessage[] as content, install AI SDK as well:

npm install tokens-usage ai

Usage

import { countTokens, estimateTokens } from "tokens-usage";

const result = await countTokens({
  provider: "openai",
  model: "gpt-5.5",
  content: [
    { role: "user", content: "Hello" },
    {
      type: "function_call",
      call_id: "call_1",
      name: "get_weather",
      arguments: "{\"city\":\"Paris\"}",
    },
  ],
  apiKey: process.env.OPENAI_API_KEY,
  countAssistantTools: true,
});

console.log(result.tokens);
console.log(result.estimated);
console.log(result.method);
console.log(result.price);

Plain text is the simplest form:

await countTokens({
  provider: "openai",
  model: "gpt-4o",
  content: "Hello world",
});

AI SDK (ModelMessage / UIMessage)

import { countTokens, type ModelMessage, type UIMessage } from "tokens-usage";

const modelMessages: ModelMessage[] = [
  { role: "system", content: "Be concise." },
  { role: "user", content: [{ type: "text", text: "Hello" }] },
];

await countTokens({
  provider: "openai",
  model: "gpt-4o",
  content: modelMessages,
});

const uiMessages: UIMessage[] = [
  {
    id: "1",
    role: "user",
    parts: [{ type: "text", text: "Hi from UIMessage" }],
  },
];

await countTokens({
  provider: "google",
  model: "gemini-2.0-flash",
  content: uiMessages,
});

Notes:

  • ModelMessage[] uses strict model validation per provider:
    • model must exist in tokens-usage catalog
    • model must be supported by AI SDK for that provider
  • UIMessage[] is converted internally with AI SDK convertToModelMessages (requires the ai peer dependency).
  • v1 counts text + tool parts; non-text media parts are ignored.

Provider Inputs

OpenAI

await countTokens({
  provider: "openai",
  model: "gpt-5.5",
  content: "Hello world",
});

await countTokens({
  provider: "openai",
  model: "gpt-5.5",
  content: [{ role: "user", content: "Hello world" }], // ResponseInput
});

Anthropic

await countTokens({
  provider: "anthropic",
  model: "claude-sonnet-4-6",
  content: "Hello",
  system: "Be concise",
});

await countTokens({
  provider: "anthropic",
  model: "claude-sonnet-4-6",
  content: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
  system: "Be concise",
});

Google (Gemini)

await countTokens({
  provider: "google",
  model: "gemini-3.5-flash",
  content: "Hello",
  system: "Be concise",
});

await countTokens({
  provider: "google",
  model: "gemini-3.5-flash",
  content: [{ role: "user", parts: [{ text: "Hello" }] }],
});

content (auto-detected)

Pass content as a string or array. tokens-usage infers the format automatically:

Shape Detected as
string Plain text
OpenAI ResponseInput (incl. function_call items) OpenAI native
Anthropic MessageParam[] Anthropic native
Google Content[] (parts) Google native
AI SDK ModelMessage[] (content, tool parts, tool role) AI SDK messages
AI SDK UIMessage[] (parts with typed items) UI messages

Optional top-level fields:

  • system?: string — for plain text (Anthropic/Google) or Anthropic native payloads
  • systemInstruction?: Content — for Google native payloads

Validation is fail-fast:

  • Plain text must be non-empty.
  • Arrays must include at least one item.
  • AI SDK messages require strict model support (catalog + AI SDK).
  • Non-text media parts are ignored for counting in AI SDK / UI paths (v1).

Migration 0.3 → 0.4

In 0.4.0, inputMode was removed. Pass the payload directly as content:

0.3.x 0.4.0
{ inputMode: "text", input: "Hi" } { content: "Hi" }
{ input: responseInput } (OpenAI) { content: responseInput }
{ messages: [...] } (Anthropic) { content: [...] }
{ contents: [...] } (Google) { content: [...] }
{ inputMode: "ai_sdk", aiSdkMessages } { content: modelMessages }
{ inputMode: "ai_sdk", uiMessages } { content: uiMessages }
{ system: "..." } (Anthropic text) { content: "...", system: "..." }

No content.type field is required — the library infers it from the shape.

estimateTokens uses the same shape (without mode).

countAssistantTools

Default: true.

When set to false, tool blocks are excluded from the count:

  • OpenAI: function_call, function_call_output
  • Anthropic: tool_use, tool_result
  • Google: functionCall, functionResponse

Modes

  • auto (default): tries the endpoint and falls back to local if a recoverable error occurs
  • endpoint: uses only the provider endpoint
  • local: no network

estimateTokens(options) is equivalent to countTokens({ ...options, mode: "local" }).

API Keys

Can be passed via apiKey or environment variables:

Provider Env var
OpenAI OPENAI_API_KEY
Anthropic ANTHROPIC_API_KEY
Google GOOGLE_GENERATIVE_AI_API_KEY or GEMINI_API_KEY or GOOGLE_API_KEY

Response Shape

{
  provider: "openai" | "anthropic" | "google",
  model: string,
  tokens: number,
  estimated: boolean,
  method: "provider_endpoint" | "local_tiktoken" | "local_anthropic" | "local_heuristic",
  price: { usd: number } | null
}

Local Strategies

  • OpenAI: tiktoken
  • Anthropic: @anthropic-ai/tokenizer
  • Google: chars/4 heuristic

Also exports countHeuristic({ text }).

Scripts

npm test
npm run test:integration
npm run try:all
npm run try:openai

Notes

  • Counts input tokens (prompt/input), not output tokens.
  • price is null if the model is not in the pricing table.

License

tokens-usage is source-available under a custom license. See LICENSE.md for the full terms.

About

Counts input tokens and estimates cost (USD) for OpenAI, Anthropic, and Google.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages