---
name: ai-tool-pricing-check
description: Verify a list of SaaS or AI tool prices (plans, monthly price, seats, free tier, usage credits) against each vendor's official pricing page and output a diff table of what changed, with a source URL and check date for every value. Handles JS-rendered and bot-blocked pricing pages with fallbacks and never guesses a number. Use when asked to check, audit, refresh or update prices in a comparison table, directory, spreadsheet, JSON data file or docs.
---

# AI tool pricing check

Prices of AI tools change monthly (new tiers, credit systems, renames, shutdowns). This skill re-verifies every price in your data against the **official** source and reports a sourced diff — and, if asked, updates the data file.

Real case: getaicodingagent.com tracks 44 AI coding tools in a public `tools.json`; this workflow found e.g. GitHub Copilot's Pro+ at $39 and Max at $100 (with $70 / $200 of included credits) on github.com/features/copilot/plans, Windsurf's rename to Devin Desktop and Amazon Q Developer's end of sign-ups. Docs: https://getaicodingagent.com/skills/ai-tool-pricing-check/

## Inputs

- The **price list**: a JSON/CSV/YAML file, a markdown table, or a list in chat. Identify for each tool: name, plans, stated prices, and the pricing URL if present.
- **Mode**: report-only (default) or update the file (only if the user asked).

## Step 1 — Normalize the current data

Build a working table with one row per (tool, plan): `tool | plan | current_value | billing (monthly/annual/per-user/usage) | pricing_url`. If a pricing URL is missing, find the official one (vendor domain only, usually `/pricing`, `/plans` or docs "Plans & billing").

## Step 2 — Fetch each official pricing page

Save this helper to `/tmp/pagetext.py` and run `python3 /tmp/pagetext.py <pricing-url>`. It prints the visible text around every currency amount (pass a regex as 2nd argument to search for something else, e.g. `'Free|Hobby|credits'`).

```python
#!/usr/bin/env python3
"""pagetext.py <url> [regex] -> visible text around currency amounts on a page."""
import sys, re, html, urllib.request, gzip
url = sys.argv[1]; pat = re.compile(sys.argv[2] if len(sys.argv) > 2 else r"(?<![\w\"$])(?:US\$|\$|€|£)\s?\d[\d,.]*(?:\s?(?:/|per)\s?(?:mo|month|user|seat|yr|year))?", re.I)
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36", "Accept-Encoding": "gzip", "Accept-Language": "en-US,en"})
try:
    r = urllib.request.urlopen(req, timeout=30); raw = r.read()
    if r.headers.get("Content-Encoding") == "gzip": raw = gzip.decompress(raw)
    status = r.status
except Exception as ex:
    print(f"FETCH_FAILED {url} {ex}"); sys.exit(2)
s = raw.decode("utf-8", "replace")
s = re.sub(r"<(script|style|noscript|svg)\b.*?</\1>", " ", s, flags=re.S | re.I)
t = re.sub(r"\s+", " ", html.unescape(re.sub(r"<[^>]+>", " ", s)))
hits = [(m.start(), m.group(0)) for m in pat.finditer(t)]
print(f"STATUS {status} chars={len(t)} matches={len(hits)} url={url}")
if len(t) < 1500 or not hits: print("HINT: page likely JS-rendered or bot-blocked; use a browser tool, the vendor docs/help center, or a web search restricted to the vendor domain.")
seen = set()
for i, h in hits:
    ctx = t[max(0, i - 120): i + 120].strip()
    k = ctx[100:160]
    if k in seen: continue
    seen.add(k); print("…" + ctx + "…")
```

Fallback order when the helper shows no prices (JS-rendered page, Cloudflare challenge, tabs that hide prices):
1. A real browser tool if you have one (open the page, click monthly/annual and plan tabs, read the rendered text).
2. The vendor's own docs/help center/changelog (e.g. "Plans and billing", "Pricing FAQ") — still official.
3. A web search restricted to the vendor domain (`site:vendor.com pricing`), then open the result.
4. If still unverified: keep the old value, mark it `UNVERIFIED`, and say why. **Never fill a price from memory, a reseller, a review site or a search snippet.**

Watch for traps: annual-billed prices shown as monthly ("$16/mo billed annually" vs "$20 monthly"), per-user vs flat, regional currency, "starting at", promo/introductory prices, usage credits included in a plan (record them: "Pro $10/mo incl. $15 credits"), and plans that exist but say "Contact sales".

## Step 3 — Compare and classify

For each row assign one status:
- `SAME` — official value matches.
- `CHANGED` — price, included usage, or plan name differs (show old → new).
- `NEW_PLAN` / `REMOVED_PLAN` — tier added or gone.
- `STATUS_CHANGE` — product renamed, acquired, sunset, sign-ups closed (check the vendor blog/changelog when the pricing page redirects or 404s).
- `UNVERIFIED` — could not read an official source (with reason).

## Step 4 — Output

```
## Pricing check — <n> tools, <date>
Changed: <a> · New/removed plans: <b> · Status changes: <c> · Unverified: <d>

| Tool | Plan | Old | Official now | Status | Source (checked <date>) |
|---|---|---|---|---|---|
| GitHub Copilot | Pro+ | $39/mo | $39/mo (incl. $70 credits) | SAME | https://github.com/features/copilot/plans |
…
### Notes
- <billing caveats, promos, anything a reader would get wrong>
### Unverified (needs a human or browser)
- <tool>: <why>
```

Sort CHANGED and STATUS_CHANGE rows first.

## Step 5 — Update the data (only if asked)

- Edit only the changed fields; keep the file's schema and formatting. Set a `last_verified` (or equivalent) date per tool you actually verified — not for UNVERIFIED ones.
- Add the source URL next to each changed value if the schema allows it.
- Re-run the project's build/tests, and show the diff (`git diff --stat` and the changed lines).
- For a public site, consider a short changelog/news entry per significant change ("<Tool> raised Pro to $X on <date>", linked to the source) — price-change pages attract searches.

## Guardrails

Official sources only for values; quote the exact plan names the vendor uses; date every check; when two official pages disagree, report both and flag it instead of picking one.
