Methodology

By J. Wren · Last reviewed 2026-10-13

This page describes how the numbers on LLM Calc are produced and checked: where the rates come from, what the scheduled job does and refuses to do, how the measurements in the guides are made, and what the site leaves out. Each statement describes what the site's sync and build scripts do today. The scripts behind the guides' measurements are public and linked below.

Where the rates come from

Rates come from the LiteLLM community pricing database, a public JSON file maintained on GitHub that tracks vendor pricing pages. It is not an official feed from Anthropic, OpenAI or Google. The vendors publish no pricing API, and their pricing pages are rendered in ways that make automated reading unreliable, so the site reads this dataset instead of scraping them.

At the time of writing the sync covers 13 chat models and 3 embedding models from those three vendors. The list is chosen for coverage, not for any commercial relationship. Every pricing page prints the date of its last sync, names the source, and links to the vendor's official pricing page. If the two disagree, the vendor is right. The values behind the calculators are published as pricing.json.

The scheduled job and its checks

A scheduled job runs once a day at 06:17 Taiwan time (22:17 UTC). It downloads the dataset, extracts the tracked models, compares every rate with the values currently published, rewrites the generated parts of the pricing pages, rebuilds the sitemap, validates every page, and commits and deploys if anything changed. The date stamps on the pages move with each run, so a commit is made on most days; the commit message says whether any rate moved.

Figure 1 follows one run from the schedule to the deploy, including the points where it stops.

Figure 1 — the daily pricing sync, step by step (the dashed red path is what happens when a step fails)

How the daily pricing sync works, from schedule to deploy Flow chart of the scheduled job. 1: a GitHub Actions schedule starts it at 22:17 UTC daily. 2: it downloads the LiteLLM community price file. 3: it picks the 13 chat and 3 embedding models listed in the script. 4: it compares the rates with the published ones and stops if a rate moved more than 50 percent or a context window more than 20 percent. 5: it writes pricing.json, pricing-history.json and the generated sections of seven pages. 6: it rebuilds the sitemap and checks every page. 7: it commits, pushes and deploys only if something changed. If any of steps 2 to 6 fails, nothing is committed or deployed and the workflow opens or updates a GitHub issue. 1 Schedule starts the job GitHub Actions cron 17 22 * * * (22:17 UTC = 06:17 Taiwan), or a manual run 2 Download the price file LiteLLM community database (JSON on GitHub), 60-second timeout 3 Pick the tracked models 13 chat + 3 embedding models named in the script; one missing = stop 4 Compare with the published rates Rate moved over 50% or context over 20% = stop; else log each change by date 5 Write the data and the generated page sections pricing.json, pricing-history.json, generated blocks in 7 pages 6 Rebuild the sitemap, then check every page build_sitemap.py, then check_pages.py; any failed check = stop 7 Commit and deploy only if something changed Message says whether rates moved; push; wrangler deploy to Cloudflare If any of steps 2 to 6 fails The run stops: nothing is committed or deployed, so the site keeps its previous numbers. A failure step opens an issue titled “Pricing sync is failing” (or comments on the open one), which emails the owner. No automatic retry: the next scheduled run tries again.

Step names follow the job's own workflow file (update-pricing.yml) and sync script (update_pricing.py); the model and page counts are those at the time of writing. Changes made by hand go through a separate deploy workflow, which runs the same page check before it deploys.

Before anything is written, the job refuses three kinds of input. An input or output rate that moved by more than 50% against the published value. A context window that moved by more than 20% (the bound is loose on purpose: upstream sometimes flips between 1,000,000 and 1,048,576, both marketed as 1M, and that must pass). A tracked model, or one of its fields, that is missing upstream. In each case the job stops with an error and leaves the site on its previous numbers. A large price cut is therefore held back until someone has checked it against the vendor's own page and updated the data by hand.

Page structure is validated on every daily run and on every deploy: required head and social tags, a unique canonical URL and title for each page, balanced markup, valid structured data, no leftover placeholder text and a minimum amount of text. A page that fails stops the deploy.

