Cardful

Privacy policy — Cardful Chrome extension

Last updated: November 2026

This is the privacy policy for the Chrome extension. It lives in a repository rather than on a website on purpose: a Chrome Web Store listing needs a privacy policy URL that stays reachable, and one that depends on a deployment staying up is one that can quietly break.

The short version

The extension sends nothing about you anywhere. It downloads one public file of shopping-portal rates once a day, and it sends your data only if you switch on sync, which is off until you do. There are no analytics, no tracking, and no third parties.

If you sign in to sync, your card list, your point values, any balances you typed in and the stores you pinned — and, with Pro, your offers — are stored on Cardful's server under your account, so you see the same thing on cardful.xyz, your phone and your other browsers. No other account can read them, and they are never shared or sold. That is a real change from "nothing leaves", and it is why it is off until you sign in and described in full below.

With sync on, each scan of a bank's offers page also sends Cardful a scan report: an outline of how that page is built, with every store name, amount, date and number blanked out. We use those reports only to keep the scanner working and to improve Cardful, and we never sell or share them. What a report contains is set out under "Scan reports" below.

The daily rate index is one file of shopping-portal rates that the extension downloads from cardful.xyz once a day. The phone app (at most once a day, when you open it) and the wallet page (when you open it) download the same file for their store search, under the same rules. Portal rates are the same for everybody, so there is nothing personal to ask for. It is worth being exact about what that is and is not. The file is the same bytes for every user and covers every portal and every store at once; it is downloaded whole and searched on your device. Cardful never asks for a particular store, because a request naming one would tell the server what you were about to buy — which is the fact this whole design exists not to learn. The request carries no cookie, no credential, no card and nothing that identifies you. What the server can see is that some address downloaded a public file, which is what a server sees when anyone loads any web page.

What it stores

All of it lives in chrome.storage.local on your own machine. In full:

There is no analytics, no error reporting, and no identifier of any kind that is not listed above.

A category correction is the one entry that names a website. If the extension guesses that example.com is a restaurant and you correct it to groceries, that single pair — hostname and category — is saved so you do not have to correct it on every visit. Two things are worth being precise about:

Whether you have Pro. Pro belongs to your account's email address. When you buy it, Stripe tells our fulfillment worker, which records two things on our server: the email you paid with, and the last day your payment covers. Nothing else — no card details, no name, no address.

Card details are handled entirely by Stripe and never reach us.

It never asks for, and has no way to learn, a card number, a CVC, an expiry date, or a billing address.

Permissions, and what each is for

Permission What it does
storage Remembers your card list and preferences, locally.
activeTab Lets the popup read the address of the current tab — only at the moment you click the toolbar icon — to work out which store you are on. If that tab is your own bank's offers page, it is also what lets the scan below reach it, for that one tab only.
scripting Puts the offer scanner onto the bank offers page you are looking at, when you press the button that starts a scan.
alarms Wakes the extension on a schedule: to check whether an offer you added is about to expire, to download the daily rate index, and — only if you have turned sync on — to sync changed records. The timer itself carries no data.
notifications Shows that expiry reminder. Only ever about offers already in your own vault, and only if you leave reminders switched on.
cardful.xyz Downloads the daily rate index: one GET of one fixed file, once a day, with no cookies and no query — the same bytes everyone else downloads. It receives nothing from you at all.
Content script on all sites Runs the on-page checkout overlay. This is what Chrome describes at install as "read and change all your data on all websites."
A small script on three bank offers pages Keeps a copy of the offers list your bank's own page loads, for the scan to read. Described under "On your bank's offers page" below. It is covered by the all-sites access above and adds no install warning.

Four bank sites, four shopping portals and the sync endpoint appear as optional host permissions, which Chrome asks about individually and only when you turn something on that needs one. None is requested at install, and declining one costs exactly the feature that asked:

Optional access Asked for when
global.americanexpress.com, secure.chase.com, online.citi.com You ask Cardful to walk your banks' offer pages unattended, or to offer to add new offers once a day when you sign in to a bank. Scanning the page you are already looking at needs none of these — that is what activeTab above is for.
capitaloneoffers.com You ask Cardful to open Capital One Offers unattended along with your other banks. It reads the offers already on your card and the in-store offers you can activate, and presses nothing there — which three in-store offers to activate is your choice, made on Capital One's page. Reading the page you are already looking at needs none of this.
card.discover.com You ask it to activate a rotating card's quarterly categories for you.
www.rakuten.com You ask it to read a cash-back shopping portal's current rates. It reads the rates on screen and presses nothing. On a long list it scrolls down to reach the rest of it — never if you scroll, tap or type first, stopping the moment you do, and putting the page back where it was.
www.aadvantageeshopping.com, www.skymilesshopping.com You ask it to read an airline shopping portal's current rates. The same reading and the same restraint as the row above; what differs is the payout, which is quoted in miles rather than cash.
The sync endpoint, vbawbduxhvyfpfomulrh.supabase.co You sign in to sync. It sends your cards, point values, balances and pinned stores, and with Pro your offers, to your own account, which no other account can read.

The last permission is the broad one, so here is exactly what the script does with it.

What the content script reads

To decide whether a page is a checkout page, it looks at:

Once it has decided a page is a checkout, it also looks at:

On your bank's offers page

In the browser extension, nothing happens on a bank's site unless you ask for it. There is no "connected bank" state, no timer and no background scan. The iPhone app's optional bank sync works differently, and has its own section below. The one standing request you can make is described below: for a bank you have given standing access, you can ask Cardful to offer, once a day when you sign in, to add new offers.

When you are signed in to your bank, on its own offers page, you can click the toolbar icon and press "Scan this page for offers". That, and only that, puts the scanner onto that one tab. Chrome's activeTab grant covers the tab you invoked the extension on and ends when that tab goes somewhere else, so the extension has no way back onto your bank's site afterwards without you doing the same thing again.

What the scanner reads is the offer tiles the page is displaying: the store name, what the offer pays, any minimum spend, the expiry date, and whether the offer is already on your card. It also reads the card's product name with the digits stripped out, so offers from two cards can be told apart. It reads no account numbers, no balances and no transactions. It clicks only buttons whose own visible name is on a short allowlist ("Add to card", "Activate" and a few more), which is checked separately from how the button was found — so a mismatch costs a missed offer rather than doing something else.

Where the scan gets the list. Your bank's offers page draws its tiles from a list it downloads for itself when it loads. On Chase's dashboard, American Express's offers page and Capital One Offers, a small script from Cardful runs inside the page from the moment it opens and keeps a copy of that one list in the tab, so the scan can read every offer at once, with the bank's own dates and amounts, instead of scrolling through the tiles. Three things are worth being exact about:

On Chase the script loads across the whole signed-in dashboard, because Chase's offers live inside it at an address a browser cannot single out. It still copies only the offers list.

All of it is written to chrome.storage.local on your machine, and sent nowhere unless you have switched on sync. With sync on, the scan also leaves a scan report, described next.

Scan reports

Banks redesign their offers pages without notice, and the scanner can only read a page it has been written for. Nobody at Cardful can open your bank's offers page — it exists only inside your signed-in session — so the only way to keep the scanner working is to see how the real pages are built. That is what a scan report is for.

After every scan, the extension writes down the structure of the page it read: the names of the page's building blocks (for example "a button inside a list item inside the offer grid"), the labels the bank's developers gave them, and what the scan concluded ("319 offers read, none added", or "could not find the offer list"). Before anything is saved, every word that is not on a short list of offer and card words — "Add to card", "Offer", "Gold", "Platinum" and the like — is replaced with x, and every digit with 9. So a report keeps that the page showed a card called "Gold Card ••••9999" and a tile reading "x x x 9% back", and loses the store, the amount, the date, your last four digits, and anything else you or the bank typed.

