npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

zapnow-all-world-bank-swift-codes

v1.0.1

Published

Latest deduplicated world SWIFT and bank code dataset plus scrape tooling

Readme

Zapnow All World Bank SWIFT Codes

This repository has two jobs:

  1. It publishes a ready-to-consume npm package named zapnow-all-world-bank-swift-codes.
  2. It contains the scraper and operator scripts used to rebuild the dataset from Wise, bank.codes, RemitFinder, and Open Banking Tracker.

The generated country files follow the same general CommonJS-per-country shape used by br99bry/swift-bank-codes, but this project uses the latest deduplicated dataset bundled under the newest finalswiftcodesdedup* folder.

Installation

npm install zapnow-all-world-bank-swift-codes

Package Usage

Example usage in Node.js:

const { albania, unitedStates, germany } = require("zapnow-all-world-bank-swift-codes");

console.log("SWIFT Codes for Albania:", albania);
console.log("SWIFT Codes for the United States:", unitedStates);
console.log("SWIFT Codes for Germany:", germany);

You can also import the full dataset object:

const swiftCodes = require("zapnow-all-world-bank-swift-codes");

console.log(Object.keys(swiftCodes).length);
console.log(swiftCodes.unitedKingdom.length);

The root package also exposes autocomplete helpers without changing the existing country export shape:

const swiftCodes = require("zapnow-all-world-bank-swift-codes");

const suggestions = swiftCodes.searchBanksIndex("citib");
const fullMatches = swiftCodes.searchBanks("CITIUS33", { limit: 5 });

console.log(suggestions[0]);
console.log(fullMatches[0]);

searchBanksIndex() returns lightweight autocomplete rows:

{
  countryKey: "unitedStates",
  country: "United States",
  countryCode: "US",
  swiftCode: "CITIUS33",
  bankName: "CITIBANK N.A.",
  city: "NEW YORK",
  branch: "",
  label: "CITIBANK N.A. (CITIUS33)",
  value: "CITIUS33",
  score: 3
}

searchBanks() uses the prebuilt search index to find matches, then hydrates the top results back to the full underlying bank rows.

If you only want one country and do not want to load the whole world dataset, use country subpath exports:

const unitedStates = require("zapnow-all-world-bank-swift-codes/countries/unitedStates");
const germany = require("zapnow-all-world-bank-swift-codes/countries/germany");

You can also import the dedicated search subpath directly:

const { searchBanks, searchBanksIndex, searchIndex } = require("zapnow-all-world-bank-swift-codes/search");

The package root automatically resolves the newest local finalswiftcodesdedup* folder, so after you generate a new final dataset you do not need to change imports in downstream projects.

Autocomplete Workflows

The package supports two different autocomplete patterns:

  • searchBanksIndex(query, options): fastest path for suggestion lists, dropdowns, and typeahead menus
  • searchBanks(query, options): best when you want the final selected row with full bank details

Use them like this:

  • While the user is typing, call searchBanksIndex()
  • After the user selects a suggestion or enters a final SWIFT code, call searchBanks()

When To Use Which API

Use searchBanksIndex() when:

  • You are building a textbox suggestion dropdown
  • You only need label, value, bankName, swiftCode, country, and city
  • You want lower memory and faster response for autocomplete

Use searchBanks() when:

  • The user already picked a suggestion
  • You want the complete row with fields like Address, Branch, Connection, and Postcode
  • You want to validate a final SWIFT code or hydrate a selected item into full bank details

Suggested Backend Pattern

For most apps, the easiest and safest pattern is:

  1. Keep this package on the server
  2. Expose a small autocomplete API endpoint
  3. Let the browser call your endpoint as the user types

Example Express route:

const express = require("express");
const { searchBanksIndex, searchBanks } = require("zapnow-all-world-bank-swift-codes/search");

const app = express();

app.get("/api/swift/autocomplete", (req, res) => {
  const q = String(req.query.q || "").trim();
  const country = req.query.country ? String(req.query.country) : undefined;

  if (q.length < 2) {
    return res.json([]);
  }

  const results = searchBanksIndex(q, {
    limit: 10,
    country,
  });

  res.json(results);
});

app.get("/api/swift/resolve", (req, res) => {
  const swift = String(req.query.swift || "").trim();
  if (!swift) {
    return res.status(400).json({ error: "Missing swift query parameter" });
  }

  const matches = searchBanks(swift, { limit: 1 });
  res.json(matches[0] || null);
});

