the biggest auto-updated genai pricing index: complete dated price history per model, peak/off-peak rates
detectors scrape provider pricing pages and the openrouter api hourly. every observed change lands as a dated row, reviewed by a human before it merges
| metric | value |
|---|---|
| models tracked | 1,675 |
| sources | 30 |
| dated rows | 4,092 |
| canonical models | 202 |
| history | since 2023-03-01 (1,351 days) |
one repo holds the observations and one generated view of them:
| file | contents |
|---|---|
data/history/<source>.ndjson |
one dated row per observed price change, plus a removal row per delisted model, appended forever, one file per source |
dist branch |
the served views, rebuilt per publish: index.json (current price of every model), flat-v3.json (one flat entry per model with name, vendor, modality on non-text rows and its intervals validity chain; flat-v2.json stays the chat-only old shape), history.ndjson, per-source index/flat/history copies, the catalog, and index.html — a static pricing page: sortable table, search, cheapest-first comparison, token calculator with a day picker, a per-model detail card with its price-history chart, a page-wide peak-time toggle, no build step |
data/schema/row.v4.json |
the json-schema a row is checked against, and the contract a consumer can read |
a row:
{"schema":4,"source":"deepseek","model_id":"deepseek-v4-pro","observed_at":"2026-08-30","effective_at":"2026-08-23","rates":{"input":0.66,"output":1.98,"cache_read":0.022},"overrides":[{"when":{"days":["monday","tuesday","wednesday","thursday","friday"],"window":[100,400],"timezone":"Asia/Shanghai"},"rates":{"input":1.32,"output":3.96,"cache_read":0.044}}],"limits":{"context":1048576,"output":393216},"provenance":{"url":"https://api-docs.deepseek.com/quick_start/pricing"}}a removal row (one per source/model ever; the index stamps the entry removed_at until the model reappears):
{"source":"deepseek","model_id":"deepseek-legacy","observed_at":"2026-08-26","removed":true}git history is the changelog. every price a model ever had stays in the history file.
| step | what happens |
|---|---|
| detect | each provider's page is parsed for its current model list (no api keys, all sources are static pages) |
| diff | new ids vs the store + open PRs |
| scrape | input/output + cache-tier prices per token from the provider's pricing page (deepseek's peak/off-peak schedule included); missing price = retry next run |
| store | a row appends only when the price differs from the last stored row for that model |
| delist | a stored model absent from its source twice, both observations merged, gets a removal row and a Mark ... delisted draft PR |
| pr | one draft PR per source per run, removal and price rows mixed, no cap; the ci claude pass reviews and the workflow merges what it verifies, everything else waits on a human |
the openrouter source stores the full keyless model list the same way. the first run with an empty store opens one seed PR with the full snapshot.
| provider | detection + pricing source |
|---|---|
| deepseek | api-docs.deepseek.com pricing page |
| zai | docs.z.ai pricing page |
| moonshot | platform.kimi.ai models + pricing pages |
| minimax | platform.minimax.io models + pricing pages |
| xai | docs.x.ai models blob |
| mistral | docs.mistral.ai model cards + pricing |
| perplexity | docs.perplexity.ai pricing |
| together | together.ai pricing |
| novita | novita.ai pricing |
| cohere | cohere.com pricing |
| ai.google.dev gemini pricing docs | |
| avian | avian.io pricing |
| fireworks | docs.fireworks.ai serverless pricing |
| deepinfra | deepinfra.com pricing |
| cloudflare | developers.cloudflare.com workers-ai pricing |
| watsonx | ibm.com watsonx.ai pricing |
| baseten | baseten.co pricing |
| digitalocean | docs.digitalocean.com inference pricing |
| sambanova | cloud.sambanova.ai pricing |
| publicai | platform.publicai.co models |
| ai21 | ai21.com pricing |
| openai | platform.openai.com docs pricing |
| anthropic | platform.claude.com docs pricing markdown twin |
| cerebras | api.cerebras.ai public models api |
| dashscope | alibabacloud model-studio intl pricing + CN model list |
| groq | console.groq.com models markdown twin |
| databricks | databricks.com foundation model serving pricing (DBU) |
| amazon | aws bedrock bulk price-list api |
| openrouter | openrouter.ai public models api (all models) |
dormant, commented out in providers.toml: volcengine (CNY-only).
uv sync --frozen
uv run ai-pricelogGH_TOKEN (a PAT with repo scope) is what opens the draft PRs. the scheduled GitHub Actions run carries it as a secret. schedule: hourly (plus a weekly moonshot smoke), or workflow_dispatch.
providers.toml holds one section per provider:
[deepseek]
detector = "deepseek_page"
detector_url = "https://api-docs.deepseek.com/quick_start/pricing"
scraper = "deepseek_page"
scraper_url = "https://api-docs.deepseek.com/quick_start/pricing"detector/scraper name modules under ai_pricelog.{detectors,scrapers}; adding a provider is a config section plus a module pair.
where do i find the current price of a model?
https://uwuclxdy.github.io/ai-pricelog/index.json under sources, keyed by provider and model id (GitHub Pages over the dist branch: application/json, cache-control: max-age=600, cross-origin). one provider alone: .../ai-pricelog/index/<source>.json. a flat, consumer-friendly twin: .../ai-pricelog/flat-v3.json, one entry per model with display name and vendor resolved through the catalog, plus its intervals chain so pricing any past day is a containment test (.../ai-pricelog/flat/<source>.json per provider); the old flat-v2.json stays chat-only, so a row carrying modality never enters it. or read it as a page: the same host's root, the same data as a sortable, searchable table with a comparison, a token-count calculator and a per-model card that charts how its price moved, plus a page-wide peak-time toggle. the raw dist-branch urls (raw.githubusercontent.com/uwuclxdy/ai-pricelog/dist/...) serve identical bytes but no content type, no cache headers and no stable host.
how do i see every price a model ever had?
rg 'deepseek-v4-pro' data/history/deepseek.ndjsoneach matching row is one observed change.
what does a peak/off-peak model look like?
deepseek rows carry overrides: the base rates are the off-peak default, and one entry per peak window overrides them with the peak rates on its when.days (weekdays, matching the beijing-time weekend rule; effective_at stamps the rule's date). an absent axis in an override inherits the base rate.
| ai-pricelog | pydantic/genai-prices | |
|---|---|---|
| what | dated price history repo | generated pricing dataset for python/js packages |
| updates | automation + human review per change | human PRs into provider ymls |
| history | every observed change since the first sighting | dated conditional entries where contributors add them |
uv run ruff check
uv run ruff format --check
uv run pytest -qtests pin live-page fixtures per provider; nothing hits the network in the suite.
MIT