Data & analysis

creditkarma-fpx

Try it

Query Credit Karma (creditkarma.com) transactions from a shell with the fpx CLI (@fetchproxy/cli) instead of running the creditkarma-mcp server — capture the signed-in session cookie once, then curl the GraphQL transactions endpoint directly. Use when you want Credit Karma transaction data without the MCP, in a script, or on a machine where the MCP isn't installed.

What it does

Credit Karma has **no server-side login** a script can drive — the only credential is the / cookies a real signed-in browser session already holds. There's also no bot wall on the API itself once you have those cookies: 's own proves plain Node works fine against and the refresh endpoint — fetch…

The skill document

Credit Karma via fpx + curl (no MCP)

Credit Karma has no server-side login a script can drive — the only credential is the CKAT/CKTRKID cookies a real signed-in browser session already holds. There's also no bot wall on the API itself once you have those cookies: creditkarma-mcp's own client.ts proves plain Node fetch works fine against api.creditkarma.com/graphql and the refresh endpoint — fetchproxy is only ever used for the one-time cookie capture, never as a request path. So this skill is hybrid: fpx grabs the cookies once, then plain curl does every read and refresh from then on.

This mirrors the one live endpoint creditkarma-mcp actually calls (ck_sync_transactions → the GraphQL query in src/transaction.graphql). The other ck_* tools (ck_list_transactions, ck_get_spending_by_category, …) are local SQLite queries over already-synced data — there's no separate remote endpoint to reproduce for those.

One-time setup

npm install -g @fetchproxy/cli                                  # provides `fpx`
fpx profile add creditkarma --domain creditkarma.com
fpx profile declare creditkarma --cookie CKAT --cookie CKTRKID   # widen scope to these cookies
fpx pair -p creditkarma                                          # prints a pair code → approve in Transporter

Requirements: the Transporter browser extension installed, with an open www.creditkarma.com tab you're signed into, and its Chrome Site access allowing creditkarma.com. CKAT/CKTRKID are HttpOnly (invisible to page JS) but fpx cookies reads them via the extension's chrome.cookies.get, same as @fetchproxy/bootstrap does inside the MCP. Pairing persists across invocations.

Capture the session (once per shell / once the token goes stale)

fpx cookies -p creditkarma
# {"CKAT":"%3B","CKTRKID":""}

CKAT packs both JWTs joined by a literal %3B (URL-encoded ;). Split it:

COOKIES=$(fpx cookies -p creditkarma)
CKAT=$(jq -r '.CKAT' <<<"$COOKIES" | sed 's/%3B/;/')
CKTRKID=$(jq -r '.CKTRKID' <<<"$COOKIES")
ACCESS=${CKAT%%;*}
REFRESH=${CKAT#*;}

Core call: fetch a page of transactions

The gateway executes only safelisted operations, so you do not send a query document — you send its sha256 hash. Sending the full document (even the correct one) is rejected with HTTP 400 {"message":"No query found"}.

Two headers are mandatory: ck-client-name: prime_web — exactly that value, since web is rejected — and a non-empty ck-client-version. Nothing else is: no cookies, no Origin/Referer/User-Agent.

jq -n --arg h 9b5109d15254ad7fc7d18f597b4026422a69bdc48a4be7d43823866a6ea15915 \
  '{extensions:{persistedQuery:{version:1,sha256Hash:$h}},
    operationName:"GetTransactions",
    variables:{input:{paginationInput:{afterCursor:null},
      categoryInput:{categoryId:null,primeCategoryType:null},
      datePeriodInput:{datePeriod:null},accountInput:{}}}}' > /tmp/ck-body.json

curl -s https://api.creditkarma.com/graphql -X POST \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -H 'ck-client-name: prime_web' \
  -H 'ck-client-version: 2.0.31' \
  --data @/tmp/ck-body.json \
  | jq '.data.prime.transactionsHub.transactionPage'

If this starts returning No query found, CK shipped a web build that rotated the hash. Re-derive it: open a signed-in creditkarma.com page and grep its Next.js chunks under creditkarmacdn-a.akamaihd.net/res/content/bundles/prime_web//_next/static/chunks/ for usePregeneratedHashes — a name→hash manifest of all 14 operations.

The one rule: cursor-paginate, and check for an auth error INSIDE the 200 body