Why this pattern works well:

  • Your frontend does not need to bundle the full world dataset
  • The UI stays lightweight
  • You can apply rate limiting, logging, and caching at your API layer

Suggested Frontend Textbox Flow

A good autocomplete UI flow usually looks like this:

  1. Wait until the user has typed at least 2 characters
  2. Debounce requests by about 150-300ms
  3. Call your autocomplete endpoint with the current query
  4. Render label in the dropdown
  5. Store value or swiftCode when the user selects an item
  6. Optionally call a resolve endpoint to get the full row

Example browser flow:

async function fetchSwiftSuggestions(query, country) {
  const params = new URLSearchParams({ q: query });
  if (country) params.set("country", country);

  const response = await fetch(`/api/swift/autocomplete?${params.toString()}`);
  if (!response.ok) throw new Error("Autocomplete request failed");
  return response.json();
}

async function resolveSwift(swift) {
  const response = await fetch(`/api/swift/resolve?swift=${encodeURIComponent(swift)}`);
  if (!response.ok) throw new Error("Resolve request failed");
  return response.json();
}

Country-Scoped Autocomplete

If your UI already knows the country, pass that into the search so the result list is smaller and more relevant.

Examples:

const { searchBanksIndex } = require("zapnow-all-world-bank-swift-codes/search");

const usResults = searchBanksIndex("citi", {
  country: "US",
  limit: 10,
});

const germanyResults = searchBanksIndex("deut", {
  country: "germany",
  limit: 10,
});

The country option accepts:

  • ISO code like US, DE, GB
  • normalized country name like united states, germany
  • country key like unitedStates, germany

You can also pass an array if your product supports a regional filter:

const results = searchBanksIndex("bank", {
  country: ["US", "CA", "MX"],
  limit: 15,
});

Country-Only Lazy Loading

If you do not want a world autocomplete and only need a single country dataset, load the country directly and filter it yourself:

const unitedStates = require("zapnow-all-world-bank-swift-codes/countries/unitedStates");

function localAutocomplete(query) {
  const q = query.trim().toLowerCase();
  return unitedStates
    .filter((row) =>
      row["Bank Name"]?.toLowerCase().includes(q) ||
      row["SWIFT Code"]?.toLowerCase().startsWith(q)
    )
    .slice(0, 10)
    .map((row) => ({
      label: `${row["Bank Name"]} (${row["SWIFT Code"]})`,
      value: row["SWIFT Code"],
      city: row["City"],
      country: row["Country"],
    }));
}

This pattern is useful when:

  • Your app only supports one country
  • You want to lazy-load a country route by route
  • You are building a small admin tool and want simple local filtering

Recommended Result Shape For UI Components

Most autocomplete UI libraries work well with this shape:

{
  label: "CITIBANK N.A. (CITIUS33)",
  value: "CITIUS33",
  swiftCode: "CITIUS33",
  bankName: "CITIBANK N.A.",
  country: "United States",
  city: "NEW YORK"
}

That means searchBanksIndex() can usually be returned to the frontend almost as-is.

Performance Notes

If you care about performance, use these rules:

  • Prefer require("zapnow-all-world-bank-swift-codes/search") for autocomplete endpoints
  • Prefer searchBanksIndex() for live typing
  • Prefer searchBanks() only for final hydration or validation
  • Prefer countries/<countryKey> imports when your use case is country-specific
  • Avoid shipping the full root package directly into browser bundles unless you intentionally want the full dataset client-side

Common Patterns

Backend autocomplete only:

const { searchBanksIndex } = require("zapnow-all-world-bank-swift-codes/search");

Backend autocomplete plus final selected-row lookup:

const { searchBanksIndex, searchBanks } = require("zapnow-all-world-bank-swift-codes/search");

Single-country lazy route:

const unitedKingdom = require("zapnow-all-world-bank-swift-codes/countries/unitedKingdom");

Full dataset analytics or offline processing:

const swiftCodes = require("zapnow-all-world-bank-swift-codes");

