Credit Card Number Format Validation with Regex
Learn how to validate credit card numbers using regular expressions, including Luhn algorithm and format-specific patterns.
Credit Card Number Format Validation with Regex
Credit card validation is essential for e-commerce, payment processing, and secure financial applications. While regex can validate card formats, remember that true validation requires the Luhn algorithm and API verification. In this comprehensive guide, we'll explore regex patterns for credit card format validation and best practices for secure payment processing.
Important Security Notice
⚠️ Security Warning: Never store or log complete credit card numbers. Only store the last 4 digits for verification purposes. Always use PCI DSS compliant payment processors for actual transactions.
Understanding Credit Card Formats
Credit cards follow specific formats based on card type:
| Card Type | Starts With | Length | Example |
|---|---|---|---|
| Visa | 4 | 13, 16, 19 | 4532015112830366 |
| Mastercard | 51-55, 2221-2720 | 16 | 5555555555554444 |
| American Express | 34, 37 | 15 | 378282246310005 |
| Discover | 6011, 65, 644-649, 622126-622925 | 16, 19 | 6011111111111117 |
| Diners Club | 36, 38 | 14 | 36382964596003 |
Basic Credit Card Pattern
Simple 13-19 Digit Pattern
^\d{13,19}$
Valid: 4532015112830366
Issue: Doesn't validate card type or format
With Spacing Support
^[\d\s-]{13,19}$
Accepts: 4532 0151 1283 0366, 4532-0151-1283-0366
Visa Card Validation
Basic Visa Pattern
^4\d{12}(?:\d{3})?$
Valid:
4532015112830366(16 digits)4929733781974550(16 digits)4929733781974(13 digits)
Breakdown:
^4- Must start with 4\d{12}- 12 more digits(?:\d{3})?- Optional 3 more digits (total 16)$- End of string
Visa with Spacing
^4\d{3}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$
Accepts: 4532 0151 1283 0366, 4532-0151-1283-0366
Mastercard Validation
Basic Mastercard Pattern
^(?:5[1-5]\d{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)\d{12}$
Valid:
5555555555554444(starts with 55)5105105105105100(starts with 51)2221000000000009(new range)
Breakdown:
5[1-5]\d{2}- 51-55222[1-9]- 2221-222922[3-9][0-9]- 2230-22992[3-6][0-9]{2}- 2300-269927[01][0-9]- 2700-27192720- Exactly 2720\d{12}- 12 more digits
Simplified Mastercard Pattern
^5[1-5]\d{14}|^(?:2[2-7]\d{2})\d{12}$
Easier to read but covers same ranges.
American Express Validation
Basic Amex Pattern
^3[47]\d{13}$
Valid:
378282246310005(starts with 37)371449635398431(starts with 37)341234567890123(starts with 34)
Breakdown:
^3[47]- Must start with 34 or 37\d{13}- Exactly 13 more digits$- End of string
Amex with Spacing
^3[47]\d{2}[- ]?\d{6}[- ]?\d{5}$
Accepts: 3782 822463 10005
Discover Card Validation
Basic Discover Pattern
^6(?:011|5\d{2})\d{12}|^(?:644-649|22)\d{13}|^(?:62212[6-9]|6221[3-9]\d|622[2-8]\d{2}|6229[01]\d|62292[0-5])\d{10}$
Valid:
6011111111111117(starts with 6011)6555555555554444(starts with 65)6440000000000000(new range)
Universal Credit Card Pattern
Detect Any Card Type
^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$
This pattern matches:
- Visa (4xxx...)
- Mastercard (51-55 or 2221-2720)
- American Express (34 or 37)
- Diners Club (36 or 38)
- Discover (6011, 65, 644-649)
Advanced Validation
Extract Card Type
function getCardType(number) {
const patterns = {
visa: /^4\d{12}(?:\d{3})?$/,
mastercard: /^(?:5[1-5]\d{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)\d{12}$/,
amex: /^3[47]\d{13}$/,
discover: /^6(?:011|5\d{2})\d{12}|^(?:644-649|22)\d{13}/,
diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
};
for (const [type, pattern] of Object.entries(patterns)) {
if (pattern.test(number)) {
return type;
}
}
return 'unknown';
}
Luhn Algorithm Implementation
Regex validates format but not checksum. Use Luhn algorithm:
function luhnCheck(cardNumber) {
const digits = cardNumber.replace(/\D/g, '');
let sum = 0;
let isEven = false;
for (let i = digits.length - 1; i >= 0; i--) {
let digit = parseInt(digits[i], 10);
if (isEven) {
digit *= 2;
if (digit > 9) {
digit -= 9;
}
}
sum += digit;
isEven = !isEven;
}
return sum % 10 === 0;
}
Combined Validation
function validateCreditCard(cardNumber) {
// Remove spaces and hyphens
const cleanNumber = cardNumber.replace(/[\s-]/g, '');
// Check basic format
const cardRegex = /^\d{13,19}$/;
if (!cardRegex.test(cleanNumber)) {
return { valid: false, error: 'Invalid format' };
}
// Check card type
const cardType = getCardType(cleanNumber);
if (cardType === 'unknown') {
return { valid: false, error: 'Unknown card type' };
}
// Check Luhn algorithm
if (!luhnCheck(cleanNumber)) {
return { valid: false, error: 'Invalid checksum' };
}
return {
valid: true,
cardType,
lastFour: cleanNumber.slice(-4)
};
}
Extracting from Text
Find Credit Cards in Text
\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})\b
Extracts: Card numbers from logs, forms, or text documents
Mask Credit Cards
(?<!\d)\d{12}(?!\d)
Replace with XXXXXXXXXXXX to mask first 12 digits
function maskCardNumber(cardNumber) {
return cardNumber.replace(/\d(?=\d{4})/g, 'X');
}
console.log(maskCardNumber('4532015112830366'));
// Output: XXXXXXXXXXXX0366
Best Practices
1. Never Store Full Numbers
// BAD: Storing full card number
database.save({ cardNumber: '4532015112830366' });
// GOOD: Store only last 4 digits
database.save({
cardLastFour: '0366',
cardType: 'visa',
token: paymentProcessorToken
});
2. Use PCI DSS Compliant Processors
// Always use payment processor APIs
async function processPayment(cardNumber) {
const response = await paymentProcessor.charge({
token: await tokenizeCard(cardNumber),
amount: 100.00
});
return response;
}
3. Validate Early, Don't Reveal Info
// GOOD: Generic error messages
if (!validateCreditCard(cardNumber).valid) {
return { error: 'Invalid card number' };
}
// BAD: Reveals card type or specific errors
if (cardType === 'amex') {
return { error: 'We do not accept American Express' };
}
4. Format for Display
function formatCardNumber(cardNumber, cardType) {
const cleanNumber = cardNumber.replace(/\D/g, '');
if (cardType === 'amex') {
// Amex: 4-6-5 format
return cleanNumber.replace(/^(\d{4})(\d{6})(\d{5})$/, '$1-$2-$3');
} else {
// Others: 4-4-4-4 format
return cleanNumber.replace(/(\d{4})(?=\d)/g, '$1-');
}
}
Common Pitfalls
Pitfall 1: Storing Full Numbers
// NEVER DO THIS
const savedCards = [
{ number: '4532015112830366', ... },
{ number: '5555555555554444', ... }
];
// INSTEAD DO THIS
const savedCards = [
{ lastFour: '0366', token: 'abc123', ... },
{ lastFour: '4444', token: 'def456', ... }
];
Pitfall 2: Not Implementing Luhn
// BAD: Only format validation
const isValid = cardRegex.test(cardNumber);
// GOOD: Format + Luhn
const isValid = cardRegex.test(cardNumber) && luhnCheck(cardNumber);
Pitfall 3: Revealing Card Information
// BAD: Reveals specific error
if (cardNumber.startsWith('3')) {
return 'Invalid American Express card';
}
// GOOD: Generic validation
if (!isValidCard(cardNumber)) {
return 'Invalid card number';
}
Testing Your Validation
Use our interactive Regex Tester with these test cases:
Valid Card Numbers (for testing only):
4532015112830366(Visa)5555555555554444(Mastercard)378282246310005(Amex)6011111111111117(Discover)3530111333300000(JCB)36382964596003(Diners Club)
Invalid Card Numbers:
1234567890123456(invalid format)4532015112830367(fails Luhn)555555555555(too short)55555555555555555555(too long)
Conclusion
Credit card validation with regex provides format checking, but remember:
- Use regex for format validation only - not actual card validation
- Implement Luhn algorithm - for checksum validation
- Never store full card numbers - only last 4 digits
- Use PCI DSS compliant processors - for actual transactions
- Provide generic error messages - don't reveal card information
The universal pattern ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11}$ provides comprehensive format validation.
For production use, always combine regex validation with:
- Luhn algorithm verification
- Payment processor API validation
- Secure tokenization
- PCI DSS compliance
Experiment with patterns using our Regex Tester, but remember: security comes first!
About the Author
The Regex Master Team consists of experienced developers and technical writers dedicated to simplifying regular expressions for everyone. We ensure all patterns are rigorously tested and verified to provide accurate, production-ready solutions.
Try It: Regex Tester
Use our interactive regex tester to experiment with the patterns you learned in this article. Test your regular expressions in real-time and see immediate results.