Inspiration

I tried to cancel a subscription and it took me twenty minutes. The cancel button was buried three menus deep, I got offered a discount twice, then asked if I wanted to "pause instead," then guilt-tripped by a button that said I didn't like good things.

When I finally looked at my bank statement properly, I found charges I'd completely forgotten about: a free trial that quietly turned paid, a service whose price had crept up, and two apps that did the same thing. None of these companies were doing anything illegal. They were just counting on me being too tired to fight.

So I built something that fights for me.

What it does

Cancel Me works in three steps:

  1. Find. Upload a bank or credit card statement as a CSV. Cancel Me detects every recurring charge and flags the sneaky ones: trials that converted, prices that went up, duplicate services, and merchant names you probably don't recognize.
  2. Choose. A dashboard shows what you're spending per month and per year on each subscription. Tick the ones you're done with.
  3. Cancel. An AI agent opens a real browser and works through each cancellation flow. A live log narrates every step and every trick it dodges, like declined retention offers, skipped "pause instead" screens, and unchecked add-ons that would have kept billing you. When it's done, it saves a screenshot of the confirmation page as your receipt.

The agent never types your password. When it hits a login page it hands control back to you, and it always asks before clicking the final confirm button.

How I built it

  • Frontend: React and TypeScript, designed in Lovable, with a live log that streams agent events over server-sent events.
  • Backend: Python and FastAPI, with SQLite storing subscriptions, runs, and receipts.
  • Detection: pandas groups charges by merchant and looks at the gaps between them. A subscription is flagged when the median gap between charges lands close to a known billing period:

$$ \left| \operatorname{median}(\Delta t) - P \right| \le 0.15P, \quad P \in {7, 30, 365} \text{ days} $$

Messy merchant strings like NETFLIX.COM 866-579 get cleaned up with a lookup table first, with an LLM only called for ones the table doesn't know.

  • Agent: an LLM with tool calling drives Playwright. Instead of sending screenshots, I tag every clickable element on the page with an index and send the model a compact text list. It picks one action per step (click, type, check, uncheck, go back, ask user, or done), and the backend executes it and logs a plain-English note.
  • StreamMax: to demo reliably, I built a fake streaming service designed to be as evil as possible: a hidden cancel link, two stacked retention offers, a pause screen, a confirmshaming survey, and a pre-checked add-on that keeps billing.

Challenges I ran into

  • Real sites don't want to be automated. CAPTCHAs, 2FA, and constantly changing layouts make full automation unrealistic. Handing login back to the user turned out to be both the practical fix and the right safety call.
  • Screenshots were slow and expensive. Switching the agent to a text list of indexed elements made it faster, cheaper, and better at finding buried links.
  • Getting stuck in loops. Early on, the agent would happily accept a "pause" or bounce between two pages. A strict system prompt, a step cap, and stuck detection (same page three times means fall back) fixed most of it.
  • Bank CSVs are all different. Column names and sign conventions vary by bank, so I added a column mapper for formats it doesn't recognize.

Accomplishments that I'm proud of

  • The agent reliably cancels subscriptions end to end, including spotting and unchecking the hidden add-on.
  • The live log makes the agent's reasoning visible, so you can actually watch it refuse to be manipulated.
  • The whole thing runs locally and costs a few cents per cancellation.

What I learned

  • How to design an agent loop that's safe by default: clear limits, human checkpoints before irreversible actions, and a graceful fallback when it can't finish.
  • Representing the page as structured text instead of images makes a huge difference to cost, speed, and accuracy.
  • Dark patterns are everywhere once you start naming them.

What's next for Cancel Me

  • A browser extension that notices when you're on a subscription page and offers to cancel it.
  • A phone fallback agent that calls support and waits on hold for you.
  • Monthly re-scans that warn you about free trials before they convert.

Built With

Share this project:

Updates

Submission history