When a rate differs from the published one, the job adds a dated entry to pricing-history.json, which feeds the pricing change log. Only movements seen after tracking began on 2026-07-25 are recorded. Nothing before that date is inferred.

One failure that went unnoticed

Between 2026-07-30 and 2026-08-03 the job failed on five consecutive scheduled runs, one for each night in that stretch. GPT-5.6 Luna's rates had dropped by 80% (input from $1 to $0.20, output from $6 to $1.20), which is past the 50% limit, so the job refused to publish. That was the intended behavior, but nobody was told. On 2026-08-04 the cut was checked by hand against OpenAI's pricing page, confirmed and published manually, with the four rate entries for GPT-5.6 Terra and GPT-5.6 Luna dated 2026-07-30, the day the cut was announced. The same day a step was added to the workflow: when a run fails, it opens an issue titled "Pricing sync is failing" in the site's repository, or adds a comment to it if it is already open, so the owner gets a notification email. Two manual runs on 2026-08-04 also failed, so GitHub Actions lists seven failed runs of this workflow between 2026-07-25 and 2026-10-13 (counted from the run list on 2026-10-13); all seven fall in this stretch, and none has failed since.

The schedule is not perfectly regular either. The job is set to start at 22:17 UTC each day. From the first scheduled run on 2026-07-25 to the run recorded on 2026-10-13 (counted from the run list on 2026-10-13), GitHub Actions recorded exactly one scheduled run for each of the 80 daily slots from 2026-07-25 through 2026-10-12, and no slot went without a run. The runs often started late, though: the median delay was about two hours and the longest was nearly eight (the run for the 2026-08-27 slot started at 06:07 UTC on 2026-08-28). Because late runs cross midnight, four UTC calendar dates in that period (2026-08-06, 2026-08-26, 2026-09-07 and 2026-09-13) show no run and three (2026-08-07, 2026-09-05 and 2026-09-12) show two. "Once a day" describes the schedule, not a guarantee: GitHub does not promise on-time starts, so a run can arrive hours late.

How the measurements are made

A guide that reports computed figures links to the script and the output file it came from, so anyone can re-run it. The guide on whether four characters equal one token uses measure_chars_per_token.py. It counts tokens with OpenAI's tiktoken library (o200k_base and cl100k_base) over 50 short text samples: ten each of English prose, Traditional Chinese, Simplified Chinese, Python code and JSON. The samples were written for the measurement and are not copied from other sources. Output: measure_chars_per_token.results.json.

The RAG pipeline cost example uses rag_cost_example.py, which reads the site's own pricing.json and states every assumption as a constant at the top of the file; its output is in rag_cost_example.results.json. The Q3 price change article is derived from pricing-history.json and states the formula behind its dollar figures.

The limits are stated where they apply. The samples are few and short. The token-length script does not measure the Claude or Gemini tokenizers. The token counter uses OpenAI's actual tokenizer tables for GPT models and a four-characters-per-token estimate for Claude and Gemini.

What "Last reviewed" means

It is the date a page's text or numbers were last revised by hand. Pages are not re-dated unless something on them changed, and no script sets this date. Guides also show a "Published" date for the first release. The generated parts of the pricing pages carry their own sync date next to the rate table; that date follows the daily job, while "Last reviewed" does not.

Corrections

If a figure looks wrong, email hello@getllmcalc.com with the page, the values entered, the result shown and what you expected (the contact page has the details). A confirmed error is fixed on the page. On an article, the correction is noted in an update section with its date instead of being rewritten silently. A disagreement with a vendor's own page is always settled in the vendor's favor.

What is not modelled

The calculators work from list prices and the token counts you supply. They do not model prompt caching, batch endpoints or committed-use discounts, taxes, or your actual traffic. They say nothing about quality: a cheaper model is not claimed to be an equal one. Rates from before 2026-07-25 and models outside the tracked list are not in the change log. The worked examples on the pricing pages use one fixed workload (1,500 input and 300 output tokens per request, 50,000 requests a month) so that figures are comparable between pages. It is a reference point, not a recommendation. Token counts for Claude and Gemini are estimates.

More on the site and its author is on the about page. The full list of rate movements is in the pricing change log.