← All docs Chrome extension

Install Fins Sync in your browser.

The extension loads straight into Chrome from a local folder. No Web Store account, no build step. Grab the extension files, load them as an unpacked extension, sign in once, and you're done.

Overview

Fins Sync is a Manifest V3 Chrome extension that pulls your live point balance off your issuer's portal and posts the delta back to your Finstracker account. You sign in once on finstracker.com, click Sync on a card, log in to the issuer in the tab it opens, and the number that appears in the portal lands in your tracker a second later.

It is not on the Chrome Web Store yet. While the listing is in review, you install it the developer way: clone the finstracker-extension repo and load it as an unpacked extension. Updates are a git pull plus a reload click.

Heads up. Unpacked extensions show a "Developer mode extension" banner the first time you launch Chrome with one installed. That goes away once the Web Store listing ships. Either way your data and JWT stay on your machine.

Install

You need git and a Chromium browser. Chrome, Edge, Brave, Arc, and Vivaldi all share the same extension format.

Clone the repo

git clone https://github.com/egomez3412/finstracker-extension.git
cd finstracker-extension

That's the whole extension. The repo root is the folder Chrome loads.

Open the extensions page

In your browser, paste chrome://extensions into the address bar (Edge: edge://extensions, Brave: brave://extensions).

Enable Developer mode

Flip the toggle in the top-right of the page. This unlocks the Load unpacked, Pack extension, and Update buttons in the toolbar above the extensions list.

chrome://extensions page with the Developer mode toggle highlighted in the top-right corner
Step 3. Developer mode toggle in the top-right of chrome://extensions.

Load unpacked

Click Load unpacked. In the file picker, pick the cloned finstracker-extension/ folder itself. That's the folder that contains manifest.json at its root.

File picker dialog with the finstracker-extension folder selected and the Select button highlighted
Step 4. Select the cloned finstracker-extension/ folder.

Pin the extension

Click the puzzle-piece icon in the Chrome toolbar, find Fins Sync, and click the pin. The Fins logo now stays in your toolbar.

Chrome extensions menu open with Fins Sync visible and the pin icon highlighted
Step 5. Pin Fins Sync so it's one click away.

First run and sign-in

Click the pinned Fins icon. The side panel opens with a single button: Sign in on finstracker.com.

Chrome side panel displaying the Fins Sync welcome card with a Sign in on finstracker.com button
First run. The extension never asks for your password directly. It opens the real finstracker.com login page in a new tab.

Click the button. A new tab opens at finstracker.com/login.html?source=extension…. Sign in with your existing account, either Google or username and password. Cloudflare Turnstile runs the same way it does on the regular login. The tab confirms "You're signed in" and the side panel auto-refreshes to your cards list.

Why a separate tab? Chrome MV3 forbids running remote scripts inside extension popups, so the Cloudflare Turnstile check can't load there. Bouncing through finstracker.com lets you reuse Google sign-in, password reset, and the captcha exactly as the website does. The token is handed back over chrome.runtime.sendMessage, and the extension never sees your password.

Sync a card

Each tile in the side panel has a Sync button. Click it on the card you want to refresh.

  1. A new tab opens at the issuer's login URL (Chase Ultimate Rewards, Amex MR, Capital One Rewards, etc.).
  2. You log in. Multi-factor, passkeys, and SMS codes are all on you. The extension never touches credentials, it just watches the tab.
  3. When the points page renders, the extension scrapes the configured selector, parses the first number, and posts a POST /api/transactions with a delta. earn if the new balance is higher, redeem if lower, no-op if equal.
  4. The card tile shows "Synced 94,308" with a green checkmark for a few seconds, then settles back to idle.
Side panel card tile showing Chase Sapphire Preferred at 94,308 points with a green Synced indicator
After a sync. The delta is posted as a real transaction so the running balance and your monthly chart both update.

Configure a portal (when scraping fails)

Issuer DOMs change every few weeks. If the default selector misses the number, the card surfaces a "Couldn't pull <card>" banner with a Pick element manually button.

  1. Click Pick element manually. The issuer tab reopens with a small Finstracker HUD floating in the top-left.
  2. Hover the points value on the page. Elements are outlined as you move, and the HUD shows a live preview of what number it sees.
  3. Click the value. The HUD locks on it. Hit Use this value (or press Enter) to confirm, Pick another to retry, or Cancel / Esc to abort.

The page URL pattern and a stable CSS selector are saved as a per-card override and reused for every future sync. You only have to do this once per card per portal redesign.

Issuer portal page with the Finstracker element picker HUD docked top-left and the points value outlined for selection
Element picker. The HUD lives inside a closed shadow root so the host page can't restyle it or swallow its clicks.

Auto-detect mode

Open the extension settings (gear icon, top-right of the side panel) and toggle Auto-detect on known portals on. From then on, the next time you visit any issuer portal you already have a card for, the extension scrapes silently and shows a desktop notification with the result. No button click required.

If you own more than one card from the same issuer, auto-detect waits for you to click Sync on a specific card instead, so it doesn't guess wrong.

Updating

From the cloned repo:

cd finstracker-extension
git pull

Then go to chrome://extensions and click the circular Reload arrow on the Fins Sync card. Your saved settings, JWT, and portal overrides all survive the reload. They live in chrome.storage.local, which is per-extension-ID, not per-version.

Troubleshooting

SymptomFix
"Load unpacked" button is greyed out. Developer mode is off. Flip the top-right toggle on chrome://extensions.
"Manifest file is missing or unreadable." You picked a parent folder instead of the cloned finstracker-extension/ folder. Reload unpacked and pick the folder that contains manifest.json.
Side panel opens but "Sign in on finstracker.com" does nothing. A popup blocker is fighting Chrome. Click the icon a second time, or allow popups for finstracker.com.
You signed in but the side panel still shows the sign-in screen. The tab couldn't reach the extension (rare). Close the tab, reopen the side panel, click Sign in again.
Sync says "Couldn't pull <card>". The issuer redesigned their DOM. Click Pick element manually and re-select the points value. Full instructions above.
Sync opens a tab but never reads the number. You're on a multi-factor or interstitial page. Finish logging in. The extension watches the tab and runs as soon as the actual points page renders.
Running a local dev server (npm run dev) and the extension keeps signing you into localhost. That's by design. The extension probes http://localhost:3000/api/health on every wake and auto-switches the API base if it's reachable, because a JWT issued by localhost can't auth against finstracker.com. Stop the dev server (or change the backend URL in Settings) to point back at production.

Security & privacy

  • The extension only stores three things in chrome.storage.local: your JWT, your user profile, and your per-card portal overrides. Nothing is sent off-device except calls to your Finstracker backend.
  • Your password is entered on finstracker.com in a normal browser tab, not inside the extension. The web tab posts the JWT back via chrome.runtime.sendMessage, scoped to your specific extension ID.
  • The page extractor runs via chrome.scripting.executeScript and only returns the text content of the element you (or the default selector) picked. It has no access to your tokens, cookies, or form fields on the issuer site.
  • Host permissions are scoped to known issuer domains plus your Finstracker backend. The extension cannot read pages on sites it isn't already permitted to.
  • Every scraped number is re-validated server-side by the existing transaction validators in routes/transactions.js (no negative amounts, no redeem above balance, etc.).

Get the extension

The full source is public on GitHub. Clone the repo, load it unpacked, and the rest is the same as any other Chrome extension. The Web Store listing is coming. This works in the meantime.