genai-prices review
genai-prices 0.1.4 estimates the cost of inference calls from reported usage and a model reference. Its bundled database accounts for provider-specific model IDs, dated price changes, cache reads and writes, long-context tiers, and time-dependent rates. extract_usage can turn several provider response shapes into the library's Usage model, while calc_price returns the matched provider, model, and price breakdown. Version 0.1.4 accepts fractional usage such as audio seconds, adds GLM-5.3 prices for Z.AI and OpenRouter, and adds GPT-5.6 pricing for AWS Bedrock. The maintainers explicitly say these estimates are not guaranteed to match a bill.
genai-prices 0.1.4 installed in 0.6 seconds, occupied 11 MB, and imported in 0.63 seconds in our sandbox with 0 audit findings. Use it for estimates and comparisons where matched-model details are retained; do not use its self-described approximate data for invoices or bill reconciliation.
We installed it
| Install | ✓ · 0.6s | 12 packages on disk · 11 MB |
| Import | ✓ | import genai_prices in 0.63s · pure Python · py.typed · requires Python >=3.10 |
| Known vulns | 0 | (pip-audit) |
Answers from our run
Does genai-prices install cleanly?
Yes. In a fresh container with an empty cache, pip install genai-prices finished in 0.6s, leaving 12 packages and 11 MB on disk. pip-audit reported no known vulnerabilities.
What does genai-prices need to run?
Python >=3.10, and nothing compiled: it is pure Python. In our run import genai_prices succeeded in 0.63s, and the package ships py.typed for type checkers.
genai-prices or litellm: which should you use?
litellm: Use it when routing model calls and calculating their cost should happen in the same gateway layer. genai-prices 0.1.4 installed in 0.6 seconds, occupied 11 MB, and imported in 0.63 seconds in our sandbox with 0 audit findings.
When should you not use genai-prices?
The number will drive an invoice, customer credit, or financial reconciliation. The project warns that provider pricing cannot be processed with complete accuracy.
Use it if
- An internal dashboard needs comparable estimated LLM costs across several providers.
- Provider response payloads need normalization before cache, input, output, or duration rates can be applied.
- Historic or tiered prices matter when recalculating older usage records.
- Engineers want a CLI for quick model comparisons alongside a typed Python API.
- The number will drive an invoice, customer credit, or financial reconciliation. The project warns that provider pricing cannot be processed with complete accuracy.
- A 0.1.x API is too early for your compatibility policy. The project recently froze v1 price data and moved current clients to the v2 format.
- Production cannot use bundled release-day data and also cannot reach raw.githubusercontent.com. The opt-in updater depends on that host.
- Your LLM gateway already calculates costs from its own model map. LiteLLM can avoid maintaining two matching and pricing layers.
- You need token counts before a request. This library prices reported usage; tiktoken is the narrower choice for OpenAI-family tokenization.
Setup reality
We installed genai-prices 0.1.4 in 0.6 seconds in a fresh Python 3.12 container. Twelve packages used 11 MB on disk, and pip-audit found 0 known vulnerabilities. The pure-Python package has 5 direct dependencies, requires Python 3.10 or newer, and includes py.typed. import genai_prices completed successfully in 0.63 seconds.
The default install exposes the calculation API. Rich terminal tables and help need the cli extra, which adds pydantic-settings, Rich, and rich-argparse. No provider credentials are required because the package consumes usage records rather than calling model APIs. Pass provider_id whenever it is known; model matching can otherwise select a plausible model from another provider. Log the matched provider and model beside each estimate.
Bundled data stays at the package release snapshot. UpdatePrices is opt-in and downloads the v2 data file from GitHub immediately, then every hour. Only one updater may run in a process. start(wait=True) blocks until the first refresh, while the context-manager form needs an explicit wait() if initial requests must avoid bundled data. A locked-down service must allow raw.githubusercontent.com or accept stale prices until the next release.
Version 0.1.4 permits finite non-negative int, float, or Decimal usage values. Cache-read and cache-write tokens are subsets of total input_tokens, so their sum cannot exceed that total. Float arithmetic uses the shortest round-trippable decimal representation; use Decimal before values lose precision when fractional billing units matter. Decimal values also need custom handling before standard JSON serialization.
Patterns
Price input and output tokens calculate-token-price
from genai_prices import Usage, calc_price
price = calc_price(
Usage(input_tokens=1_000, output_tokens=100),
model_ref='gpt-4o',
provider_id='openai',
)
print(price.input_price, price.output_price, price.total_price)provider_id narrows model matching. Save price.provider and price.model with the total so a surprising match can be audited.
Include cache reads and writes price-cached-input
usage = Usage(
input_tokens=4_740,
cache_read_tokens=0,
cache_write_tokens=4_735,
output_tokens=255,
)
price = calc_price(usage, 'claude-sonnet-4-20250514', provider_id='anthropic')input_tokens is the full input count. Cache reads and writes are partitions of that total and cannot add up to more than it.
Preserve fractional duration with Decimal record-fractional-usage
from decimal import Decimal
from genai_prices import Usage
usage = Usage(audio_seconds=Decimal('0.1')) + Usage(audio_seconds=0.2)
assert usage.audio_seconds == Decimal('0.3')Version 0.1.4 preserves Decimal when any operand is Decimal. Standard json.dumps still needs a conversion rule for that value.
Parse an Anthropic response extract-anthropic-usage
from genai_prices import extract_usage
payload = {
'model': 'claude-sonnet-4-20250514',
'usage': {
'input_tokens': 504,
'cache_creation_input_tokens': 123,
'cache_read_input_tokens': 0,
'output_tokens': 97,
},
}
price = extract_usage(payload, provider_id='anthropic').calc_price()The extractor maps Anthropic's cache creation and cache read fields, which have rates distinct from uncached input.
Parse an OpenAI chat response extract-openai-chat-usage
payload = {
'model': 'gpt-5',
'usage': {'prompt_tokens': 100, 'completion_tokens': 200},
}
extracted = extract_usage(payload, provider_id='openai', api_flavor='chat')
print(extracted.calc_price().total_price)api_flavor='chat' selects chat-completions field names. The Responses API uses a different payload shape.
Refresh prices inside a context refresh-with-context
from genai_prices import UpdatePrices, Usage, calc_price
with UpdatePrices() as updater:
updater.wait()
price = calc_price(Usage(input_tokens=123, output_tokens=456), 'gpt-5')wait() blocks for the first GitHub download. Without it, early calculations can use the data bundled in version 0.1.4.
Run the updater for a service lifetime refresh-in-service
updater = UpdatePrices()
updater.start(wait=True)
try:
serve_requests()
finally:
updater.stop()Only one UpdatePrices instance may run in a process. stop() ends its background thread during shutdown.
Wait for a shared updater asynchronously await-price-refresh
from genai_prices import wait_prices_updated_async
await wait_prices_updated_async()
result = calculate_current_batch()This waits for the process-wide updater when the caller does not own its instance; some code still has to start UpdatePrices first.
Compare models from the shell compare-models-cli
uvx genai-prices calc --input-tokens 100000 --output-tokens 3000 o1 o3 claude-opus-4uvx supplies the command in an isolated environment. A local pip install needs genai-prices[cli] for Rich output.
Inspect known providers and models list-models-cli
uvx genai-prices list --plainUse the listed identifiers when fuzzy matching picks an unexpected provider or model. The plain flag avoids colored table output.
Store the selected price record audit-matched-model
price = calc_price(usage, model_ref=model_name, provider_id=provider)
record = {
'estimated_total': str(price.total_price),
'matched_provider': price.provider.name,
'matched_model': price.model.name,
}The returned match is part of the estimate. Persist it with usage so later price-data changes do not hide what was selected.
Read the current raw price database download-v2-data
import httpx
url = 'https://raw.githubusercontent.com/pydantic/genai-prices/refs/heads/main/prices/new_data/v2/data.json'
data = httpx.get(url, timeout=10).raise_for_status().json()The v2 file is current. The older prices/data.json files are frozen and no longer receive provider or model updates.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| litellm | PyPI | Use it when routing model calls and calculating their cost should happen in the same gateway layer. |
| tokencost | PyPI | Use it for a smaller prompt-and-completion calculator without this project's historic and fractional-unit model. |
| tiktoken | PyPI | Use it to count supported model tokens before a request instead of pricing provider-reported usage afterward. |
More ai / ml guides
openai · mcp · huggingface-hub · @modelcontextprotocol/sdk · scikit-learn · tiktoken · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

