A library to estimate OpenAI API costs based on token usage.
Project description
openai_cost_calculator
A lightweight, user-friendly library to estimate USD costs for OpenAI and Azure OpenAI API responses.
Features
- Query-level cost estimation: calculates cost per user query individually, based on the actual tokens used — no guesswork, no aggregate billing needed.
- Dual-API support: works with
chat.completions.create()and the newresponses.create(). - Zero boilerplate: one import & one call:
estimate_cost(response). - Strongly-typed API: new typed functions return
CostBreakdowndataclass withDecimalprecision for accurate financial calculations. - Backward compatibility: legacy string-based API remains unchanged.
- Pricing auto-refresh: daily CSV pull with a helper
refresh_pricing(). - Edge-case aware: cached tokens, undated models, streaming generators, Azure deployments handled.
- Predictable output: legacy API returns strings formatted to 8 decimal places; typed API uses
Decimalfor precise arithmetic.
Note:
openai_cost_calculatorcomputes the exact USD cost for each individual user query,
based on token counts directly returned by OpenAI or Azure OpenAI.
It does not estimate based on model type or guessing — it uses precise usage data attached to each response.
Installation
pip install openai-cost-calculator
Note: Package name on PyPI uses dashes; import name is
openai_cost_calculator.
Quickstart
Basic Usage (Legacy String API)
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 Usage (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
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 with precise Decimal values
decimal_dict = cost.as_dict(stringify=False)
# Convert to legacy string format
string_dict = cost.as_dict(stringify=True)
Chat Completion API
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'}
Responses API
resp = client.responses.create(
model="gpt-4.1-mini",
input=[{"role":"user","content":"Hi there!"}],
)
print(estimate_cost(resp))
API Reference
Strongly-Typed API (Recommended)
from openai_cost_calculator import estimate_cost_typed, calculate_cost_typed, CostBreakdown
estimate_cost_typed(response) → CostBreakdown
- Accepts a ChatCompletion, streamed chunks, or Response object.
- Returns a
CostBreakdowndataclass withDecimalfields:prompt_cost_uncached: Decimalprompt_cost_cached: Decimalcompletion_cost: Decimaltotal_cost: Decimal
calculate_cost_typed(usage, rates) → CostBreakdown
- Lower-level function for direct cost calculation.
usage: dict withprompt_tokens,completion_tokens,cached_tokensrates: dict withinput_price,cached_input_price,output_price- Returns the same
CostBreakdowndataclass.
CostBreakdown dataclass
@dataclass(frozen=True, slots=True)
class CostBreakdown:
prompt_cost_uncached: Decimal
prompt_cost_cached: Decimal
completion_cost: Decimal
total_cost: Decimal
def as_dict(self, stringify: bool = True) -> Dict[str, str | Decimal]:
"""
Convert to dictionary.
- If stringify=True: return 8-decimal-place strings (legacy format)
- If stringify=False: return raw Decimal objects
"""
Legacy String API (Backward Compatibility)
from openai_cost_calculator import estimate_cost, refresh_pricing, CostEstimateError
estimate_cost(response) → dict[str, str]
- Accepts a ChatCompletion, streamed chunks, or Response object.
- Returns a dict with:
prompt_cost_uncached: strprompt_cost_cached: strcompletion_cost: strtotal_cost: str
Common Functions
refresh_pricing() → None
- Force-reload the remote pricing CSV (cache TTL is 24h).
CostEstimateError
- Unified exception for recoverable input, parsing, or pricing errors.
When to Use Which API
Use the Typed API (estimate_cost_typed) when:
- Building new applications
- Performing financial calculations requiring precision
- Working with accounting or billing systems
- Need to aggregate costs across multiple requests
- Want type safety and IDE support
Use the Legacy API (estimate_cost) when:
- Maintaining existing codebases
- Need string output for JSON serialization
- Working with systems expecting the original format
- Quick debugging or logging
Example: Financial Calculations
from openai_cost_calculator import estimate_cost_typed
from decimal import Decimal
# Calculate costs for multiple requests
total_cost = Decimal('0')
for response in responses:
cost = estimate_cost_typed(response)
total_cost += cost.total_cost
print(f"Total cost: ${total_cost}") # Precise Decimal arithmetic
Pricing Data
Pricing is loaded from a remote CSV at:
https://raw.githubusercontent.com/orkunkinay/openai_cost_calculator/refs/heads/main/data/gpt_pricing_data.csv
Cached for 24 hours by default; use refresh_pricing() to force an update immediately.
Troubleshooting
-
New model raises "pricing not found"
- Verify the model/date in the pricing CSV on GitHub.
- If missing, open an issue or email the maintainer.
- If present, call
refresh_pricing().
-
cached_tokens = 0even though some were cached- Ensure you request
include_usage_details=True(classic) orstream_options={"include_usage": True}(streaming).
- Ensure you request
Contributing
PRs for additional edge-cases, new pricing formats, or SDK changes are welcome!
License
MIT License © 2025 Orkun Kınay, Murat Barkın Kınay
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openai_cost_calculator-1.0.3.tar.gz.
File metadata
- Download URL: openai_cost_calculator-1.0.3.tar.gz
- Upload date:
- Size: 16.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d818205f69c0f841b045c363c8e166b0c19b71c4d79eba0ae1e2c47614b895f0
|
|
| MD5 |
fed476edf74e1474b8e2d1c9d829fc1d
|
|
| BLAKE2b-256 |
1598db7b75cf274c8f0b07aef557aa8093e3461266c087756742c261480c3622
|
File details
Details for the file openai_cost_calculator-1.0.3-py3-none-any.whl.
File metadata
- Download URL: openai_cost_calculator-1.0.3-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a773a101f8bd2195759f009a4485d72266bc587c37605868a2cb1e221b035c45
|
|
| MD5 |
3afd81036db688ab2c2f3e3999adf9ed
|
|
| BLAKE2b-256 |
c2cb1b9171731a175fae19ae68fd5d24c54884a5b0a9685262ac6c7e5c68f29a
|