openai_cost_calculator

🪙 One-line helper that turns any OpenAI / Azure OpenAI response ( Chat Completions or Responses API ) into a human-readable USD cost — accurate to 8 decimals, with both string and strongly-typed APIs.

Why this library?

Installation

pip install openai-cost-calculator

(Package name on PyPI uses dashes; import name is from openai_cost_calculator import ….)

Quick start

New: For applications requiring precise financial calculations, use the strongly-typed API with estimate_cost_typed().

Legacy String API (Backward Compatible)

from openai import OpenAI
from openai_cost_calculator import estimate_cost

client = OpenAI(api_key="sk-…")
resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role":"user","content":"Hi there!"}],
)

print(estimate_cost(resp))
# {'prompt_cost_uncached': '0.00000150',
#  'prompt_cost_cached'  : '0.00000000',
#  'completion_cost'     : '0.00000600',
#  'total_cost'          : '0.00000750'}

Strongly-Typed API (Recommended for New Code)

from openai import OpenAI
from openai_cost_calculator import estimate_cost_typed

client = OpenAI(api_key="sk-…")
resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role":"user","content":"Hi there!"}],
)

cost = estimate_cost_typed(resp)
print(f"Total cost: ${cost.total_cost}")  # Decimal('0.00000750')

# Access individual components with Decimal precision
print(f"Prompt (uncached): ${cost.prompt_cost_uncached}")
print(f"Prompt (cached): ${cost.prompt_cost_cached}")
print(f"Completion: ${cost.completion_cost}")

# Convert to dict as needed
decimal_dict = cost.as_dict(stringify=False)  # Decimal values
string_dict = cost.as_dict(stringify=True)    # String values (legacy format)

Responses API

# Works with both APIs
resp = client.responses.create(
    model="gpt-4.1-mini",
    input=[{"role":"user","content":"Hi there!"}],
)

# Legacy: returns dict[str, str]
cost_dict = estimate_cost(resp)

# Typed: returns CostBreakdown dataclass
cost_obj = estimate_cost_typed(resp)

Public API

Strongly-Typed API (Recommended)

Legacy String API (Backward Compatible)

Common Functions

When to Use Which API

Use the typed API (estimate_cost_typed) when:

Use the legacy API (estimate_cost) when:

Financial Calculation Example

from openai_cost_calculator import estimate_cost_typed
from decimal import Decimal

# Calculate precise costs across multiple requests
total_cost = Decimal('0')
for response in responses:
    cost = estimate_cost_typed(response)
    total_cost += cost.total_cost
    
print(f"Total spend: ${total_cost}")  # Accurate Decimal arithmetic

Troubleshooting & FAQs

🎉 A brand-new model just launched – my code raises "pricing not found"

  1. Head to the pricing CSV on GitHub.
  2. If the new model/date is missing  →  open an issue or email the maintainer (orkunkinay@sabanciuniv.edu).
  3. If the new row is already there  →  call refresh_pricing() once — the 24-hour cache is then refreshed for every worker.

🔄 Streaming chunks

Just pass the generator returned by client.chat.completions.create(..., stream=True, stream_options={"include_usage": True}) straight into estimate_cost or estimate_cost_typed. The helper silently walks the stream and uses the last chunk that contains .usage.

⚠️ "cached_tokens = 0" even though I know some were cached

Make sure you request include_usage_details=True (classic) or stream_options={"include_usage": True} (streaming). Without it the API omits the cached-token breakdown.

🏷️ Azure OpenAI deployment IDs vs. model names

Azure responses still carry the original model string (chunk.model) — the calculator ignores the deployment name, so you're covered.

⏱️ Performance concerns

The only network call is the pricing CSV (max once every 24 h). All cost maths are pure Python and nanosecond-level.

Contributing & License

PRs for additional edge-cases, new pricing formats or SDK changes are welcome!
MIT License © 2025 Orkun Kınay & Murat Barkın Kınay