Credit Karma's primary expired-token signal is an HTTP-200 body carrying an errorCode — not an HTTP 401. Always check before trusting the payload:

jq -r '.errorCode // (.errors[]?.errorCode) // (.errors[]?.code) // (.errors[]?.extensions.code) // empty' response.json

If that value matches UNAUTHENTICATED|UNAUTHORIZED|TOKEN_EXPIRED|401 (case-insensitive), the access token expired — refresh it (below) and retry. Anything else (schema drift, validation) is a real error, not an auth failure — don't refresh on it. A FORBIDDEN/403-shaped code means authenticated-but-not-authorized; refreshing won't help.

For the next page, re-run the same body with variables.input.paginationInput.afterCursor set to the previous response's pageInfo.endCursor, and stop when pageInfo.hasNextPage is false. See references/requests.md for the full loop.

Refreshing the access token (no need to re-run fpx for this)

The access token is short-lived (~10 min). Refresh with the refreshToken you already extracted — this is a plain curl, not another fpx capture:

GLID=$(node -e "console.log(JSON.parse(Buffer.from(process.argv[1].split('.')[1],'base64url').toString()).glid||'')" "$ACCESS")

curl -s https://www.creditkarma.com/member/oauth2/refresh -X POST \
  -H 'Content-Type: application/json' \
  -H 'Origin: https://www.creditkarma.com' \
  -H 'Referer: https://www.creditkarma.com/' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36' \
  -H 'ck-client-name: web' -H 'ck-client-version: 1.0.0' -H 'ck-device-type: Desktop' \
  -H "Authorization: Bearer $ACCESS" \
  -H "ck-trace-id: $GLID" \
  -H "ck-cookie-id: $CKTRKID" \
  -H "Cookie: CKTRKID=$CKTRKID; CKAT=$ACCESS%3B$REFRESH" \
  --data "$(jq -n --arg rt "$REFRESH" '{refreshToken:$rt}')" \
  | jq '{accessToken, refreshToken}'

A non-JSON (HTML) error body from this endpoint means the refresh token itself is dead — re-sign into creditkarma.com in the browser and re-run fpx cookies -p creditkarma to capture a fresh CKAT/CKTRKID pair.

Output / exit-code contract

  • fpx cookies/fpx session/fpx pair are bridge round-trips: they exit 0 on a successful read regardless of upstream status, 1 on a usage error (e.g. an undeclared cookie key), 2 if the bridge/extension is unreachable or pairing is still pending.
  • Reads and the refresh call go through plain curl — there's no fetchproxy bot-wall exit code (3) to check on them. Check the HTTP status yourself and, for the GraphQL call, the in-body errorCode above.

Notes

  • Never persist ACCESS/REFRESH/CKAT to a file you don't control the permissions of — treat them like the MCP's own .env (0600) if you must write them down at all; prefer keeping them in shell variables for the session.
  • Amounts: negative = expense/debit, positive = credit/income (amount.value/amount.asCurrencyString).
  • This project is developed and maintained by AI (Claude).

Related skills

Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.

by nssa.io1.0k installs47 stars

Fetch raw ad creative, app, ranking, and revenue data from AdMapix as structured JSON.

by fly0pants4.3k installs296 stars

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai21 installs8 stars

Read and write Excel workbooks, worksheets, ranges, tables, and charts in OneDrive through Microsoft Graph with managed OAuth.

by byungkyu800 installs42 stars

Find why your productivity system keeps failing, then apply the smallest fix — capacity math, bottleneck routing, durable local notes.

by Iván854 installs69 stars

More from chrischall

Browse all skills

Read and write OurFamilyWizard messages, calendar events, expenses, and journal entries from your agent.

by chrischall41 installs

Find, inspect, compare, and resolve Compass listings, photos, prices, addresses, and property records.

by chrischall31 installs

Pull Credit Karma transactions into a local SQLite database and query them by category, merchant, or account.

by chrischall31 installs

Search, book, and cancel Resy reservations, plus favorites and Priority Notify alerts.

by chrischall29 installs

Manage iOffice buildings, rooms, visitors, maintenance, moves, and mail through natural-language commands.

by chrischall13 installs

Look up concert setlists, tour histories, and live-show data on setlist.fm through natural-language MCP tools.

by chrischall12 installs