mrkeyoor.com_
Wed 05 Aug 19:58 UTC
PyPIAI / MLupdated 05 Aug 2026

genai-prices

genai-prices is a package plus community-maintained price database from the Pydantic team for estimating what an LLM API call costs. You hand it token counts (or a raw provider response via extract_usage) and a model reference, and it matches the right provider and model, applies historic price changes, tiered pricing for long contexts, and even off-peak rates, then returns input, output, and total price. The price data ships bundled as JSON, can be auto-refreshed hourly from GitHub, and covers dozens of providers from OpenAI and Anthropic to OpenRouter's full catalog. A CLI is included for quick comparisons.

Verdict

The most carefully engineered open price dataset available, backed by the Pydantic team and updated constantly, but it is young at 0.1.x and self-described as an estimate. Use it for dashboards and comparisons, not invoices.

API stability2/5Version 0.1.1 with no stability promises; the project has already migrated its data format from v1 to v2 and frozen the old files, so expect interface movement.
Docs3/5The two READMEs cover installation, calc_price, extract_usage, UpdatePrices, and the CLI well, but there is no rendered API reference; the maintainers explicitly point you at the source code.
Maintenance5/5Extremely active: pushed the day this guide was written, price data updates land continuously from maintainers and community PRs, and it sits inside the Pydantic organization.
Ecosystem3/5Feeds Pydantic AI and Logfire and has a JS/TS twin package, plus the raw JSON is usable from any language, but third-party adoption outside the Pydantic stack is still young.

Use it if

  • You want a cost column in your own observability dashboard or usage accounting across many providers without maintaining a price table
  • You need to parse heterogeneous provider responses: extract_usage normalizes OpenAI, Anthropic, and other payloads including cache token fields
  • You compare model costs in scripts or CI, or from the terminal with the genai-prices CLI
  • You already use the Pydantic stack (Pydantic AI, Logfire), which uses this same data
Skip it if

Setup reality

pip install genai-prices (or uv add) is pure Python and quick; the rich CLI output needs the [cli] extra. The real work is data freshness: bundled prices are a snapshot from release day, and staying current means opting into UpdatePrices, which downloads roughly 51KB from GitHub raw hourly, allows only one running instance, and needs outbound network access that locked-down deployments may not have. Model matching is deliberately fuzzy, so when a number looks wrong, check which model it actually matched before trusting the price.

Patterns

Price a call from token countscalc-price-basic

from genai_prices import Usage, calc_price

price_data = calc_price(
    Usage(input_tokens=1000, output_tokens=100),
    model_ref='gpt-4o',
    provider_id='openai',
)
print(f"Total: ${price_data.total_price} (input: ${price_data.input_price}, output: ${price_data.output_price})")

provider_id is optional but recommended; without it the fuzzy matcher guesses the provider from the model name.

Extract usage from an Anthropic responseextract-usage-anthropic

from genai_prices import extract_usage

response_data = {
    'model': 'claude-sonnet-4-20250514',
    'usage': {
        'input_tokens': 504,
        'cache_creation_input_tokens': 123,
        'cache_read_input_tokens': 0,
        'output_tokens': 97,
    },
}
extracted = extract_usage(response_data, provider_id='anthropic')
print(extracted.calc_price().total_price)

extract_usage understands cache creation and cache read token fields, which naive per-token math gets wrong.

Extract usage from OpenAI, picking the API flavorextract-usage-openai-flavor

from genai_prices import extract_usage

response_data = {
    'model': 'gpt-5',
    'usage': {'prompt_tokens': 100, 'completion_tokens': 200},
}
extracted = extract_usage(response_data, provider_id='openai', api_flavor='chat')
print(extracted.calc_price().total_price)

OpenAI has two response shapes (chat completions vs responses API); api_flavor tells the parser which field names to expect.

Keep prices fresh with UpdatePrices as a context managerauto-update-prices

from genai_prices import UpdatePrices, Usage, calc_price

with UpdatePrices() as update_prices:
    update_prices.wait()  # block until the first download completes
    p = calc_price(Usage(input_tokens=123, output_tokens=456), 'gpt-5')
    print(p)

Opt-in by design: it fetches data.json from GitHub raw immediately, then hourly. Only one UpdatePrices instance may run at a time.

Start and stop price updates in a long-running serviceupdate-prices-long-running

from genai_prices import UpdatePrices

update_prices = UpdatePrices()
update_prices.start(wait=True)

# ... serve requests, calc_price now uses fresh data ...

update_prices.stop()

start(wait=True) blocks until the first refresh so early requests do not use stale bundled data. Call stop() on shutdown to end the background thread.

Wait for fresh prices anywhere in the codebasewait-for-updated-prices

from genai_prices import wait_prices_updated_sync

wait_prices_updated_sync()
# prices are now refreshed; safe to calculate

Useful when the UpdatePrices instance lives in another module. An async variant, wait_prices_updated_async, exists for async apps.

Compare model costs from the terminalcli-calculate-prices

uvx genai-prices calc --input-tokens 100000 --output-tokens 3000 o1 o3 claude-opus-4

uvx runs it without installing. If installed via pip, you need the [cli] extra for rich output; add --plain for script-friendly text.

List known providers and modelscli-list-models

uvx genai-prices list

Handy for finding the exact model_ref string the matcher expects when your provider uses nonstandard IDs.

Read the full price breakdownprice-breakdown-fields

from genai_prices import Usage, calc_price

p = calc_price(
    Usage(input_tokens=50000, output_tokens=2000),
    model_ref='claude-sonnet-4',
    provider_id='anthropic',
)
print(p.input_price, p.output_price, p.total_price)
print(p.model.name, p.provider.name)

The result also exposes which model and provider were matched; log these, since a fuzzy mismatch is the usual cause of surprising totals.

Consume the raw price data without the packageuse-raw-data-json

import httpx

url = 'https://raw.githubusercontent.com/pydantic/genai-prices/refs/heads/main/prices/new_data/v2/data.json'
data = httpx.get(url).json()
print(len(data['providers']), 'providers')

The v2 JSON files are published with a JSON Schema and free to use from any language; the frozen v1 files no longer receive updates.

Alternatives

PackageRegistryPick it when
litellmPyPIYou want cost tracking built into the same layer that routes your LLM calls, via completion_cost and its bundled price map.
tokencostPyPIYou want a smaller, simpler prompt-and-completion cost calculator and do not need tiered or historic pricing.
tiktokenPyPIYou need to count tokens before making a call rather than price usage after it.