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:
- which cards you told it you carry, and which bonus categories you have selected on the ones that let you choose
- two display preferences: dollars vs points, light vs dark
- your own point valuations if you set any — those override the published defaults for how much a currency like Chase Ultimate Rewards is worth to you
- your rewards balances and your typical monthly spend per category, if you enter them, which are used to rank cards and nothing else
- any category corrections you make
- the bank offers you have added or scanned, and a receipt per bank saying when it was last scanned and how that went. These are cleaned up rather than kept forever: once a scan finds that your bank has stopped listing an offer, it leaves your lists straight away, and the record itself is deleted a month later — long enough that an offer which comes back is simply restored. An offer you typed in yourself is never swept, because no scan speaks for it; that one is yours to delete
- travel-portal rates read from one of the two airline shopping portals, each with the time it was read (they stay on this computer and are not synced)
- Capital One Offers' online offers, if you scan Capital One Offers: the store, its website and Capital One's own wording of the reward, each with the time it was read. With Pro and sync on, this list syncs like your other offers, so your phone and cardful.xyz show it too
- a short-lived note that you asked to activate a card's bonus categories, which authorises one click on that issuer's own site and then expires
- with sync on: your email address, your sign-in session, and this device's sync position
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:
- Nothing is written by visiting a page. An entry appears only when you yourself pick a different category, in the popup or the overlay. A site you never corrected is never recorded, so this is not a browsing history and cannot be used as one.
- It still goes nowhere — including with sync on. Your site corrections are deliberately left out of what syncs, along with your light/dark preference. They are keyed by the websites you visit, and that is not something we will copy to a server. You can drop any entry with the back arrow that appears on a corrected site, and removing the extension deletes the lot.
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.
- The extension reads that one row when you are signed in: once an hour with the regular sync, and when you open the popup. It asks only for its own row, and the server's access rules let a signed-in session see its own email's row and nobody else's. No client can write it.
- A copy is kept on this device, with the email it belongs to, so Pro keeps working without a connection. It counts only while that same email is signed in, so signing out turns it off here.
- The date your trial started is stored beside it, as a plain calendar day. The trial needs no account, and starting it involves no server.
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:
- The
autocomplete,name,id,placeholder,aria-label, anddata-testid/data-qa/data-testattributes of form fields that were already present in the page's HTML — the last few catch checkout forms built with a component library that skipsname/idin favor of a visible label or a test hook. Still markup metadata in every case, never a typed value. - The
srcof iframes, checked against a list of known payment processors (Stripe, Braintree, Adyen and similar), since those render the real card field in a cross-origin frame the extension cannot see into at all. - The page's own hostname, to work out which store you are on.
Once it has decided a page is a checkout, it also looks at:
The
alt,title,aria-labelandsrcattributes of images whose attributes mention a card network, to see which networks the checkout says it accepts. This is how it can tell you a store does not take your Discover before you get to the card entry screen.The order total the page is already displaying, so it can tell you what a card earns on this cart in dollars instead of as a rate, and whether the cart clears the minimum spend on an offer you hold. It matches text like "Order total $87.40" against the visible text of the row containing it.
This is the one place the extension reads text rather than markup, and it is worth being exact about what that means. It reads the number the page is showing you on screen. It does not read what you type, it keeps no record of the total, and the figure never leaves the page — it is used to render one line in the overlay and then discarded when the overlay re-renders.
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:
- It sends nothing, with one exception you start. It copies what the page asked for, under your own session, for its own reasons. The exception is Capital One Offers' online offers, which the page loads about ninety at a time behind a "View More Offers" button: when you scan Capital One Offers, Cardful asks for the rest of that same list itself — the page's own request, one page at a time, about a second apart — so every online offer is read without you pressing the button dozens of times. It is a read only: it activates nothing, and it asks for nothing but that list.
- It keeps only the offers list. It looks at the address of each request the page makes and copies the answer to just the offers-list request. Balances, transactions, transfers and everything else the page loads pass by without being read. What it hands to the scan is the store names, the offer wording, dates and amounts, and whether the offer is on your card — not the bank's ids, account references or tokens.
- It holds the copy in that tab only. Nothing is stored or sent until you start a scan, and closing or reloading the page discards it.
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
- It never reads a field's value. Not the card number, not the CVC, not anything else you type into any field on any page. It reads attributes, which are part of the page's markup, not its contents.
- It attaches exactly one event listener, for
focus, and only so it knows when to show the overlay — the same moment your browser's own autofill suggestion would appear. A focus event carries no information about what gets typed afterwards. It is neverinputorkeydown. - It sends nothing about you unless you turn on sync. The card database
and the ranking engine are bundled into the extension itself, so it works
fully offline. Once a day it downloads one public file of portal rates from
cardful.xyzand sends nothing at all — no store, no card, no identifier. With sync on, it contacts the sync server and sends the cards, values and offers described below to your account, plus the redacted scan reports described above. None of those requests happens on a page you are visiting, and the only thing any of them carries from a page is a bank's offers and a scan report with its words and numbers blanked out. - The extension does not read cookies, passwords, or anything you type. The only page text it reads at all is the displayed order total described above, and only on pages it has already identified as checkouts. It reads no other text, no product names, no addresses, and no order history.
- It cannot change what you pay with. It shows a recommendation; choosing the card is always yours.
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.
- What is stored: your card list (and the bonus categories you picked on cards that let you choose), your point values, any balances and monthly spend you typed in, the stores you pinned on the store table, and — with Pro — your bank offers and when each bank was last scanned, including Capital One Offers' online offers, packed into a few records. On the free plan, offers stay on your computer. If you have bought Pro, a separate record of your email and the day your payment covers it to, described above. On every plan, the redacted scan reports described under "Scan reports" — the newest 50, none older than 90 days.
- What is never stored: your site corrections and your light/dark setting, for the reasons above, and travel-portal rates, which are public and stay on each device. Nothing from your bank's site is stored except the offers themselves: no account numbers, no balances from the bank, no transactions, and never a password.
- Who can read it. Your signed-in account, and no other. The database enforces that each account can read and change its own records and no one else's, and it is encrypted on disk by our hosting provider (Supabase). Cardful does not sell, share or analyse your cards, point values or offers, and uses them for nothing but showing them back to you. Scan reports are the one thing we do read: to repair and improve the scanner, and never to sell or share. As with any service that stores your data, the people who run it could in principle access the database; we do not, except to fix something you ask us to fix.
- When it runs. About a minute after your cards or offers change or a scan finishes, half a minute after you save something on cardful.xyz in the same browser, and once an hour, as long as you are signed in. Each run sends only what changed.
- Signing in once. When you are signed in on cardful.xyz and the extension is not, the extension signs itself in as the same account: a script that runs on cardful.xyz only reads the site's sign-in from that site's own storage, and our server exchanges it for a separate sign-in for the extension, for the same email and no other. An extension already signed in is left alone, unless you press Switch this browser under Settings › This browser, which signs it out of the other account first. That screen says which account the extension in this browser is signed in as, read from the extension itself.
- The wallet page on the website shows the same records once you sign in with the same email. Adding a card, changing a point value or typing in an offer there saves to your account, and your other devices pick it up on their next sync. The extension in the same browser is told, and syncs within the minute; when it finishes a sync, it tells the page, which re-reads your wallet. Both messages stay inside that browser. It keeps your sign-in in that browser's local storage so you stay signed in; Sign out removes it.
- Your partner's cards. You can list the cards your partner carries on the wallet page so Cardful can say when one of theirs earns more. Those are stored in your account like your own cards, and your partner needs no account for it.
- Sharing a household. If you invite your partner by email, nothing is shared until they sign in with that address and accept. From then on each of you can see the other's card list and card offers — nothing else: not point values, balances, pinned stores or scan reports — and one Pro subscription covers you both. If you had added their cards for them, accepting puts those cards in their own wallet. Either of you can stop sharing at any time on the wallet page, which ends it for both. The invitation records both email addresses, and Cardful sends one email to the address you invited, from keys@cardful.xyz, saying who invited them and how to accept. It goes only to the address you entered, and can be sent again at most a few times.
- Deleting it. Sign out ends the session on that device and stops it syncing; your cards and offers stay on the device. Delete my data on the server (under Settings on cardful.xyz, and in the app) removes every record your account has stored, scan reports included, and ends any household you share. It signs out the device you pressed it on; your other devices stay signed in, and anything they change afterwards is stored again. What is on your devices stays on them — it was yours before sync existed. To delete the account itself, email us.
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.