Repository Layout

  • build-package-artifacts.cjs: regenerates the country subpath wrappers and the prebuilt search index from the newest final dedup folder.
  • scrape-swift-codes.js: main scraper for Wise, bank.codes, RemitFinder, and Open Banking Tracker.
  • merge-swift-outputs.js: merges multiple scrape output folders into one deduplicated working folder.
  • generate-global-report.cjs: generates the final text report with per-country totals, bank lists, and optional GitHub comparison.
  • watch-wise-finalize.ps1: watches parallel Wise jobs, merges temp outputs, builds the final dedup folder, clones the comparison repo, and writes the final report.
  • countries: generated country-by-country subpath exports such as countries/unitedStates.cjs.
  • search-index.cjs: generated lightweight autocomplete search index.
  • search: generated search helper export surface.
  • wise-country-meta.json: fallback country metadata for Wise when the live Wise country index cannot be read.
  • finalswiftcodesdedup*: timestamped final world deduplicated dataset snapshots. The package resolves the newest one automatically.
  • reports: final generated text reports.

Requirements

  • Node.js 20+ recommended.
  • npm install already ran in this repo before the current package snapshot, but if you clone fresh you should run it again.
  • Internet access is required for scraping.
  • Cloudflare Browser Rendering credentials are strongly recommended for Wise recovery.
  • Firecrawl credentials are recommended as the last fallback path for Wise.
  • Git is required only if you want the comparison report against br99bry/swift-bank-codes.

Environment Setup

The scraper automatically loads .env.vars from the repo root before starting.

Create or update .env.vars like this:

# Cloudflare Browser Rendering
CF_API_TOKEN=your_cloudflare_api_token
CF_ACCOUNT_ID=your_cloudflare_account_id

# Firecrawl
FIRECRAWL_API_KEY=your_firecrawl_api_key

Supported aliases are also accepted:

  • Cloudflare token: CF_API_TOKEN, CLOUDFLARE_API_TOKEN, or CF_API
  • Cloudflare account: CF_ACCOUNT_ID, CLOUDFLARE_ACCOUNT_ID, or CLOUDFLARE_ACCOUNT
  • Optional Cloudflare Browser Rendering endpoint hint: CF_BROWSER_RENDER_URL
  • Firecrawl token: FIRECRAWL_API_KEY or FIRECRAWL_TOKEN

Important behavior:

  • .env.vars lines starting with # are ignored.
  • Quoted values are supported.
  • If you provide CF_API, the scraper maps it to CF_API_TOKEN.
  • If you provide CLOUDFLARE_ACCOUNT, the scraper maps it to CF_ACCOUNT_ID.
  • If Cloudflare account ID is not set but a Cloudflare token is present, the scraper will try to resolve the account automatically via the Cloudflare accounts API.

How The Scraper Works

scrape-swift-codes.js is incremental. It does not assume every run is fresh.

  • It loads .env.vars.
  • It parses the command-line flags.
  • It loads any existing country files already present in --out.
  • It runs the selected providers and merges new rows into the existing in-memory dataset.
  • It writes the merged working dataset back to --out.
  • It writes index.js in that same output folder.
  • Unless you disable it, it also writes a new timestamped final deduplicated snapshot under finalswiftcodesdedup*.

Deduplication is based on normalized SWIFT codes. If the same SWIFT record is found from multiple providers, the scripts keep the better non-empty values field by field.

Provider behavior:

  • Wise uses the HTML page flow, not the blocked gateway/swift-data JSON flow.
  • Wise supports direct fetches plus adaptive fallback to Cloudflare Browser Rendering and then Firecrawl.
  • bank.codes can optionally do deeper detail parsing with --with-bankcodes-details.
  • RemitFinder contributes additional rows and fields that get merged into the same country outputs.
  • Open Banking Tracker contributes country-page SWIFT datasets sourced from its /swift-codes directory and __NEXT_DATA__ payloads.

Output Folders

There are two important output types:

  • Working output folder: whatever you pass in --out, for example swiftCodesGlobal
  • Final snapshot folder: a new finalswiftcodesdedup* directory created at the end of a run unless you disable it

Use the working output folder when:

  • You want resumable/incremental scraping
  • You want to run providers in separate stages
  • You want to merge several temporary outputs later

Use the final dedup folder when:

  • You want the publishable dataset snapshot
  • You want a stable output to compare against another repo
  • You want the package to export the newest finished dataset

CLI Reference

Main command:

node .\scrape-swift-codes.js [flags]

You can also use the package scripts:

npm run scrape -- [flags]
npm run merge -- [flags]
npm run report -- [flags]

Key scraper flags:

