What happened?
kagi usage fails hard on plans that don't include the AI-cost box (reproduced on Starter):
$ kagi usage
parse error: Kagi billing page did not contain the current AI cost and limit; the page layout may have changed
Root cause
parse_usage_html in src/usage.rs requires the label total ai cost this period (or ai usage (usd)) and returns a parse error when absent. But the AI-cost box is an Ultimate-plan feature. A Starter billing page (verified against /settings/billing server HTML, 2026-09-12, Norwegian locale) instead renders plain usage counters:
<span>Starter</span> …
<div class="billing_box_count_title">Søk</div>
<div class="billing_box_count_num">…3…/300</div>
<div class="billing_box_count_title">Assistant-interaksjoner</div>
<div class="billing_box_count_num"><span >8</span>/300</div>
<div class="billing_box_count_title">Saldo</div>
<div class="billing_box_count_num">$0.07</div>
<span>Neste fornyelse er <b>2026-09-19</b></span>
Two separate issues:
ai_cost is treated as mandatory, so every non-Ultimate account gets a hard parse error even though plan/balance/renewal data is present.
- Labels are matched in English only.
account balance / next renewal is never match localized pages (Saldo, Neste fornyelse er), so those fields come back empty on non-English accounts even when present.
Suggested fix
- Make
ai_cost: Option<AiCostUsage> and skip the field when the box is absent (JSON consumers already tolerate skip_serializing_if-style fields).
- Accept localized variants for the labels that have stable equivalents (or, better long-term, parse the
billing_box_count_* structure instead of label text).
I have implemented this locally (optional ai_cost + saldo/neste fornyelse er fallbacks) and verified E2E on a Norwegian-locale Starter account:
{
"plan": "Starter",
"ai_cost": null,
"account_balance_usd": 0.07,
"next_renewal": "2026-09-19",
"daily_usage": []
}
All 215 unit tests pass (one test updated: the "missing cost pair errors" test now asserts successful parse with ai_cost: None). Happy to open a PR.
Environment
- kagi-cli 0.20.0 (homebrew tap
microck/kagi)
- macOS 15 (arm64)
- Kagi plan: Starter; UI language: Norwegian (Bokmål)
What happened?
kagi usagefails hard on plans that don't include the AI-cost box (reproduced on Starter):Root cause
parse_usage_htmlinsrc/usage.rsrequires the labeltotal ai cost this period(orai usage (usd)) and returns a parse error when absent. But the AI-cost box is an Ultimate-plan feature. A Starter billing page (verified against/settings/billingserver HTML, 2026-09-12, Norwegian locale) instead renders plain usage counters:Two separate issues:
ai_costis treated as mandatory, so every non-Ultimate account gets a hard parse error even though plan/balance/renewal data is present.account balance/next renewal isnever match localized pages (Saldo,Neste fornyelse er), so those fields come back empty on non-English accounts even when present.Suggested fix
ai_cost: Option<AiCostUsage>and skip the field when the box is absent (JSON consumers already tolerateskip_serializing_if-style fields).billing_box_count_*structure instead of label text).I have implemented this locally (optional
ai_cost+saldo/neste fornyelse erfallbacks) and verified E2E on a Norwegian-locale Starter account:{ "plan": "Starter", "ai_cost": null, "account_balance_usd": 0.07, "next_renewal": "2026-09-19", "daily_usage": [] }All 215 unit tests pass (one test updated: the "missing cost pair errors" test now asserts successful parse with
ai_cost: None). Happy to open a PR.Environment
microck/kagi)