
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
swedbank-json
Advanced tools
A modern TypeScript port of walle89/SwedbankJson that interacts with Swedbank's mobile APIs. It supports Mobile BankID QR login, session caching, cookie management, account overview, transaction previews, and complete transaction history with pagination.
This project is not affiliated with Swedbank or Sparbanken. Use for personal/educational purposes only.
accountTransactions) and full history pagination (getFullTransactionHistory)npm install swedbank-json
TypeScript/ESM import:
import { loginWithBankID, SwedbankClient } from "swedbank-json";
CommonJS require:
const { loginWithBankID, SwedbankClient } = require("swedbank-json");
import { loginWithBankID, SwedbankClient } from "swedbank-json";
async function main() {
const { auth, session } = await loginWithBankID({
personnummer: "YYYYMMDDXXXX", // optional for QR, required for same-device
bankApp: "sparbanken",
cachePath: "./cache/session.json", // where you persist the session/AppData cache
sameDevice: false, // set true to deep-link to the BankID app instead of QR
});
// Render QR by polling in your own loop (pseudo):
const status = await auth.pollStatus();
console.log(status.imageChallengeData); // base64 for animated QR frames
await auth.verify(); // waits for COMPLETE
const client = new SwedbankClient(auth);
const accounts = await client.accountList();
console.log(accounts.transactionAccounts.map((a: any) => a.name));
}
Valid bankApp values: swedbank, sparbanken, savingsbank, swedbank_foretag, sparbanken_foretag.
Session caching behavior
loginWithBankID returns { auth, session }. Persist session to disk (e.g., fs.writeFileSync("./cache/session.json", JSON.stringify(session))).new SwedbankClient(loadedSession) to reuse cookies/user agent without scanning a new QR (until Swedbank expires the session).cachePath so repeat runs avoid remote lookups.Cookie handling
session, those cookies are preserved and replayed when you reconstruct SwedbankClient with the saved session.const client = new SwedbankClient(auth);
const overview = await client.accountList();
// Transaction accounts
for (const account of overview.transactionAccounts) {
console.log(`${account.name} (${account.id}) -> balance: ${account.balance.amount} ${account.balance.currency}`);
}
// Savings/investments
if (overview.savingsAccounts) {
console.log(`You have ${overview.savingsAccounts.length} savings accounts`);
}
Account categories commonly present in engagement/overview:
transactionAccounts: Current/checking accountssavingsAccounts: Savings & investment accountscardAccounts: Credit card accountsloans: Loan products (mortgage, consumer loans)Basic preview (single page):
const accountId = overview.transactionAccounts[0].id;
const page = await client.accountTransactions(accountId, 40, 1);
console.log(page.transactions.length); // Up to ~40, depending on the API default
Full history with pagination (recommended):
const allTransactions = await client.getFullTransactionHistory(accountId);
console.log(`Fetched ${allTransactions.length} transactions`);
// Example: find the latest card charge
const latestCard = allTransactions.find((t) => t.type === "CARD");
console.log(latestCard);
getFullTransactionHistory follows Swedbank's links.next.uri pagination until moreTransactionsAvailable is false, so you get the complete list the API exposes.
├─ src/ # TypeScript sources with rich TSDoc
│ ├─ auth/ # Mobile BankID, security token, and unauth flows
│ ├─ swedbank/ # SwedbankClient and high-level banking helpers
│ ├─ http/ # HTTP wrapper with headers/cookies
│ ├─ appdata/ # AppData cache (User-Agent/AppID)
│ └─ index.ts # Public entrypoint (loginWithBankID, exports)
├─ dist/ # Compiled JavaScript + type declarations (npm publishes this)
├─ cache/ # (suggested) store session JSON and AppData cache here
├─ test/ # Vitest tests
├─ package.json
├─ tsconfig.json
└─ README.md
.env example (with dotenv):
SWEDBANK_PERSONNUMMER=YYYYMMDDXXXX
SWEDBANK_BANKAPP=sparbanken
SWEDBANK_CACHE_PATH=./cache/session.json
SWEDBANK_SAME_DEVICE=false
SWEDBANK_DEBUG=1
Usage:
import "dotenv/config";
import { loginWithBankID } from "swedbank-json";
const { auth } = await loginWithBankID({
personnummer: process.env.SWEDBANK_PERSONNUMMER,
bankApp: process.env.SWEDBANK_BANKAPP || "swedbank",
cachePath: process.env.SWEDBANK_CACHE_PATH || "./cache/session.json",
sameDevice: process.env.SWEDBANK_SAME_DEVICE === "true",
});
Common errors thrown by the client:
Unable to use Mobile BankID. Check if the user has enabled Mobile BankID. – initiation failedMobile BankID verification timed out. User did not complete authentication in time. – QR not scanned within timeoutThe user is not a customer in Swedbank... or ...Sparbanken – profile selection mismatches the chosen bankAppNot a valid AccountID / Not a valid DetailsTransactionID – invalid identifiers passed to account/transaction endpointsThere are no registered transactions to confirm. – attempting to confirm transfers when none existPROFILE_SELECTION_NEEDED / MULTIPLE_PROFILES – some users must select a profile; use selectProfileIfNeeded or set profileIDCatch errors around your calls to provide better user messaging or retries.
Set SWEDBANK_DEBUG=1 to log request URLs, headers, cookies, and short response excerpts. By default, the client is quiet aside from thrown errors.
SWEDBANK_DEBUG=1 node your-script.js
loginWithBankID(options: LoginWithBankIDOptions)Starts Mobile BankID authentication and returns { auth, session }. Persist session to disk to skip QR next time; use auth.pollStatus() for QR frames and auth.verify() to block until done.
SwedbankClientconstructor(authOrSession) – pass a MobileBankIDAuth instance or a persisted Session objectprofileList() – list available profiles for the authenticated useraccountList(profileID?) – fetch engagement overview (transactionAccounts, savingsAccounts, cardAccounts, loans)accountTransactions(accountID?, transactionsPerPage?, page?) – single-page transaction preview (legacy)accountDetails(accountID?, transactionsPerPage?, page?) – alias of accountTransactionsgetFullTransactionHistory(accountID?) – traverse pagination and return all transactionstransactionDetails(detailsTransactionID) – fetch additional info for a transactionportfolioList(profileID?) – list savings/investment holdingsreminders() – fetch message reminderstransferBaseInfo() – base info for payments (limits, defaults)transferRegisterPayment(amount, fromAccountId, recipientAccountId, fromAccountNote?, recipientAccountMessage?, transferDate?, periodicity?)transferListRegistered() / transferListConfirmed() – list pending/confirmed paymentstransferConfirmPayments() – confirm all registered transferstransferDeletePayment(transferId) – delete a paymentquickBalanceAccounts(profileID?) – list accounts eligible for quick balancequickBalanceSubscription(accountQuickBalanceSubID) / quickBalance(subscriptionId) / quickBalanceUnsubscription(subscriptionId, profileID?)selectProfileIfNeeded(accountsResp) – helper to auto-select a profile when the API requests itterminate() – end the authentication sessionMobileBankIDAuthinitAuth() – start Mobile BankID (QR or same-device)pollStatus() – non-blocking status + animated QR payloadverify() / verifyLoop() – block until authentication is completegetAutoStartToken() – deep-link token for same-device flowsgetImageChallengeData() – latest QR frame payloadsetSameDevice(sameDevice) – toggle between QR and same-device modesterminate() – logoutSecurityTokenAuthHardware token/OTP flow (legacy): getChallenge(), login(responseCode), isUseOneTimePassword().
UnAuthDevice registration without full login: login() registers the device; useful for unauthenticated endpoints.
AppData / AppDataCache – fetch and cache mobile app metadataHttpClient – Swedbank-aware fetch wrapper with cookie + header managementSession, SwedbankTransaction, LoginWithBankIDOptions, MobileBankIDAuthOptions, SecurityTokenAuthOptions, UnAuthOptionsPRs are welcome! Please:
npm test to execute Vitest suites.SWEDBANK_DEBUG to avoid noisy defaults.MIT
FAQs
Node.js Swedbank API client (unofficial) based on walle89/swedbank-json
The npm package swedbank-json receives a total of 0 weekly downloads. As such, swedbank-json popularity was classified as not popular.
We found that swedbank-json demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.