| Flag | Meaning | | --- | --- | | --providers=wise,bankcodes,remitfinder,openbankingtracker | Selects which providers to run. Aliases openbanking and obt also work for Open Banking Tracker. | | --out=<dir> | Working output directory. Existing data in that folder is loaded and merged. | | --workers=<n> | Country-level worker pool. Also used to limit Cloudflare and Firecrawl parallel calls. | | --concurrency=<n> | In-country concurrency for detail/page tasks. | | --countries=<csv> | Filters to specific countries. Accepts ISO code, slug, or normalized name. | | --with-bankcodes-details | Enables deeper bank.codes detail enrichment. | | --quiet | Reduces logging. | | --no-dedup-output | Skips writing a final finalswiftcodesdedup* folder. Useful for temporary lanes. | | --dedup-output-base=<name> | Controls the final dedup folder name. Use 'finalswiftcodesdedup$timestamp' in PowerShell if you want the literal $timestamp placeholder. |

Wise-specific flags:

| Flag | Meaning | | --- | --- | | --state-file=<file> | Path to Wise recovery state JSON. | | --resume | Resume from existing Wise state. This is the default. | | --no-resume | Ignore previous Wise state and start the selected Wise scope from scratch. | | --chunk-size=<n> | Number of countries per Wise checkpoint chunk. Smaller values checkpoint more often. | | --wise-transport=auto | Base transport mode. Supported: auto, direct-first, cloudflare-first, cloudflare-only, firecrawl-first, firecrawl-only. | | --wise-auto-cloudflare | Automatically escalate Wise traffic to Cloudflare after repeated blocks. Default is on. | | --no-wise-auto-cloudflare | Disables automatic Cloudflare escalation. | | --wise-auto-firecrawl | Automatically escalate Wise traffic to Firecrawl after repeated blocks. Default is on. | | --no-wise-auto-firecrawl | Disables automatic Firecrawl escalation. | | --wise-block-threshold=<n> | Number of consecutive Wise blocks before transport escalation. | | --wise-locale=<locale> | Wise locale prefix used for HTML pages. Default is us. | | --wise-max-pages=<n> | Maximum Wise pagination depth per country or bank listing. | | --weight-source=<dir> | Directory used to estimate country size so heavier countries can be pushed later. | | --heavy-last | Runs heavier Wise countries later. Default is on. | | --no-heavy-last | Disables heavy-country-last ordering. |

Recommended Workflows

1. Single-Country Wise Smoke Test

Use this before large runs to validate that Wise HTML scraping, Cloudflare fallback, and output writing all work in your current environment.

node .\scrape-swift-codes.js --providers=wise --countries=albania --out=swiftCodesSmoke --state-file=wise-smoke-state.json --workers=1 --concurrency=3 --chunk-size=1

What this does:

  • Runs only Wise
  • Restricts the scrape to Albania
  • Writes the working output to swiftCodesSmoke
  • Saves Wise recovery state in wise-smoke-state.json

1b. Single-Country Open Banking Tracker Smoke Test

Use this to validate the Open Banking Tracker provider before running a larger global merge.

node .\scrape-swift-codes.js --providers=openbankingtracker --countries=AL,SG,US --out=swiftCodesOpenBankingSmoke --workers=3 --concurrency=3 --no-dedup-output

What this does:

  • Runs only Open Banking Tracker
  • Scrapes the requested country pages from https://www.openbankingtracker.com/swift-codes
  • Writes a temporary working folder without creating a new final dedup snapshot
  • Lets you inspect the provider-specific rows before you merge them into a larger baseline
  • Checkpoints after every country because --chunk-size=1

If the machine stops or the process is interrupted, run the exact same command again to resume.

2. One-Shot Global Run

This is the simplest full run if you want one command and are comfortable letting it run for a long time.

node .\scrape-swift-codes.js --providers=wise,bankcodes,remitfinder,openbankingtracker --out=swiftCodesGlobal --state-file=wise-global-state.json --workers=5 --concurrency=8 --chunk-size=3 --with-bankcodes-details

What this does:

  • Starts with Wise country discovery
  • Scrapes Wise first
  • Scrapes bank.codes
  • Scrapes RemitFinder
  • Scrapes Open Banking Tracker
  • Merges everything into swiftCodesGlobal
  • Writes a final deduplicated finalswiftcodesdedup* folder automatically

This is the easiest path if you are not splitting the work manually.

3. Safer Staged Global Run

This is the recommended operator flow when Wise is the most fragile provider and you want clean recovery points.

Step 1, run Wise only into the global working folder:

node .\scrape-swift-codes.js --providers=wise --out=swiftCodesGlobal --state-file=wise-global-state.json --workers=5 --concurrency=8 --chunk-size=3 --no-dedup-output

