When a checkout form receives a card number, the first useful question is often not whether the payment will be approved. It is whether the input is structurally plausible and which network rules should be shown to the user.
The open-source credit-card-brand-detector package provides that small client-side or server-side building block. It detects 11 brands, removes spaces and hyphens, and applies a Luhn checksum. It has zero runtime dependencies and exposes CommonJS functions for validation and brand detection.
This tutorial builds a minimal Node.js check, verifies the result with known test numbers, and explains what this kind of validation cannot tell you.
TL;DR
Install version 1.0.1, call validateCreditCard when you need both a boolean result and a brand, and call detectBrand when you only need the network name. The package does not contact a payment processor, authorize a transaction, tokenize data, or prove that a card exists.
Prerequisites
You need:
- Node.js 12 or newer. The package declares
>=12.0.0in its metadata. - npm.
- A terminal and a small JavaScript file.
The package is released under the MIT license. The examples below target the published npm package version 1.0.1, which is also the version I installed for this walkthrough.
Install the package
Create a directory for the example and install the pinned version:
mkdir card-check-example
cd card-check-example
npm init -y
npm install credit-card-brand-detector@1.0.1
Pinning the version makes the example reproducible. If you use a different version later, check its README and package metadata before copying the behavior into a production application.
Build the smallest useful check
Create check-card.js:
const {
validateCreditCard,
detectBrand,
getBrand,
} = require('credit-card-brand-detector');
const formattedVisa = '4532 0151-1283-0366';
const mastercard = '5555555555554444';
console.log(validateCreditCard(formattedVisa));
console.log(detectBrand(mastercard));
console.log(getBrand(mastercard));
Run it:
node check-card.js
The expected output is:
{ isValid: true, bandeira: 'Visa' }
Mastercard
Mastercard
The Portuguese property name bandeira is part of the package's public return shape. Keep it as-is when consuming the API, or map it to an application-specific name at your boundary.
Understand the two API paths
validateCreditCard(cardNumber) returns an object with isValid and bandeira. It first strips non-digit characters, rejects values shorter than 13 or longer than 19 digits, detects a brand from configured prefixes, and then runs the Luhn calculation.
detectBrand(cardNumber) returns a brand name or null. getBrand is an alias for the same function. This is useful when the UI needs to change an icon or helper message before the complete number is validated.
The implementation checks more specific ranges before broad ones. That matters for Brazilian brands such as Elo, whose configured prefixes can begin with 4, the same first digit used by Visa. A broad prefix check performed first could classify a supported Elo example as Visa.
Add an explicit application boundary
The package accepts a string and normalizes it internally, but your application should decide how to handle empty input, pasted content, and form errors. A small wrapper can keep the package's output separate from UI messages:
const { validateCreditCard } = require('credit-card-brand-detector');
function inspectCardInput(value) {
if (typeof value !== 'string' || value.trim() === '') {
return { ok: false, message: 'Enter a card number.' };
}
const result = validateCreditCard(value);
if (!result.bandeira) {
return { ok: false, message: 'The card network is not recognized.' };
}
if (!result.isValid) {
return { ok: false, message: 'The number failed its checksum.' };
}
return { ok: true, brand: result.bandeira };
}
console.log(inspectCardInput('4532015112830366'));
This wrapper deliberately reports a checksum failure as an input problem. It does not imply that a valid checksum means the card can be charged.
Reproduce the verification
The repository README documents these public examples. You can check the package independently with a one-line Node command:
node -e "const p=require('credit-card-brand-detector'); console.log(JSON.stringify({validVisa:p.validateCreditCard('4532015112830366'),mastercard:p.detectBrand('5555555555554444'),formatted:p.validateCreditCard('4532 0151-1283-0366'),unknown:p.detectBrand('1234567890123')}))"
The verified result is:
{"validVisa":{"isValid":true,"bandeira":"Visa"},"mastercard":"Mastercard","formatted":{"isValid":true,"bandeira":"Visa"},"unknown":null}
For an application test suite, add cases for formatting normalization, unknown prefixes, too-short values, each supported network you rely on, and known invalid checksums. Do not use real customer card numbers in tests or fixtures.
Why the check works
Brand detection is prefix matching against the rules in the package source. Luhn validation is a checksum calculation that doubles alternating digits from the right, subtracts nine when a doubled value exceeds nine, and checks whether the total is divisible by ten.
That division of responsibility is useful: prefix rules answer “which configured network might this resemble?” while Luhn answers “does this string satisfy the checksum?” Neither step performs authorization or a network lookup.
Failure modes and security boundaries
There are several important limitations:
- A valid Luhn result does not prove that a card is issued, active, funded, or owned by the person entering it.
- Prefix tables can become outdated as networks change ranges. Review the package source and release history before relying on a classification for business logic.
- The package strips non-digit characters. That is convenient for spaces and hyphens, but it should not replace input limits, rate limiting, or server-side validation.
- Never log full card numbers. Avoid putting them in analytics events, exception messages, URLs, screenshots, or support tickets.
- Browser-side validation is only a user-experience aid. Payment credentials should be handled through a PCI-compliant payment provider and tokenization flow appropriate to your system.
- This package has no payment gateway integration and makes no security guarantee for an application that uses it.
Use test numbers supplied by your payment provider for payment-flow tests. For a real checkout, send payment data only through the provider's documented secure collection mechanism instead of building your own storage path.
FAQ
Does this package charge a card?
No. It only analyzes a string locally.
Does a valid result mean the payment will succeed?
No. Authorization, funds, fraud checks, expiration, and issuer decisions happen elsewhere.
Can I use it with formatted input?
Yes. The implementation removes non-digit characters before checking length, prefixes, and the checksum.
Why is the result property named bandeira?
That is the package's documented public API. Map it in your own code if your application uses English field names.
Does it support every card network?
No. The README lists 11 supported brands. Treat null as “not recognized by this rule set,” not as proof that a number is invalid.
Takeaway
credit-card-brand-detector is a focused Node.js utility for early input feedback. Its useful boundary is narrow: normalize a candidate number, identify a configured brand, and run a checksum before the payment workflow begins. Keep that result separate from authorization, and keep payment data out of logs and application storage.
This article was prepared with AI assistance. The commands, package version, API behavior, and example output were checked against the public repository and the installed npm package before publication.
What additional boundary would you test before putting a card-number helper in front of a payment provider?
Top comments (0)