With sync on, the next sync sends the newest report for each bank to Cardful's server under your account, along with the extension's version number. Each account keeps its 50 newest reports, and none older than 90 days. They are used only to repair and improve the scanner and Cardful, they are never sold or shared, and Delete my data on the server deletes them with everything else. You can see the newest one yourself: press "Copy scan details" in the popup on your bank's offers page and paste it anywhere. With sync off, the report stays on your computer and is never sent.

Separately, you can grant one of these banks standing access from the offers page, which lets the extension open several banks in turn in a window you watch — and, at a bank that keeps the offers already on your card on a second page, both of that bank's offer pages rather than one. That is optional, never requested at install, revocable from the same row, and the only thing it changes is how the scanner gets to the page. Both pages are inside the access you granted and neither is anything but a list of offers.

For a bank with standing access you can also switch on "Offer to add new offers when I sign in". Then, at most once a day, signing in to that bank shows a small question in the corner of its page — how many offers Cardful last saw that are not on your card yet, and whether to add them. Nothing happens unless you press "Add offers"; then Cardful opens your offers page in a window you can see and runs the same scan the button would, with the usual progress box and Stop button. "Not today" puts the question away until tomorrow. Going straight to the offers page yourself runs the scan in that tab. To notice the sign-in, a small script runs on that bank's signed-in pages and tells the extension which page you are on; it reads nothing else from them, and the number in the question comes from your own saved offers, not from the page. It never runs in a hidden tab and never runs on a timer. Switch it off on the same row.

What it does not read

Bank sync in the iPhone app

This is optional, off by default and part of Pro. It works differently from the browser extension, so here is exactly what it does.

If you save a bank login, your username and password are stored in your iPhone's Keychain, on that phone only. They are not synced to iCloud, not included in backups, and never sent to Cardful or to anyone except your bank. The app uses them for one thing: signing in on your bank's own website, inside the app.

With a saved login, the app can sign in and scan while you are not looking, usually overnight, on the schedule you choose. It reads the same offers the extension reads, and adds them to your card where your bank allows it. It reads no balances, transactions or account numbers.

The app keeps your bank's website session on your phone, so your bank can recognise the device. Turning off a saved login deletes it and that session immediately. So does signing out of Cardful, deleting your data, or reinstalling the app.

If your bank asks for a code, or a sign-in fails, the app stops and tells you. It does not try again on its own and it never reads your messages.

Your offers then sync to your account as they do from the extension. A login is never part of that.

The card recommendation itself

Computed entirely in your browser from the card list bundled in the extension. Your wallet is never transmitted in order to rank it, with or without sync.

Sync, in detail

Off until you sign in. Signing in asks for permission to reach the sync server, and for your email address; you get a code by email, and there is no password.

The phone app's location

The phone app asks where you are only to name the store you are standing in, and only once you have added cards — before that there is nothing to tell you. On an iPhone it asks Apple Maps, through the phone's own MapKit, which shops are within a couple of hundred metres; that request goes to Apple and nowhere else, and Cardful's servers never see your location or which store came back. The card answer is worked out on the phone. If you turn on nearby stores, the same question is asked in the background as you move, and the store you are in is kept on the phone for twenty minutes so the Home Screen widget can show it. It is never synced. On Android the same question goes to OpenStreetMap's public map server instead — the coordinates and a radius, nothing about you — at most a few dozen times a day. A version of the app built with a Google Places key asks Google instead, under the same rules.

This website

This policy is about the extension, which has no analytics. The website at cardful.xyz is a separate thing, and it does count visits: it uses Vercel Web Analytics, which records the page viewed, the referring site, and the visitor's country and device type, sets no cookie, and keeps no identifier that lasts past the day. It is not loaded on the wallet page (/vault), and nothing the extension does ever reaches it.

The statement checker on the website ("Is my card worth it?") reads a transaction file you choose on your own computer. The file is read by the page in your browser and is never uploaded, saved, synced or sent anywhere — not to us and not to your vault, which holds no transactions. Only its date, description, amount and category columns are read, and it is gone when you close the tab.

Changes and questions

Material changes will update this file, and its history is public in the repository's git log — you can see exactly what changed and when.

Questions or concerns: email keys@cardful.xyz.