IFSC lookup in Node.js with caching and clean errors
Normalise what users type, check the format before calling, cache branches for a day, and tell apart a mistyped code, an unknown branch and a network failure, in Node.js with no dependencies.
When a user enters an IFSC for a payout, you want the bank and branch on screen before they confirm. This is a small module for a Node.js server (Node 18 or later, no packages) that does the lookup properly: it cleans the input, refuses impossible codes without a request, caches answers, and returns errors your UI can show.
What a lookup returns
curl "https://api.dharun.dev/v1/ifsc/HDFC0000001?utm_medium=guide"
{
"data": {
"ifsc": "HDFC0000001",
"bank": {"code": "HDFC", "name": "HDFC Bank"},
"branch": "TULSIANI CHMBRS - NARIMAN PT",
"city": "Greater Mumbai",
"district": "Mumbai",
"state": "Maharashtra",
"micr": "400240003",
"swift": "HDFCINBB",
"imps": true, "neft": true, "rtgs": true, "upi": true
}
}
(Shortened; the address and contact come too.) Lowercase works as well: hdfc0000001 finds the same branch.
The module
// ifsc.js
const BASE = "https://api.dharun.dev/v1";
const DAY = 24 * 60 * 60 * 1000;
const cache = new Map(); // ifsc -> { at, branch }
export class IfscError extends Error {
constructor(kind, message) {
super(message);
this.kind = kind; // "format", "unknown", "unavailable"
}
}
// Users paste codes with spaces, dashes and the letter O for zero.
export function normaliseIfsc(raw) {
let code = String(raw).toUpperCase().replace(/[\s-]/g, "");
if (code.length === 11 && code[4] === "O") code = code.slice(0, 4) + "0" + code.slice(5);
return code;
}
export async function lookupIfsc(raw) {
const code = normaliseIfsc(raw);
if (!/^[A-Z]{4}0[A-Z0-9]{6}$/.test(code)) {
throw new IfscError("format", "An IFSC is 11 characters: four letters, then 0, then six letters or digits.");
}
const hit = cache.get(code);
if (hit && Date.now() - hit.at < DAY) return hit.branch;
let r;
try {
r = await fetch(`${BASE}/ifsc/${code}`, { signal: AbortSignal.timeout(8000) });
} catch {
throw new IfscError("unavailable", "Could not check the IFSC right now. You can continue; we will verify it later.");
}
if (r.status === 404) {
throw new IfscError("unknown", `No branch has the IFSC ${code}. Check it on the cheque book or passbook.`);
}
if (!r.ok) {
throw new IfscError("unavailable", "Could not check the IFSC right now. You can continue; we will verify it later.");
}
const branch = (await r.json()).data;
cache.set(code, { at: Date.now(), branch });
return branch;
}
Using it in a route
import express from "express";
import { lookupIfsc, IfscError } from "./ifsc.js";
const app = express();
app.get("/payout/ifsc/:code", async (req, res) => {
try {
const b = await lookupIfsc(req.params.code);
res.json({ bank: b.bank.name, branch: b.branch, city: b.city, neft: b.neft, imps: b.imps });
} catch (e) {
if (!(e instanceof IfscError)) throw e;
const status = { format: 400, unknown: 404, unavailable: 503 }[e.kind];
res.status(status).json({ error: e.message });
}
});
Decisions worth copying
- The format check is local. A code that cannot exist never costs a request, and the user gets the message at once. The API answers the same rule with a 400 if you skip it.
- 404 is an answer, not a failure. It means the Reserve Bank's list has no such branch: show it, do not retry.
- Network trouble should not block a payout form. Let the user continue and verify the code again before money moves.
- Cache for a day. Branch details change rarely; the list behind the API is refreshed weekly. One process-wide
Mapis enough for most servers; use Redis if you run several. - Check the payment system.
neft,imps,rtgsandupisay what the branch takes; a branch without NEFT should be refused before a NEFT payout.
Find a bank's code by name with GET /v1/banks?q=..., and see Handle India API errors, rate limits and retries for a general client.
The code in this guide is MIT-0: copy it into anything, no credit needed. Updated 2026-11-12.
APIs used: IFSC and banks.