← back to gallery

Tier Drift

Silent rate-limit, quota, and pricing drift across every major AI subscription

aisubscriptionspricingrate-limitstransparencywayback
Open product ↗

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:

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:

  1. Fetch the live page.
  2. Normalise to plain text via cheerio, hash with SHA-256.
  3. If the digest changed since last time, snapshot + diff the new text against
  4. the previous snapshot.
  5. Classify the diff (price | quota | model-access | rate-limit | wording)
  6. and score severity (major | minor | cosmetic).
  7. Extract structured quotas with deterministic regex.
  8. Optionally summarise the diff in one sentence with Claude Haiku via
  9. 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 marked
status: stale with last_error and a visible last_refresh_at. We never
fabricate.

Stack

Endpoints

All endpoints are public (no auth). Access-Control-Allow-Origin: on every
GET /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.