Step 2, after Wise is complete, enrich the same working folder with bank.codes, RemitFinder, and Open Banking Tracker:

node .\scrape-swift-codes.js --providers=bankcodes,remitfinder,openbankingtracker --out=swiftCodesGlobal --workers=5 --concurrency=8 --with-bankcodes-details

Why this staged flow is useful:

  • Wise gets its own resumable state file
  • You avoid creating extra intermediate finalswiftcodesdedup* folders during the long Wise phase
  • The second run automatically loads the Wise output already written in swiftCodesGlobal
  • The second run creates the final dedup snapshot at the end

4. Running Only Specific Countries

The --countries filter accepts several forms:

  • ISO code: US, DE, BR
  • Wise-style slug: united-states, germany, brazil
  • Normalized country name: united states, germany, brazil

Example:

node .\scrape-swift-codes.js --providers=wise,bankcodes,remitfinder,openbankingtracker --countries=US,CA,mexico,brazil --out=swiftCodesAmericas --state-file=wise-americas-state.json --workers=4 --concurrency=6 --chunk-size=2

5. Resuming After A Stop, Crash, Or Throttle Event

Wise resume is on by default.

If the machine turns off or the process is interrupted:

  • Do not delete the working output folder
  • Do not delete the Wise state file
  • Re-run the same Wise command

Example resume:

node .\scrape-swift-codes.js --providers=wise --out=swiftCodesGlobal --state-file=wise-global-state.json --workers=5 --concurrency=8 --chunk-size=3 --no-dedup-output

When resuming:

  • Already completed Wise countries are skipped
  • Failed or remaining countries stay in the recovery plan
  • Existing output files in --out are loaded first and preserved
  • The transport state also resumes, including whether Cloudflare or Firecrawl had already been promoted

If you really want to restart a Wise scope from zero, add --no-resume.

6. Parallel Wise Runs

For very large backfills, it is safer to split Wise into several non-overlapping country lanes instead of letting multiple processes write into the same folder.

Rules for safe parallel Wise lanes:

  • Each lane must have a unique --out folder.
  • Each lane must have a unique --state-file.
  • Each lane should normally use --no-dedup-output.
  • Country lists must not overlap across lanes.
  • Merge the temp outputs only after all lanes finish.

Example three-lane setup:

Lane A:

node .\scrape-swift-codes.js --providers=wise --countries=austria,ireland,switzerland,germany --out=swiftCodesWise_A --state-file=wise_A.json --workers=2 --concurrency=6 --chunk-size=1 --no-dedup-output

Lane B:

node .\scrape-swift-codes.js --providers=wise --countries=belgium,singapore,hong-kong,united-kingdom --out=swiftCodesWise_B --state-file=wise_B.json --workers=2 --concurrency=6 --chunk-size=1 --no-dedup-output

Lane C:

node .\scrape-swift-codes.js --providers=wise --countries=spain,bangladesh,australia,italy --out=swiftCodesWise_C --state-file=wise_C.json --workers=2 --concurrency=6 --chunk-size=1 --no-dedup-output

When all lanes finish, merge them:

node .\merge-swift-outputs.js --base=swiftCodesGlobal --from=swiftCodesWise_A --from=swiftCodesWise_B --from=swiftCodesWise_C

Then enrich that merged working folder with the non-Wise providers:

node .\scrape-swift-codes.js --providers=bankcodes,remitfinder,openbankingtracker --out=swiftCodesGlobal --workers=5 --concurrency=8 --with-bankcodes-details

7. Watching Parallel Wise Lanes And Auto-Finalizing

watch-wise-finalize.ps1 is useful after you start several Wise-only temp lanes. It polls every 15 minutes by default, waits for all active Wise scraper processes to disappear, then runs the finish steps automatically.

What the watcher does after the last Wise lane ends:

  • Merges all temp Wise folders into swiftCodesGlobal
  • Builds a new finalswiftcodesdedup<timestamp> folder
  • Clones the latest br99bry/swift-bank-codes repo into a temp comparison folder
  • Generates a final report in reports

Example:

powershell -ExecutionPolicy Bypass -File .\watch-wise-finalize.ps1 -Workspace "C:\Users\MeetMo.io\swift-code-scrapper" -MasterLog "logs\wise_parallel_master.log" -TempDirs swiftCodesWise_A,swiftCodesWise_B,swiftCodesWise_C -PollSeconds 900

