DEV Community

easysolutions906
easysolutions906

Posted on

How to Look Up and Validate Bank Routing Numbers Programmatically

How to Look Up and Validate Bank Routing Numbers Programmatically

Every ACH transfer, wire payment, and direct deposit in the United States requires a 9-digit ABA routing number. There are roughly 28,000 active routing numbers issued by the Federal Reserve. If your application handles payments, payroll, or bank account verification, you need a way to look up and validate these numbers reliably.

This article explains what ABA routing numbers are, how the checksum algorithm works, and how to look up routing numbers programmatically.

What is an ABA routing number

The American Bankers Association (ABA) routing transit number is a 9-digit code that identifies a financial institution. It was introduced in 1910 -- making it one of the oldest identification systems still in daily use. The Federal Reserve assigns and publishes routing numbers through its E-Payments Routing Directory.

A routing number encodes three pieces of information:

  • Digits 1-4: Federal Reserve routing symbol (identifies the Fed district and processing center)
  • Digits 5-8: ABA institution identifier (identifies the specific bank)
  • Digit 9: Check digit (validates the entire number)

For example, Chase Bank's primary routing number is 021000021. The first four digits (0210) indicate the Federal Reserve Bank of New York. The next four (0002) identify JPMorgan Chase. The final digit (1) is the check digit.

The checksum algorithm

ABA routing numbers use a weighted checksum with the repeating weights 3, 7, 1. Here is how it works:

Given a 9-digit routing number d1 d2 d3 d4 d5 d6 d7 d8 d9:

(3*d1 + 7*d2 + 1*d3 + 3*d4 + 7*d5 + 1*d6 + 3*d7 + 7*d8 + 1*d9) mod 10 = 0
Enter fullscreen mode Exit fullscreen mode

Let us validate Chase's routing number 021000021:

3*0 + 7*2 + 1*1 + 3*0 + 7*0 + 1*0 + 3*0 + 7*2 + 1*1
= 0 + 14 + 1 + 0 + 0 + 0 + 0 + 14 + 1
= 30
30 mod 10 = 0  -- valid
Enter fullscreen mode Exit fullscreen mode

Here is that algorithm in JavaScript:

const validateChecksum = (routingNumber) => {
  const d = routingNumber.split('').map(Number);
  if (d.length !== 9) { return false; }

  const sum = 3*d[0] + 7*d[1] + 1*d[2]
            + 3*d[3] + 7*d[4] + 1*d[5]
            + 3*d[6] + 7*d[7] + 1*d[8];

  return sum % 10 === 0;
};

validateChecksum('021000021'); // true
validateChecksum('021000022'); // false
Enter fullscreen mode Exit fullscreen mode

A valid checksum means the number is structurally correct, but it does not guarantee the routing number is currently active. For that, you need to look it up against the Federal Reserve directory.

Looking up routing numbers

The MCP server @easysolutions906/mcp-routing embeds the full Federal Reserve routing directory -- all 28,000+ active routing numbers with bank names, addresses, phone numbers, and status information.

Lookup by routing number

Looking up 021000021 returns:

{
  "routingNumber": "021000021",
  "bankName": "JPMORGAN CHASE",
  "city": "TAMPA",
  "state": "FL",
  "zipCode": "33610",
  "phoneNumber": "813-432-3700",
  "status": "active",
  "checksumValid": true
}
Enter fullscreen mode Exit fullscreen mode

Note that Chase's routing number resolves to Tampa, FL -- that is where their ACH processing center is located, not necessarily where your local branch is.

Search by bank name

Searching for "wells fargo" returns all routing numbers associated with Wells Fargo across different states:

{
  "query": "wells fargo",
  "results": [
    { "routingNumber": "121000248", "bankName": "WELLS FARGO BANK, NA", "state": "CA" },
    { "routingNumber": "111900659", "bankName": "WELLS FARGO BANK, NA", "state": "TX" },
    { "routingNumber": "021200025", "bankName": "WELLS FARGO BANK, NA", "state": "NY" }
  ],
  "totalResults": 47
}
Enter fullscreen mode Exit fullscreen mode

Large banks have dozens of routing numbers -- one or more per state they operate in.

Validate a routing number

The validation endpoint combines checksum verification with directory lookup:

{
  "routingNumber": "021000021",
  "valid": true,
  "checksumValid": true,
  "foundInDirectory": true,
  "bankName": "JPMORGAN CHASE"
}
Enter fullscreen mode Exit fullscreen mode

If a number passes checksum but is not in the directory, it may be a decommissioned routing number or a number for an institution that has merged or closed.

Setting up the MCP server

Add to your Claude Desktop or Cursor configuration:

{
  "mcpServers": {
    "routing": {
      "command": "npx",
      "args": ["-y", "@easysolutions906/mcp-routing"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

After restarting, you can ask natural language questions like:

  • "What bank has routing number 021000021?"
  • "Find all routing numbers for Bank of America in California"
  • "Is routing number 123456789 valid?"

The MCP server exposes routing_lookup, routing_search, and routing_validate tools.

Common use cases

Payment form validation. When a user enters a routing number in a payment form, validate the checksum immediately on the client side and verify against the directory on the server side. Show the bank name back to the user as confirmation they entered the right number.

Payroll processing. Before submitting an ACH batch, validate every routing number in the file. Catching an invalid routing number before submission prevents costly returns and delays.

Bank account verification. During account onboarding, look up the routing number and confirm the bank name matches what the user claims. This is a lightweight fraud signal -- it does not replace micro-deposit verification, but it catches obvious mismatches.

Compliance and audit. Regulatory requirements often include verifying that payment destinations are valid US financial institutions. A routing number lookup confirms the institution exists in the Federal Reserve directory.

Data freshness

The Federal Reserve updates the routing directory periodically as banks merge, close, or open new processing centers. The @easysolutions906/mcp-routing npm package includes a data-info endpoint that returns the build date and record count, so you can verify the data is current. The embedded data is rebuilt from the Fed source with each package update.

Routing number validation is one of those things that seems simple until you need it. The checksum algorithm is straightforward, but matching against the full directory, handling edge cases like merged banks, and returning useful metadata requires the complete dataset. Having it available as both an MCP tool and an npm package means you can integrate it wherever you need it.

Top comments (0)