Subscription waste calculator
A 15.99 monthly plan nobody used for 4 months wastes 63.96 a year, and this calculator does that sum for every subscription you list. Weekly, quarterly and yearly bills are turned into a monthly figure first. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
A gym you stopped visiting, a streaming trial that rolled into a paid plan, and a SaaS seat nobody logs into still leave the same charge on every statement. This subscription waste calculator turns each subscription’s cost, billing cycle, and months unused into money wasted per year, so a household or team can see the annual leak instead of a raw spend total. Weekly, monthly, and yearly plans are first converted to a monthly equivalent with fixed period factors, then multiplied by unused months in a twelve-month window. The result is a deterministic yearly waste figure you can pin in a budget bot or a cancel-or-keep meeting. Negative costs are rejected as invalid input because a waste ledger is not a refund calculator.
What you can do with it
Household unused streaming audit
List every streaming, gym, and news plan with how many months nobody used it and instantly see yearly household leak plus each idle service’s waste.
Team SaaS seat waste
Convert yearly software renewals and monthly seats into unused-month waste so procurement can cancel idle licenses before the next invoice.
FAQ
How is subscription waste per year calculated?
Each cost is scaled to a monthly equivalent from its billing cycle, then multiplied by unused months in a twelve-month window (capped at 12).
What happens if a subscription cost is negative?
Subscription costs must be non-negative; negative values are rejected and not charged.
How are yearly and weekly billing cycles converted?
Weekly uses fifty-two periods, biweekly twenty-six, quarterly four, and semiannual two, then unused months apply to that monthly figure.
What if a subscription was unused for more than 12 months?
Yearly waste caps unused months at 12, so the line reports a full year of cost as the leak.
Is the subscription waste calculator free?
The browser tool runs free on your device.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/fin/subscription-waste \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"subscriptions":[{"name":"Streaming","cost":15.99,"billing_cycle":"monthly","months_unused":4},{"name":"Cloud storage","cost":119.88,"billing_cycle":"yearly","months_unused":6},{"name":"News","cost":12,"billing_cycle":"monthly","months_unused":0}]}'const res = await fetch("https://api.kit.forhosting.com/fin/subscription-waste", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"subscriptions": [
{
"name": "Streaming",
"cost": 15.99,
"billing_cycle": "monthly",
"months_unused": 4
},
{
"name": "Cloud storage",
"cost": 119.88,
"billing_cycle": "yearly",
"months_unused": 6
},
{
"name": "News",
"cost": 12,
"billing_cycle": "monthly",
"months_unused": 0
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/subscription-waste",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"subscriptions": [
{
"name": "Streaming",
"cost": 15.99,
"billing_cycle": "monthly",
"months_unused": 4
},
{
"name": "Cloud storage",
"cost": 119.88,
"billing_cycle": "yearly",
"months_unused": 6
},
{
"name": "News",
"cost": 12,
"billing_cycle": "monthly",
"months_unused": 0
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/subscription-waste", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"subscriptions":[{"name":"Streaming","cost":15.99,"billing_cycle":"monthly","months_unused":4},{"name":"Cloud storage","cost":119.88,"billing_cycle":"yearly","months_unused":6},{"name":"News","cost":12,"billing_cycle":"monthly","months_unused":0}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"subscriptions":[{"name":"Streaming","cost":15.99,"billing_cycle":"monthly","months_unused":4},{"name":"Cloud storage","cost":119.88,"billing_cycle":"yearly","months_unused":6},{"name":"News","cost":12,"billing_cycle":"monthly","months_unused":0}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/subscription-waste", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"subscriptions": [
{
"name": "Streaming",
"cost": 15.99,
"billing_cycle": "monthly",
"months_unused": 4
},
{
"name": "Cloud storage",
"cost": 119.88,
"billing_cycle": "yearly",
"months_unused": 6
},
{
"name": "News",
"cost": 12,
"billing_cycle": "monthly",
"months_unused": 0
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.subscription_waste",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
What to send: cost, billing cycle, and months unused
Billing cycle accepts weekly, biweekly or fortnightly, monthly, quarterly, semiannual or half-yearly, and yearly or annual, with spaces and hyphens normalized before lookup. Optional name, label, title, or service gives a human-readable row for dashboards; if you omit the name the engine assigns Subscription one, Subscription two, and so on in list order. At least one subscription is required; an empty array fails validation before any waste is computed. Negative months unused also fail, because idle time cannot run backwards. Unknown billing cycle strings fail with a list of accepted values so typos surface early. Send a JSON body with a required subscriptions array—aliases items, list, services, and plans are accepted when a client already uses another field name. Each entry is an object with three required facts: cost, the amount billed each cycle; billing_cycle, the cadence of that charge; and months_unused, how many months of a twelve-month window the service sat idle. Cost may arrive as a number or a numeric string; aliases amount, price, fee, and charge map to the same value so bank exports and form builders keep familiar keys. Negative costs raise invalid_input with a message that the cost cannot be negative—the product promise is money wasted on unused subscriptions, not a refund ledger. Extremely large costs, idle-month counts, and very long lists are capped so Worker isolate math stays bounded. All validation runs before scaling, so a bad list never returns half-filled yearly waste that looks successful to a client that only checks HTTP success.
How yearly waste is computed from unused months
For every subscription the engine multiplies the billed cost by how many times that cycle occurs in one year, then divides by twelve to produce a monthly equivalent: weekly uses fifty-two periods, biweekly uses twenty-six, monthly uses twelve, quarterly uses four, semiannual uses two, and yearly uses one. That means a yearly plan of one hundred nineteen point eighty-eight becomes nine point ninety-nine per month, while a monthly fee of fifteen point ninety-nine stays fifteen point ninety-nine. Six unused months on that yearly cloud plan therefore waste fifty-nine point ninety-four in a year; twelve unused months waste the full annual cost; eighteen unused months still report a full-year leak because the product answers money wasted per year, not a multi-year running total. Intermediate products use ordinary floating-point arithmetic; every money field in the response is then rounded half-up to two decimal places so results look like currency on a statement rather than long binary fractions. Unused months are then applied inside a twelve-month window: waste_per_year equals monthly equivalent times the smaller of months_unused and twelve. Each result line includes its zero-based index, display name, echoed cost, canonical billing_cycle, months_unused, monthly_cost, annual_cost, unused_months_in_year after the cap, and waste_per_year. Top-level total_waste_per_year sums the pre-rounded waste contributions so the grand total stays consistent with the line math before final half-up rounding. total_annual_cost is the sum of full annualized costs, and unused_pct is one hundred times waste over that annual total (zero when every cost is zero). The count field equals the number of input rows, currency_decimals is always two, and method is always subscription_waste so downstream code can branch without sniffing shapes. Missing subscriptions, empty lists, missing cost, missing billing cycle, missing months unused, non-numeric values, unknown cycles, and negative costs all fail with invalid_input and are not charged after rejection.
Where a subscription waste API earns its keep
Call the free in-browser subscription waste calculator when you are hunting forgotten streaming stacks, unused gym memberships, or software seats that still renew while nobody logs in. Keep lists within ordinary household or team sizes; the published subscription cap protects isolate runtime while still covering full media and software stacks. The product promise is transparent unused-month waste, not live merchant scraping or bank-feed classification—those intents belong to different tools with different search terms and engines. Use the prepaid API when a personal-finance app, expense coach, SaaS procurement helper, family shared-cost bot, or cancel-or-keep onboarding flow needs a stable contract at $0.002 per successful item; validation failures never consume balance after the engine rejects the request. Pair this endpoint with a spend-total calculator only when you also need the used portion of the stack—this capability answers unused money per year, not the full recurring bill. Authors shipping SDKs can map the lines array into a cancel-first table, surface total_waste_per_year in a summary banner, and use unused_pct to show how much of the annual stack is idle.
Integration use cases
Cancel-or-keep budget coaching
Finance coaches and chatbots call a stable prepaid endpoint instead of reimplementing cycle factors, twelve-month caps, and negative-cost guards in every client language.