Notes:

  • The script now creates logs and reports automatically if they do not exist.
  • -PollSeconds 900 means a 15-minute check interval.
  • -MasterLog is required by the script and should point to the master batch log you are using for the run.
  • The watcher does not run bank.codes or RemitFinder by itself. Use it only when swiftCodesGlobal already contains the non-Wise data you want preserved, or when the Wise temp folders represent the last missing part of your dataset.

8. Manual Final Snapshot Build

If you already have a finished working folder and want to create a clean final snapshot manually, do this in PowerShell:

$stamp = Get-Date -Format 'yyyyMMdd_HHmmss'
node .\merge-swift-outputs.js --base="finalswiftcodesdedup$stamp" --from=swiftCodesGlobal

This creates a new final snapshot folder without re-running the scraper.

9. Manual Report Generation

If you want the final text report with per-country bank names, total banks, total entries, and GitHub repo comparison, first clone the comparison repo:

git clone --depth 1 https://github.com/br99bry/swift-bank-codes.git repo-compare

Then generate the report:

$stamp = Get-Date -Format 'yyyyMMdd_HHmmss'
node .\generate-global-report.cjs --local=finalswiftcodesdedup20260330_020938 --compare=repo-compare\swiftCodes --out="reports\swift-global-report-$stamp.txt"

You can omit --compare if you want a report for the local dataset only.

10. Regenerating Package Search Artifacts

After a new final dedup folder exists, regenerate the autocomplete helpers and country subpath wrappers so the npm package stays aligned with the newest dataset:

node .\build-package-artifacts.cjs

This rebuilds:

  • search-index.cjs
  • countries\*.cjs
  • countries\index.cjs

11. Publishing The Refreshed Package

After a fresh final dataset exists, the package root automatically points to the newest finalswiftcodesdedup* folder.

Recommended validation before publishing:

node -e "const data = require('./'); console.log(Object.keys(data).length)"
node -e "const { searchBanksIndex } = require('./search'); console.log(searchBanksIndex('citi', { limit: 3 }).length)"
npm pack --dry-run

Recommended release sequence:

  1. Finish or merge the newest final finalswiftcodesdedup* folder.
  2. Run node .\build-package-artifacts.cjs.
  3. Run the validation commands above.
  4. Commit the updated package files.
  5. Publish or push.

The package configuration includes the latest final dedup folder, the generated country subpath wrappers, and the generated search index, so new npm packs stay autocomplete-ready.

Wise Transport Strategy In Practice

Wise is the provider most likely to throttle or block.

The current Wise strategy is:

  • Try direct HTML fetches first unless you explicitly change the base transport mode
  • Track consecutive block/challenge events
  • Escalate to Cloudflare Browser Rendering when blocking crosses the configured threshold
  • Escalate to Firecrawl if Cloudflare is still not enough or if you choose a Firecrawl-first mode
  • Persist the transport state in the Wise recovery JSON so a resumed run does not forget that it was blocked

This is why the recommended pattern is:

  • Start with Wise-only runs
  • Keep chunk sizes relatively small
  • Use separate state files
  • Split heavy countries across separate lanes when you need speed
  • Leave bank.codes and RemitFinder for after the Wise phase is stable

Troubleshooting

If Wise looks blocked:

  • Confirm .env.vars contains valid CF_API_TOKEN and CF_ACCOUNT_ID
  • Confirm .env.vars contains FIRECRAWL_API_KEY
  • Reduce --workers
  • Reduce --concurrency
  • Reduce --chunk-size
  • Re-run the same command and let resume continue from the current state
  • Move the remaining countries into smaller parallel lanes with separate output folders

If you want fewer intermediate folders:

  • Use --no-dedup-output on temporary or Wise-only runs
  • Build the final snapshot only after all provider data is in the working folder

If you want cleaner reporting:

  • Generate the report from the final dedup folder, not from temporary lane folders
  • Clone a fresh copy of br99bry/swift-bank-codes before running the comparison report

Current Bundled Dataset

The repository currently ships with:

  • Latest final dedup folder: finalswiftcodesdedup20260330_020938
  • Final report folder: reports

Downstream imports always come from the package root:

const swiftCodes = require("zapnow-all-world-bank-swift-codes");

For frontend or route-level lazy loading, prefer the country subpath exports:

const unitedStates = require("zapnow-all-world-bank-swift-codes/countries/unitedStates");