Regex for Credit Card Validation — Patterns for Visa, Mastercard, Amex & RuPay

Every major card network uses a different prefix range (the "IIN" or "BIN") and a different total digit length. Regex is a fast first-line check for these formats — useful for client-side UX before you hit a payment gateway — but it can never confirm that a card number is real. This guide covers the regex patterns for each network and explains why you still need the Luhn algorithm on top.

Card Number Formats by Network

Card networks are identified by the first one to six digits, and each network has a fixed set of valid lengths:

  • Visa — starts with 4, length 13 or 16 digits
  • Mastercard — starts with 51–55 or 2221–2720, length 16 digits
  • American Express (Amex) — starts with 34 or 37, length 15 digits
  • Discover — starts with 6011, 65, or 644–649, length 16 digits
  • RuPay (India) — starts with 60, 6521, 6522, 508, 353, or 356, length 16 digits

Regex Patterns for Each Network

// Visa: starts with 4, 13 or 16 digits
const visa = /^4[0-9]{12}(?:[0-9]{3})?$/;

// Mastercard: 51-55 or 2221-2720, 16 digits
const mastercard = /^(5[1-5][0-9]{14}|222[1-9][0-9]{12}|22[3-9][0-9]{13}|2[3-6][0-9]{14}|27[01][0-9]{13}|2720[0-9]{12})$/;

// American Express: 34 or 37, 15 digits
const amex = /^3[47][0-9]{13}$/;

// Discover: 6011, 65, or 644-649, 16 digits
const discover = /^6(?:011|5[0-9]{2}|4[4-9][0-9])[0-9]{12}$/;

// RuPay (common issuer ranges): 60, 6521, 6522, 508, 353, 356
const rupay = /^(60|6521|6522|508|353|356)[0-9]{13,14}$/;

Combined Detection Function

In practice you usually want to detect which network a number belongs to, then show the matching card logo in your UI:

function detectCardNetwork(number) {
  const clean = number.replace(/[\s-]/g, '');

  const patterns = {
    visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
    mastercard: /^5[1-5][0-9]{14}$/,
    amex: /^3[47][0-9]{13}$/,
    discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
    rupay: /^(60|6521|6522|508|353|356)[0-9]{13,14}$/,
  };

  for (const [network, pattern] of Object.entries(patterns)) {
    if (pattern.test(clean)) return network;
  }
  return 'unknown';
}

detectCardNetwork('4111 1111 1111 1111'); // 'visa'

Why Regex Alone Is Not Enough — the Luhn Algorithm

A regex match only proves the number "looks like" a card from a given network — it does not prove the number is mathematically valid. Every real card number includes a check digit computed with the Luhn algorithm. If a user mistypes a digit or transposes two digits, the Luhn check will almost always catch it, while a regex pattern will happily accept the typo as long as the length and prefix still match.

function isValidLuhn(number) {
  const digits = number.replace(/\D/g, '').split('').reverse().map(Number);

  const sum = digits.reduce((acc, digit, i) => {
    if (i % 2 === 1) {
      digit *= 2;
      if (digit > 9) digit -= 9;
    }
    return acc + digit;
  }, 0);

  return sum % 10 === 0;
}

isValidLuhn('4111111111111111'); // true  (Visa test number)
isValidLuhn('4111111111111112'); // false (fails checksum)

The correct validation pipeline is: strip spaces/dashes → check length and prefix with regex → run the Luhn check → then, for actual payments, let your payment gateway (Razorpay, Stripe, PayU) do the real authorization. Never rely on client-side checks alone for security-sensitive decisions.

Best Practices for Card Input Fields

  • Strip all non-digit characters before validating (users type spaces and dashes)
  • Run network detection first so you can show real-time card branding as they type
  • Apply the Luhn check only after the full length is entered, not on every keystroke
  • Never log or store raw card numbers — use tokenization from your payment provider
  • Always validate server-side too; client regex is only a UX convenience, not security

Frequently Asked Questions

Can regex fully validate a credit card number?

No. Regex can only confirm that a number matches the expected prefix and length pattern for a card network. It cannot verify that the number is a real, issuable card — that requires the Luhn checksum algorithm and, ultimately, the issuing bank.

What is the Luhn algorithm and why is it needed?

The Luhn algorithm is a checksum formula used to validate a range of identification numbers, including credit cards. It catches accidental single-digit errors and transpositions that a regex pattern cannot detect, since regex only checks format, not the mathematical checksum digit.

What regex matches a Visa card number?

Visa card numbers start with 4 and are 13 or 16 digits long. The regex ^4[0-9]{12}(?:[0-9]{3})?$ matches both lengths.

Try the Free AI Regex Generator

Describe any validation rule in plain English and get a working regex instantly — no signup required.

Related articles