tier-drift
Live tracker for silent rate-limit, quota, model-access, and pricing changes
on consumer AI subscriptions — Anthropic Claude (Pro, Max), OpenAI ChatGPT
(Plus, Pro, Business, Enterprise), Cursor (Pro, Pro+, Ultra), GitHub Copilot
(Pro, Pro+, Business, Enterprise), Google Gemini (Advanced, AI Pro, AI Ultra),
Perplexity (Pro, Max), Replit (Core, Teams), xAI Grok (SuperGrok, Heavy).
Wayback Machine + live-fetch powered. Public, no auth, no mocks.
Why
The May 2026 news cycle is dominated by AI subscriptions silently changing
terms at the same price:
- GitHub Copilot moving to token-based billing on June 1, 2026.
- Anthropic removing Claude Code from the $20 Pro plan, then doubling Claude
- Code's 5-hour limits two weeks later — all without a single changelog entry.
- ChatGPT Plus silently downgrading capped users to "mini" models.
- OpenAI Codex credits flipping to token-based pricing.
There is no neutral, longitudinal record of these changes — provider blog
posts get backdated, pricing pages get edited in place, help articles get
rewritten. tier-drift is the missing record.
How
Every 6 hours, for each tracked URL:
- Fetch the live page.
- Normalise to plain text via cheerio, hash with SHA-256.
- If the digest changed since last time, snapshot + diff the new text against
- the previous snapshot.
- Classify the diff (
price | quota | model-access | rate-limit | wording) - and score severity (
major | minor | cosmetic). - Extract structured quotas with deterministic regex.
- Optionally summarise the diff in one sentence with Claude Haiku via
- OpenRouter (skipped if no key — UI still works).
Once a week (Sundays), we additionally walk the Wayback Machine CDX index for
each tracked URL back to Jan 2024 and backfill any historical snapshots we
don't yet have.
Real data sources
Every numeric value rendered in the UI comes from one of these endpoints. No
mocks. No seed arrays. No Math.random() outside cron jitter.
| Source | URL | Used for | Cadence |
|---|---|---|---|
| Wayback Machine CDX API | http://web.archive.org/cdx/search/cdx?url=<URL>&output=json&collapse=digest | List dedup'd historical snapshots | Weekly backfill |
| Wayback raw snapshot | https://web.archive.org/web/<ts>id_/<URL> | Pull archived HTML | On-demand per snapshot |
| Anthropic pricing | https://www.anthropic.com/pricing | Plans, limits | Every 6h |
| Anthropic Pro-usage doc | https://support.anthropic.com/en/articles/8324991-about-claude-pro-usage | Usage limits | Every 6h |
| Anthropic Claude Code doc | https://support.anthropic.com/en/articles/11145838-using-claude-code-with-your-pro-or-max-plan | Code-specific limits | Every 6h |
| OpenAI pricing | https://openai.com/chatgpt/pricing/ | Plans, prices | Every 6h |
| OpenAI Plus/Pro limits | https://help.openai.com/en/articles/9824962-chatgpt-plus-pro-limits | Message caps | Every 6h |
| OpenAI Codex limits | https://help.openai.com/en/articles/9275245-codex-limits | Codex token quotas | Every 6h |
| Cursor pricing | https://www.cursor.com/pricing | Plans, prices | Every 6h |
| Cursor docs | https://docs.cursor.com/account/plans-and-usage | Usage policies | Every 6h |
| GitHub Copilot plans | https://github.com/features/copilot/plans | Plans, prices | Every 6h |
| GitHub Copilot billing | https://docs.github.com/en/copilot/concepts/billing/about-billing-for-copilot | Billing terms | Every 6h |
| Gemini pricing | https://gemini.google.com/advanced | Plans, prices | Every 6h |
| Gemini help limits | https://support.google.com/gemini/answer/14517446 | Quotas | Every 6h |
| Perplexity pricing | https://www.perplexity.ai/hub/legal/pricing-of-plans | Plans | Every 6h |
| Perplexity help | https://www.perplexity.ai/help-center/en/articles/10354894-what-is-perplexity-pro | Quotas | Every 6h |
| Replit pricing | https://replit.com/pricing | Plans | Every 6h |
| Replit usage policies | https://docs.replit.com/legal-and-security/usage-policies | Limits | Every 6h |
| xAI pricing | https://x.ai/pricing | Plans, prices | Every 6h |
| OpenRouter Chat Completions | https://openrouter.ai/api/v1/chat/completions (optional) | One-sentence change summary | On each new change row |
If a source can't be fetched in a refresh window, the row is markedstatus: stale with last_error and a visible last_refresh_at. We never
fabricate.
Stack
- Node.js ≥ 18, Express 4
better-sqlite3in WAL modenode-cronfor periodic refresh (default7 /6)helmet+compressioncheeriofor HTML → text normalisation- Vanilla JS SPA — no React/Vue/Tailwind.
Endpoints
All endpoints are public (no auth). Access-Control-Allow-Origin: on everyGET /api/ so the badge embeds anywhere.
| Endpoint | What it returns |
|---|---|
| GET /tier-drift/health | {ok, version, providers_tracked, urls_tracked, snapshots_indexed, changes_recorded, last_refresh_at, last_refresh_status} |
| GET /tier-drift/api/providers | All providers with their plans and tracked URLs |
| GET /tier-drift/api/plans?provider= | Plan list |
| GET /tier-drift/api/changes?limit=&severity=&category=&provider=&since= | Recent change feed |
| GET /tier-drift/api/changes/:id | Full change with diff snippets and Wayback URLs |
| GET /tier-drift/api/providers/:slug | Provider detail (plans, URLs, recent snapshots, timeline) |
| GET /tier-drift/api/stability | Plan stability ranking (90d) |
| GET /tier-drift/api/stats | Counts + worker state |
| GET /tier-drift/api/badge?plan=<slug> | SVG badge for embedding |
| POST /tier-drift/api/refresh | Manual refresh trigger (idempotent if in-flight) |
Run
cp .env.example .env # fill in OPENROUTER_API_KEY if you want LLM summaries
npm install
npm start # listens on :4787 by default
Then visit http://localhost:4787/tier-drift/.
The first refresh kicks 5 seconds after boot, after which the dashboard
populates. Subsequent refreshes run on REFRESH_CRON (default every 6h on
the :07 minute of even hours).
License
MIT.