Methodology
What apilong measures, where every number comes from, and how you can recompute each ranking yourself. This page is generated from the same daily feed files that power the rankings, so its numbers always match the live site.
Where the data comes from
Every day an automated collector takes a snapshot of each provider's published prices. Only two kinds of sources are used, and every row in the feed is labeled with which one:
- Official API — the provider's own public pricing/model API response. Today: 1,106 rows.
- Official site — figures read from the provider's public pricing page. Today: 239 rows.
We do not collect from third-party blogs, scraped copies, or user reports. Each snapshot
is stored with a capture timestamp (captured_at) and the exact source URL
(source) in prices.json, so any figure can be
traced back to the page it came from. In total this edition covers 59 providers,
plus 8 open-data sources tracked separately in open_data.json.
How prices are compared
Prices are only ever compared within the same billing unit. Rows are grouped by their
pricing.unit (per 1M tokens, per GB, per hour, per month…), and a ranking is
formed inside one unit group only — we never convert between units.
- For token-priced models the comparable number is the floor price: the lower of input and output, normalized to $/1M tokens (per-token API responses are multiplied by 1,000,000).
- Where an aggregator resells a model that its maker also sells directly, the listing shows the official maker price and the percentage difference between platform and maker (negative = cheaper than the maker).
-
Free listings are shown as
$0or as the provider's published free-tier allowance — never mixed into paid rankings.
How probes work
A scheduled probe hits each monitored endpoint once per day and records the HTTP status code and response latency. The probe set currently covers 20 endpoints across 19 providers. Two metrics are derived per endpoint:
- p50 latency — median response time in milliseconds.
- Availability — share of probes returning a 2xx status.
Raw results are in measurements.json. Latency is measured at the provider endpoint level, not per individual model.
Where Elo ratings come from
The Score column is not our own opinion: it is a daily snapshot of the public arena.ai text leaderboard (390 models in the current feed). When several variants of one model appear on the arena, the best variant's rating is shown. Models absent from the arena show “—” rather than a made-up score.
How popularity (“heat”) is computed
Heat is a 0–100 percentile score combining three independent public usage signals:
- OpenRouter — 7-day prompt + completion token volume · weight 50%
- HuggingFace — trending score · weight 30%
- Replicate — run count · weight 20%
Each signal is percentile-ranked within its modality board (LLM text, image, video, audio, embedding), so modalities never mix. A model missing one signal is scored on the remaining signals with weights renormalized — a gap never zeroes a score. Current feed: 703 families in heat.json.
How to backtest us
Every ranking on this site is recomputable from the raw feeds — no hidden state:
- Download the feed(s): prices.json, measurements.json, heat.json, elo.json, open_data.json.
- Pick any ranking on the site (cheapest, fastest, most reliable, overall, heat).
- Apply the formula described in the matching section above to the feed rows.
- Your output should match the site to the displayed precision.
Agents can start from llms.txt, which indexes all feeds with row counts, or the RFC-9727-style directory api-catalog.json.
Honesty policy
-
If a source publishes prices only in a form we cannot reliably parse, the source is
recorded as such (
NO_MACHINE_READABLE) and shown without a price — we never type a number in by hand. - Missing values display as “—”. We do not interpolate, extrapolate or estimate prices.
- Rankings are computed mechanically from the feeds before any commercial consideration; no provider can pay to change a rank or score.
- When a source cannot be reached on a given day, its rows simply keep the last successful snapshot timestamp instead of pretending to be fresh.