<p>I'm trying to figure out how to detect the type of credit card based purely on its number. Does anyone know of a definitive, reliable way to find this?</p>

[{'answer_id': 72801, 'author': 'senfo', 'author_id': 10792, 'author_profile': 'https://Stackoverflow.com/users/10792', 'pm_score': 11, 'selected': True, 'text': '<p>The credit/debit card number is referred to as a <strong>PAN</strong>, or <em>Primary Account Number</em>.  The first six digits of the PAN are taken from the <strong>IIN</strong>, or <em>Issuer Identification Number</em>, belonging to the issuing bank (IINs were previously known as BIN — Bank Identification Numbers — so you may see references to that terminology in some documents).  These six digits are subject to an international standard, <a href="http://en.wikipedia.org/wiki/ISO/IEC_7812" rel="noreferrer">ISO/IEC 7812</a>, and can be used to determine the type of card from the number.</p>\n<p>Unfortunately the actual ISO/IEC 7812 database is not publicly available, however, there are unofficial lists, both commercial and free, including <a href="http://en.wikipedia.org/wiki/Bank_card_number" rel="noreferrer">on Wikipedia</a>.</p>\n<p>Anyway, to detect the type from the number, you can use a regular expression like the ones below: <a href="http://www.regular-expressions.info/creditcard.html" rel="noreferrer">Credit for original expressions</a></p>\n<p><strong>Visa:</strong> <code>^4[0-9]{6,}$</code> Visa card numbers start with a 4.</p>\n<p><strong>MasterCard:</strong> <code>^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$</code> Before 2016, MasterCard numbers start with the numbers 51 through 55, <strong>but this will only detect MasterCard credit cards</strong>; there are other cards issued using the MasterCard system that do not fall into this IIN range.  In 2016, they will add numbers in the range (222100-272099).</p>\n<p><strong>American Express:</strong> <code>^3[47][0-9]{5,}$</code> American Express card numbers start with 34 or 37.</p>\n<p><strong>Diners Club:</strong> <code>^3(?:0[0-5]|[68][0-9])[0-9]{4,}$</code> Diners Club card numbers begin with 300 through 305, 36 or 38. There are Diners Club cards that begin with 5 and have 16 digits. These are a joint venture between Diners Club and MasterCard and should be processed like a MasterCard.</p>\n<p><strong>Discover:</strong> <code>^6(?:011|5[0-9]{2})[0-9]{3,}$</code> Discover card numbers begin with 6011 or 65.</p>\n<p><strong>JCB:</strong> <code>^(?:2131|1800|35[0-9]{3})[0-9]{3,}$</code> JCB cards begin with 2131, 1800 or 35.</p>\n<p>Unfortunately, there are a number of card types processed with the MasterCard system that do not live in MasterCard’s IIN range (numbers starting 51...55); the most important case is that of Maestro cards, many of which have been issued from other banks’ IIN ranges and so are located all over the number space.  As a result, <strong>it may be best to assume that any card that is not of some other type you accept must be a MasterCard</strong>.</p>\n<p><strong>Important</strong>: card numbers do vary in length; for instance, Visa has in the past issued cards with 13 digit PANs and cards with 16 digit PANs.  Visa’s documentation currently indicates that it may issue or may have issued numbers with between 12 and 19 digits.  <strong>Therefore, you should not check the length of the card number, other than to verify that it has at least 7 digits</strong> (for a complete IIN plus one check digit, which should match the value predicted by <a href="http://en.wikipedia.org/wiki/Luhn_algorithm" rel="noreferrer">the Luhn algorithm</a>).</p>\n<p>One further hint: <strong>before processing a cardholder PAN, strip any whitespace and punctuation characters from the input</strong>.  Why?  Because it’s typically <em>much</em> easier to enter the digits in groups, similar to how they’re displayed on the front of an actual credit card, i.e.</p>\n<pre><code>4444 4444 4444 4444\n</code></pre>\n<p>is much easier to enter correctly than</p>\n<pre><code>4444444444444444\n</code></pre>\n<p>There’s really no benefit in chastising the user because they’ve entered characters you don\'t expect here.</p>\n<p><strong>This also implies making sure that your entry fields have room for <em>at least</em> 24 characters, otherwise users who enter spaces will run out of room.</strong>  I’d recommend that you make the field wide enough to display 32 characters and allow up to 64; that gives plenty of headroom for expansion.</p>\n<p>Here\'s an image that gives a little more insight:</p>\n<p><strong>UPDATE (2016):</strong> Mastercard is to implement new BIN ranges starting <a href="http://achpayment.net/" rel="noreferrer">Ach Payment</a>.</p>\n<p><img src="https://i.stack.imgur.com/Cu7PG.jpg" alt="Credit Card Verification" /></p>\n'}, {'answer_id': 73248, 'author': 'Shoban', 'author_id': 12178, 'author_profile': 'https://Stackoverflow.com/users/12178', 'pm_score': 3, 'selected': False, 'text': '<p>The first numbers of the credit card can be used to approximate the vendor:</p>\n\n<ul>\n<li>Visa: 49,44 or 47</li>\n<li>Visa electron: 42, 45, 48, 49</li>\n<li>MasterCard: 51</li>\n<li>Amex:34</li>\n<li>Diners: 30, 36, 38</li>\n<li>JCB: 35</li>\n</ul>\n'}, {'answer_id': 1780382, 'author': 'Simon_Weaver', 'author_id': 16940, 'author_profile': 'https://Stackoverflow.com/users/16940', 'pm_score': 4, 'selected': False, 'text': '<p>Here\'s <a href="http://www.codeproject.com/Articles/20271/Ultimate-NET-Credit-Card-Utility-Class" rel="noreferrer">Complete C# or VB code for all kinds of CC related things</a> on codeproject.</p>\n\n<ul>\n<li>IsValidNumber</li>\n<li>GetCardTypeFromNumber</li>\n<li>GetCardTestNumber</li>\n<li>PassesLuhnTest</li>\n</ul>\n\n<p>This article has been up for a couple years with no negative comments.</p>\n'}, {'answer_id': 2408585, 'author': 'Rashy', 'author_id': 289587, 'author_profile': 'https://Stackoverflow.com/users/289587', 'pm_score': 4, 'selected': False, 'text': '<p>Check this out:</p>\n\n<p><a href="http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B" rel="nofollow noreferrer">http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B</a></p>\n\n<pre class="lang-js prettyprint-override"><code>function isValidCreditCard(type, ccnum) {\n    /* Visa: length 16, prefix 4, dashes optional.\n    Mastercard: length 16, prefix 51-55, dashes optional.\n    Discover: length 16, prefix 6011, dashes optional.\n    American Express: length 15, prefix 34 or 37.\n    Diners: length 14, prefix 30, 36, or 38. */\n\n    var re = new Regex({\n        "visa": "/^4\\d{3}-?\\d{4}-?\\d{4}-?\\d",\n        "mc": "/^5[1-5]\\d{2}-?\\d{4}-?\\d{4}-?\\d{4}$/",\n        "disc": "/^6011-?\\d{4}-?\\d{4}-?\\d{4}$/",\n        "amex": "/^3[47]\\d{13}$/",\n        "diners": "/^3[068]\\d{12}$/"\n    }[type.toLowerCase()])\n\n    if (!re.test(ccnum)) return false;\n    // Remove all dashes for the checksum checks to eliminate negative numbers\n    ccnum = ccnum.split("-").join("");\n    // Checksum ("Mod 10")\n    // Add even digits in even length strings or odd digits in odd length strings.\n    var checksum = 0;\n    for (var i = (2 - (ccnum.length % 2)); i &lt;= ccnum.length; i += 2) {\n        checksum += parseInt(ccnum.charAt(i - 1));\n    }\n    // Analyze odd digits in even length strings or even digits in odd length strings.\n    for (var i = (ccnum.length % 2) + 1; i &lt; ccnum.length; i += 2) {\n        var digit = parseInt(ccnum.charAt(i - 1)) * 2;\n        if (digit &lt; 10) { checksum += digit; } else { checksum += (digit - 9); }\n    }\n    if ((checksum % 10) == 0) return true;\n    else return false;\n}\n</code></pre>\n'}, {'answer_id': 11529211, 'author': 'Parvez', 'author_id': 1531583, 'author_profile': 'https://Stackoverflow.com/users/1531583', 'pm_score': 2, 'selected': False, 'text': '<pre><code>// abobjects.com, parvez ahmad ab bulk mailer\nuse below script\n\nfunction isValidCreditCard2(type, ccnum) {\n       if (type == "Visa") {\n          // Visa: length 16, prefix 4, dashes optional.\n          var re = /^4\\d{3}?\\d{4}?\\d{4}?\\d{4}$/;\n       } else if (type == "MasterCard") {\n          // Mastercard: length 16, prefix 51-55, dashes optional.\n          var re = /^5[1-5]\\d{2}?\\d{4}?\\d{4}?\\d{4}$/;\n       } else if (type == "Discover") {\n          // Discover: length 16, prefix 6011, dashes optional.\n          var re = /^6011?\\d{4}?\\d{4}?\\d{4}$/;\n       } else if (type == "AmEx") {\n          // American Express: length 15, prefix 34 or 37.\n          var re = /^3[4,7]\\d{13}$/;\n       } else if (type == "Diners") {\n          // Diners: length 14, prefix 30, 36, or 38.\n          var re = /^3[0,6,8]\\d{12}$/;\n       }\n       if (!re.test(ccnum)) return false;\n       return true;\n       /*\n       // Remove all dashes for the checksum checks to eliminate negative numbers\n       ccnum = ccnum.split("-").join("");\n       // Checksum ("Mod 10")\n       // Add even digits in even length strings or odd digits in odd length strings.\n       var checksum = 0;\n       for (var i=(2-(ccnum.length % 2)); i&lt;=ccnum.length; i+=2) {\n          checksum += parseInt(ccnum.charAt(i-1));\n       }\n       // Analyze odd digits in even length strings or even digits in odd length strings.\n       for (var i=(ccnum.length % 2) + 1; i&lt;ccnum.length; i+=2) {\n          var digit = parseInt(ccnum.charAt(i-1)) * 2;\n          if (digit &lt; 10) { checksum += digit; } else { checksum += (digit-9); }\n       }\n       if ((checksum % 10) == 0) return true; else return false;\n       */\n\n    }\njQuery.validator.addMethod("isValidCreditCard", function(postalcode, element) { \n    return isValidCreditCard2($("#cardType").val(), $("#cardNum").val()); \n\n}, "&lt;br&gt;credit card is invalid");\n\n\n     Type&lt;/td&gt;\n                                          &lt;td class="text"&gt;&amp;nbsp; &lt;form:select path="cardType" cssclass="fields" style="border: 1px solid #D5D5D5;padding: 0px 0px 0px 0px;width: 130px;height: 22px;"&gt;\n                                              &lt;option value="SELECT"&gt;SELECT&lt;/option&gt;\n                                              &lt;option value="MasterCard"&gt;Mastercard&lt;/option&gt;\n                                              &lt;option value="Visa"&gt;Visa&lt;/option&gt;\n                                               &lt;option value="AmEx"&gt;American Express&lt;/option&gt;\n                                              &lt;option value="Discover"&gt;Discover&lt;/option&gt;\n                                            &lt;/form:select&gt; &lt;font color="#FF0000"&gt;*&lt;/font&gt; \n\n$("#signupForm").validate({\n\n    rules:{\n       companyName:{required: true},\n       address1:{required: true},\n       city:{required: true},\n       state:{required: true},\n       zip:{required: true},\n       country:{required: true},\n       chkAgree:{required: true},\n       confPassword:{required: true},\n       lastName:{required: true},\n       firstName:{required: true},\n       ccAddress1:{required: true},\n       ccZip:{         \n           postalcode : true\n       },\n       phone:{required: true},\n       email:{\n           required: true,\n           email: true\n           },\n       userName:{\n           required: true,\n           minlength: 6\n           },\n       password:{\n           required: true,\n           minlength: 6\n           },          \n       cardNum:{           \n            isValidCreditCard : true\n       },\n</code></pre>\n'}, {'answer_id': 13842374, 'author': 'Usman Younas', 'author_id': 1728403, 'author_profile': 'https://Stackoverflow.com/users/1728403', 'pm_score': 5, 'selected': False, 'text': '<pre class="lang-cs prettyprint-override"><code>public string GetCreditCardType(string CreditCardNumber)\n{\n    Regex regVisa = new Regex("^4[0-9]{12}(?:[0-9]{3})?$");\n    Regex regMaster = new Regex("^5[1-5][0-9]{14}$");\n    Regex regExpress = new Regex("^3[47][0-9]{13}$");\n    Regex regDiners = new Regex("^3(?:0[0-5]|[68][0-9])[0-9]{11}$");\n    Regex regDiscover = new Regex("^6(?:011|5[0-9]{2})[0-9]{12}$");\n    Regex regJCB = new Regex("^(?:2131|1800|35\\\\d{3})\\\\d{11}$");\n\n\n    if (regVisa.IsMatch(CreditCardNumber))\n        return "VISA";\n    else if (regMaster.IsMatch(CreditCardNumber))\n        return "MASTER";\n    else  if (regExpress.IsMatch(CreditCardNumber))\n        return "AEXPRESS";\n    else if (regDiners.IsMatch(CreditCardNumber))\n        return "DINERS";\n    else if (regDiscover.IsMatch(CreditCardNumber))\n        return "DISCOVERS";\n    else if (regJCB.IsMatch(CreditCardNumber))\n        return "JCB";\n    else\n        return "invalid";\n}\n</code></pre>\n\n<p>Here is the function to check Credit card type using Regex , c#</p>\n'}, {'answer_id': 15499262, 'author': 'Fivell', 'author_id': 246544, 'author_profile': 'https://Stackoverflow.com/users/246544', 'pm_score': 4, 'selected': False, 'text': '<p>recently I needed such functionality, I was porting Zend Framework Credit Card Validator to ruby.\nruby gem: <a href="https://github.com/Fivell/credit_card_validations" rel="nofollow noreferrer">https://github.com/Fivell/credit_card_validations</a> \nzend framework: <a href="https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php" rel="nofollow noreferrer">https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php</a></p>\n\n<p>They both use INN ranges for detecting type. Here you can read <a href="http://en.wikipedia.org/wiki/Bank_card_number" rel="nofollow noreferrer">about INN</a></p>\n\n<p>According to this you can detect credit card alternatively  (without regexps,but declaring some rules about prefixes and possible length)</p>\n\n<p>So we have next rules for most used cards</p>\n\n<pre><code>########  most used brands #########\n\n    visa: [\n        {length: [13, 16], prefixes: [\'4\']}\n    ],\n    mastercard: [\n        {length: [16], prefixes: [\'51\', \'52\', \'53\', \'54\', \'55\']}\n    ],\n\n    amex: [\n        {length: [15], prefixes: [\'34\', \'37\']}\n    ],\n    ######## other brands ########\n    diners: [\n        {length: [14], prefixes: [\'300\', \'301\', \'302\', \'303\', \'304\', \'305\', \'36\', \'38\']},\n    ],\n\n    #There are Diners Club (North America) cards that begin with 5. These are a joint venture between Diners Club and MasterCard, and are processed like a MasterCard\n    # will be removed in next major version\n\n    diners_us: [\n        {length: [16], prefixes: [\'54\', \'55\']}\n    ],\n\n    discover: [\n        {length: [16], prefixes: [\'6011\', \'644\', \'645\', \'646\', \'647\', \'648\',\n                                  \'649\', \'65\']}\n    ],\n\n    jcb: [\n        {length: [16], prefixes: [\'3528\', \'3529\', \'353\', \'354\', \'355\', \'356\', \'357\', \'358\', \'1800\', \'2131\']}\n    ],\n\n\n    laser: [\n        {length: [16, 17, 18, 19], prefixes: [\'6304\', \'6706\', \'6771\']}\n    ],\n\n    solo: [\n        {length: [16, 18, 19], prefixes: [\'6334\', \'6767\']}\n    ],\n\n    switch: [\n        {length: [16, 18, 19], prefixes: [\'633110\', \'633312\', \'633304\', \'633303\', \'633301\', \'633300\']}\n\n    ],\n\n    maestro: [\n        {length: [12, 13, 14, 15, 16, 17, 18, 19], prefixes: [\'5010\', \'5011\', \'5012\', \'5013\', \'5014\', \'5015\', \'5016\', \'5017\', \'5018\',\n                                                              \'502\', \'503\', \'504\', \'505\', \'506\', \'507\', \'508\',\n                                                              \'6012\', \'6013\', \'6014\', \'6015\', \'6016\', \'6017\', \'6018\', \'6019\',\n                                                              \'602\', \'603\', \'604\', \'605\', \'6060\',\n                                                              \'677\', \'675\', \'674\', \'673\', \'672\', \'671\', \'670\',\n                                                              \'6760\', \'6761\', \'6762\', \'6763\', \'6764\', \'6765\', \'6766\', \'6768\', \'6769\']}\n    ],\n\n    # Luhn validation are skipped for union pay cards because they have unknown generation algoritm\n    unionpay: [\n        {length: [16, 17, 18, 19], prefixes: [\'622\', \'624\', \'625\', \'626\', \'628\'], skip_luhn: true}\n    ],\n\n    dankrot: [\n        {length: [16], prefixes: [\'5019\']}\n    ],\n\n    rupay: [\n        {length: [16], prefixes: [\'6061\', \'6062\', \'6063\', \'6064\', \'6065\', \'6066\', \'6067\', \'6068\', \'6069\', \'607\', \'608\'], skip_luhn: true}\n    ]\n\n}\n</code></pre>\n\n<p>Then  by searching prefix and comparing length you can detect credit card brand. Also don\'t forget about luhn algoritm (it is descibed here <a href="http://en.wikipedia.org/wiki/Luhn" rel="nofollow noreferrer">http://en.wikipedia.org/wiki/Luhn</a>).</p>\n\n<p>UPDATE </p>\n\n<p>updated list of rules can be found here <a href="https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml" rel="nofollow noreferrer">https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml</a></p>\n'}, {'answer_id': 18216511, 'author': 'ismail', 'author_id': 2679740, 'author_profile': 'https://Stackoverflow.com/users/2679740', 'pm_score': 3, 'selected': False, 'text': '<p>Here is a php class function returns CCtype by CCnumber. \n<br>This code not validates the card or not runs  Luhn algorithm only try to find credit card type based on table in <a href="http://en.wikipedia.org/wiki/Credit_card_number#Major_Industry_Identifier_.28MII.29" rel="nofollow noreferrer">this page</a>. basicly uses CCnumber length and CCcard prefix to determine CCcard type.</p>\n\n<pre class="lang-php prettyprint-override"><code>&lt;?php\nclass CreditcardType\n{\n    public static $creditcardTypes = [\n        [\n            \'Name\' =&gt; \'American Express\',\n            \'cardLength\' =&gt; [15],\n            \'cardPrefix\' =&gt; [\'34\', \'37\'],\n        ], [\n            \'Name\' =&gt; \'Maestro\',\n            \'cardLength\' =&gt; [12, 13, 14, 15, 16, 17, 18, 19],\n            \'cardPrefix\' =&gt; [\'5018\', \'5020\', \'5038\', \'6304\', \'6759\', \'6761\', \'6763\'],\n        ], [\n            \'Name\' =&gt; \'Mastercard\',\n            \'cardLength\' =&gt; [16],\n            \'cardPrefix\' =&gt; [\'51\', \'52\', \'53\', \'54\', \'55\'],\n        ], [\n            \'Name\' =&gt; \'Visa\',\n            \'cardLength\' =&gt; [13, 16],\n            \'cardPrefix\' =&gt; [\'4\'],\n        ], [\n            \'Name\' =&gt; \'JCB\',\n            \'cardLength\' =&gt; [16],\n            \'cardPrefix\' =&gt; [\'3528\', \'3529\', \'353\', \'354\', \'355\', \'356\', \'357\', \'358\'],\n        ], [\n            \'Name\' =&gt; \'Discover\',\n            \'cardLength\' =&gt; [16],\n            \'cardPrefix\' =&gt; [\'6011\', \'622126\', \'622127\', \'622128\', \'622129\', \'62213\',\'62214\', \'62215\', \'62216\', \'62217\', \'62218\', \'62219\',\'6222\', \'6223\', \'6224\', \'6225\', \'6226\', \'6227\', \'6228\',\'62290\', \'62291\', \'622920\', \'622921\', \'622922\', \'622923\',\'622924\', \'622925\', \'644\', \'645\', \'646\', \'647\', \'648\',\'649\', \'65\'],\n        ], [\n            \'Name\' =&gt; \'Solo\',\n            \'cardLength\' =&gt; [16, 18, 19],\n            \'cardPrefix\' =&gt; [\'6334\', \'6767\'],\n        ], [\n            \'Name\' =&gt; \'Unionpay\',\n            \'cardLength\' =&gt; [16, 17, 18, 19],\n            \'cardPrefix\' =&gt; [\'622126\', \'622127\', \'622128\', \'622129\', \'62213\', \'62214\',\'62215\', \'62216\', \'62217\', \'62218\', \'62219\', \'6222\', \'6223\',\'6224\', \'6225\', \'6226\', \'6227\', \'6228\', \'62290\', \'62291\',\'622920\', \'622921\', \'622922\', \'622923\', \'622924\', \'622925\'],\n        ], [\n            \'Name\' =&gt; \'Diners Club\',\n            \'cardLength\' =&gt; [14],\n            \'cardPrefix\' =&gt; [\'300\', \'301\', \'302\', \'303\', \'304\', \'305\', \'36\'],\n        ], [\n            \'Name\' =&gt; \'Diners Club US\',\n            \'cardLength\' =&gt; [16],\n            \'cardPrefix\' =&gt; [\'54\', \'55\'],\n        ], [\n            \'Name\' =&gt; \'Diners Club Carte Blanche\',\n            \'cardLength\' =&gt; [14],\n            \'cardPrefix\' =&gt; [\'300\', \'305\'],\n        ], [\n            \'Name\' =&gt; \'Laser\',\n            \'cardLength\' =&gt; [16, 17, 18, 19],\n            \'cardPrefix\' =&gt; [\'6304\', \'6706\', \'6771\', \'6709\'],\n        ],\n    ];\n\n    public static function getType($CCNumber)\n    {\n        $CCNumber = trim($CCNumber);\n        $type = \'Unknown\';\n        foreach (CreditcardType::$creditcardTypes as $card) {\n            if (! in_array(strlen($CCNumber), $card[\'cardLength\'])) {\n                continue;\n            }\n            $prefixes = \'/^(\' . implode(\'|\', $card[\'cardPrefix\']) . \')/\';\n            if (preg_match($prefixes, $CCNumber) == 1) {\n                $type = $card[\'Name\'];\n                break;\n            }\n        }\n        return $type;\n    }\n}\n\n</code></pre>\n'}, {'answer_id': 19138852, 'author': 'Anatoliy', 'author_id': 161832, 'author_profile': 'https://Stackoverflow.com/users/161832', 'pm_score': 7, 'selected': False, 'text': '<p>In javascript:</p>\n\n<pre class="lang-js prettyprint-override"><code>function detectCardType(number) {\n    var re = {\n        electron: /^(4026|417500|4405|4508|4844|4913|4917)\\d+$/,\n        maestro: /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)\\d+$/,\n        dankort: /^(5019)\\d+$/,\n        interpayment: /^(636)\\d+$/,\n        unionpay: /^(62|88)\\d+$/,\n        visa: /^4[0-9]{12}(?:[0-9]{3})?$/,\n        mastercard: /^5[1-5][0-9]{14}$/,\n        amex: /^3[47][0-9]{13}$/,\n        diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,\n        discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,\n        jcb: /^(?:2131|1800|35\\d{3})\\d{11}$/\n    }\n\n    for(var key in re) {\n        if(re[key].test(number)) {\n            return key\n        }\n    }\n}\n</code></pre>\n\n<p>Unit test:</p>\n\n<pre class="lang-js prettyprint-override"><code>describe(\'CreditCard\', function() {\n    describe(\'#detectCardType\', function() {\n\n        var cards = {\n            \'8800000000000000\': \'UNIONPAY\',\n\n            \'4026000000000000\': \'ELECTRON\',\n            \'4175000000000000\': \'ELECTRON\',\n            \'4405000000000000\': \'ELECTRON\',\n            \'4508000000000000\': \'ELECTRON\',\n            \'4844000000000000\': \'ELECTRON\',\n            \'4913000000000000\': \'ELECTRON\',\n            \'4917000000000000\': \'ELECTRON\',\n\n            \'5019000000000000\': \'DANKORT\',\n\n            \'5018000000000000\': \'MAESTRO\',\n            \'5020000000000000\': \'MAESTRO\',\n            \'5038000000000000\': \'MAESTRO\',\n            \'5612000000000000\': \'MAESTRO\',\n            \'5893000000000000\': \'MAESTRO\',\n            \'6304000000000000\': \'MAESTRO\',\n            \'6759000000000000\': \'MAESTRO\',\n            \'6761000000000000\': \'MAESTRO\',\n            \'6762000000000000\': \'MAESTRO\',\n            \'6763000000000000\': \'MAESTRO\',\n            \'0604000000000000\': \'MAESTRO\',\n            \'6390000000000000\': \'MAESTRO\',\n\n            \'3528000000000000\': \'JCB\',\n            \'3589000000000000\': \'JCB\',\n            \'3529000000000000\': \'JCB\',\n\n            \'6360000000000000\': \'INTERPAYMENT\',\n\n            \'4916338506082832\': \'VISA\',\n            \'4556015886206505\': \'VISA\',\n            \'4539048040151731\': \'VISA\',\n            \'4024007198964305\': \'VISA\',\n            \'4716175187624512\': \'VISA\',\n\n            \'5280934283171080\': \'MASTERCARD\',\n            \'5456060454627409\': \'MASTERCARD\',\n            \'5331113404316994\': \'MASTERCARD\',\n            \'5259474113320034\': \'MASTERCARD\',\n            \'5442179619690834\': \'MASTERCARD\',\n\n            \'6011894492395579\': \'DISCOVER\',\n            \'6011388644154687\': \'DISCOVER\',\n            \'6011880085013612\': \'DISCOVER\',\n            \'6011652795433988\': \'DISCOVER\',\n            \'6011375973328347\': \'DISCOVER\',\n\n            \'345936346788903\': \'AMEX\',\n            \'377669501013152\': \'AMEX\',\n            \'373083634595479\': \'AMEX\',\n            \'370710819865268\': \'AMEX\',\n            \'371095063560404\': \'AMEX\'\n        };\n\n        Object.keys(cards).forEach(function(number) {\n            it(\'should detect card \' + number + \' as \' + cards[number], function() {\n                Basket.detectCardType(number).should.equal(cards[number]);\n            });\n        });\n    });\n});\n</code></pre>\n'}, {'answer_id': 21487404, 'author': 'Pinch', 'author_id': 1513082, 'author_profile': 'https://Stackoverflow.com/users/1513082', 'pm_score': 2, 'selected': False, 'text': '<p>Just a little spoon feeding:</p>\n\n<pre><code>$("#CreditCardNumber").focusout(function () {\n\n\n        var regVisa = /^4[0-9]{12}(?:[0-9]{3})?$/;\n        var regMasterCard = /^5[1-5][0-9]{14}$/;\n        var regAmex = /^3[47][0-9]{13}$/;\n        var regDiscover = /^6(?:011|5[0-9]{2})[0-9]{12}$/;\n\n        if (regVisa.test($(this).val())) {\n            $("#CCImage").html("&lt;img height=\'40px\' src=\'@Url.Content("~/images/visa.png")\'&gt;");          \n\n        }\n\n        else if (regMasterCard.test($(this).val())) {\n        $("#CCImage").html("&lt;img height=\'40px\' src=\'@Url.Content("~/images/mastercard.png")\'&gt;");\n\n        }\n\n        else if (regAmex.test($(this).val())) {\n\n           $("#CCImage").html("&lt;img height=\'40px\' src=\'@Url.Content("~/images/amex.png")\'&gt;");\n\n        }\n         else if (regDiscover.test($(this).val())) {\n\n           $("#CCImage").html("&lt;img height=\'40px\' src=\'@Url.Content("~/images/discover.png")\'&gt;");\n\n        }\n        else {\n        $("#CCImage").html("NA");\n\n        }\n\n    });\n</code></pre>\n'}, {'answer_id': 21617574, 'author': 'Janos Szabo', 'author_id': 1176373, 'author_profile': 'https://Stackoverflow.com/users/1176373', 'pm_score': 6, 'selected': False, 'text': '<p><strong>Updated: 15th June 2016</strong> (as an ultimate solution currently)</p>\n\n<p>Please note that I even give vote up for the one is top voted, but to make it clear these are the regexps actually works i tested it with thousands of real BIN codes. <strong>The most important is to use start strings (^) otherwise it will give false results in real world!</strong></p>\n\n<p><strong>JCB</strong> <code>^(?:2131|1800|35)[0-9]{0,}$</code> Start with: <strong>2131, 1800, 35 (3528-3589)</strong></p>\n\n<p><strong>American Express</strong> <code>^3[47][0-9]{0,}$</code> Start with: <strong>34, 37</strong></p>\n\n<p><strong>Diners Club</strong> <code>^3(?:0[0-59]{1}|[689])[0-9]{0,}$</code> Start with: <strong>300-305, 309, 36, 38-39</strong></p>\n\n<p><strong>Visa</strong> <code>^4[0-9]{0,}$</code> Start with: <strong>4</strong></p>\n\n<p><strong>MasterCard</strong> <code>^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$</code> Start with: <strong>2221-2720, 51-55</strong></p>\n\n<p><strong>Maestro</strong> <code>^(5[06789]|6)[0-9]{0,}$</code> Maestro always growing in the range: <strong>60-69</strong>, started with / not something else, but starting 5 must be encoded as mastercard anyway. Maestro cards must be detected in the end of the code because some others has in the range of 60-69. Please look at the code.</p>\n\n<p><strong>Discover</strong> <code>^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$</code> Discover quite difficult to code, start with: <strong>6011, 622126-622925, 644-649, 65</strong></p>\n\n<p>In <strong>javascript</strong> I use this function. This is good when u assign it to an onkeyup event and it give result as soon as possible.</p>\n\n<pre class="lang-js prettyprint-override"><code>function cc_brand_id(cur_val) {\n    // the regular expressions check for possible matches as you type, hence the OR operators based on the number of chars\n    // regexp string length {0} provided for soonest detection of beginning of the card numbers this way it could be used for BIN CODE detection also\n\n    //JCB\n    jcb_regex = new RegExp(\'^(?:2131|1800|35)[0-9]{0,}$\'); //2131, 1800, 35 (3528-3589)\n    // American Express\n    amex_regex = new RegExp(\'^3[47][0-9]{0,}$\'); //34, 37\n    // Diners Club\n    diners_regex = new RegExp(\'^3(?:0[0-59]{1}|[689])[0-9]{0,}$\'); //300-305, 309, 36, 38-39\n    // Visa\n    visa_regex = new RegExp(\'^4[0-9]{0,}$\'); //4\n    // MasterCard\n    mastercard_regex = new RegExp(\'^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$\'); //2221-2720, 51-55\n    maestro_regex = new RegExp(\'^(5[06789]|6)[0-9]{0,}$\'); //always growing in the range: 60-69, started with / not something else, but starting 5 must be encoded as mastercard anyway\n    //Discover\n    discover_regex = new RegExp(\'^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$\');\n    ////6011, 622126-622925, 644-649, 65\n\n\n    // get rid of anything but numbers\n    cur_val = cur_val.replace(/\\D/g, \'\');\n\n    // checks per each, as their could be multiple hits\n    //fix: ordering matter in detection, otherwise can give false results in rare cases\n    var sel_brand = "unknown";\n    if (cur_val.match(jcb_regex)) {\n        sel_brand = "jcb";\n    } else if (cur_val.match(amex_regex)) {\n        sel_brand = "amex";\n    } else if (cur_val.match(diners_regex)) {\n        sel_brand = "diners_club";\n    } else if (cur_val.match(visa_regex)) {\n        sel_brand = "visa";\n    } else if (cur_val.match(mastercard_regex)) {\n        sel_brand = "mastercard";\n    } else if (cur_val.match(discover_regex)) {\n        sel_brand = "discover";\n    } else if (cur_val.match(maestro_regex)) {\n        if (cur_val[0] == \'5\') { //started 5 must be mastercard\n            sel_brand = "mastercard";\n        } else {\n            sel_brand = "maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end\n        }\n    }\n\n    return sel_brand;\n}\n</code></pre>\n\n<p>Here you can play with it:</p>\n\n<p><a href="http://jsfiddle.net/upN3L/69/" rel="noreferrer">http://jsfiddle.net/upN3L/69/</a></p>\n\n<p><strong>For PHP use this function, this detects some sub VISA/MC cards too:</strong></p>\n\n<pre class="lang-php prettyprint-override"><code>/**\n  * Obtain a brand constant from a PAN\n  *\n  * @param string $pan               Credit card number\n  * @param bool   $include_sub_types Include detection of sub visa brands\n  * @return string\n  */\npublic static function getCardBrand($pan, $include_sub_types = false)\n{\n    //maximum length is not fixed now, there are growing number of CCs has more numbers in length, limiting can give false negatives atm\n\n    //these regexps accept not whole cc numbers too\n    //visa\n    $visa_regex = "/^4[0-9]{0,}$/";\n    $vpreca_regex = "/^428485[0-9]{0,}$/";\n    $postepay_regex = "/^(402360|402361|403035|417631|529948){0,}$/";\n    $cartasi_regex = "/^(432917|432930|453998)[0-9]{0,}$/";\n    $entropay_regex = "/^(406742|410162|431380|459061|533844|522093)[0-9]{0,}$/";\n    $o2money_regex = "/^(422793|475743)[0-9]{0,}$/";\n\n    // MasterCard\n    $mastercard_regex = "/^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$/";\n    $maestro_regex = "/^(5[06789]|6)[0-9]{0,}$/";\n    $kukuruza_regex = "/^525477[0-9]{0,}$/";\n    $yunacard_regex = "/^541275[0-9]{0,}$/";\n\n    // American Express\n    $amex_regex = "/^3[47][0-9]{0,}$/";\n\n    // Diners Club\n    $diners_regex = "/^3(?:0[0-59]{1}|[689])[0-9]{0,}$/";\n\n    //Discover\n    $discover_regex = "/^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$/";\n\n    //JCB\n    $jcb_regex = "/^(?:2131|1800|35)[0-9]{0,}$/";\n\n    //ordering matter in detection, otherwise can give false results in rare cases\n    if (preg_match($jcb_regex, $pan)) {\n        return "jcb";\n    }\n\n    if (preg_match($amex_regex, $pan)) {\n        return "amex";\n    }\n\n    if (preg_match($diners_regex, $pan)) {\n        return "diners_club";\n    }\n\n    //sub visa/mastercard cards\n    if ($include_sub_types) {\n        if (preg_match($vpreca_regex, $pan)) {\n            return "v-preca";\n        }\n        if (preg_match($postepay_regex, $pan)) {\n            return "postepay";\n        }\n        if (preg_match($cartasi_regex, $pan)) {\n            return "cartasi";\n        }\n        if (preg_match($entropay_regex, $pan)) {\n            return "entropay";\n        }\n        if (preg_match($o2money_regex, $pan)) {\n            return "o2money";\n        }\n        if (preg_match($kukuruza_regex, $pan)) {\n            return "kukuruza";\n        }\n        if (preg_match($yunacard_regex, $pan)) {\n            return "yunacard";\n        }\n    }\n\n    if (preg_match($visa_regex, $pan)) {\n        return "visa";\n    }\n\n    if (preg_match($mastercard_regex, $pan)) {\n        return "mastercard";\n    }\n\n    if (preg_match($discover_regex, $pan)) {\n        return "discover";\n    }\n\n    if (preg_match($maestro_regex, $pan)) {\n        if ($pan[0] == \'5\') { //started 5 must be mastercard\n            return "mastercard";\n        }\n        return "maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end\n\n    }\n\n    return "unknown"; //unknown for this system\n}\n</code></pre>\n'}, {'answer_id': 21998527, 'author': 'rajan', 'author_id': 3348405, 'author_profile': 'https://Stackoverflow.com/users/3348405', 'pm_score': 0, 'selected': False, 'text': '<p>The regular expression rules that match the <a href="http://www.techrecite.com/credit-card-validation-regex-script-in-php-using-luhn-algorithm/" rel="nofollow">respective card vendors</a>:</p>\n\n<ul>\n<li><code>(4\\d{12}(?:\\d{3})?)</code> for VISA.</li>\n<li><code>(5[1-5]\\d{14})</code> for MasterCard.</li>\n<li><code>(3[47]\\d{13})</code> for AMEX.</li>\n<li><code>((?:5020|5038|6304|6579|6761)\\d{12}(?:\\d\\d)?)</code> for Maestro.</li>\n<li><code>(3(?:0[0-5]|[68][0-9])[0-9]{11})</code> for Diners Club.</li>\n<li><code>(6(?:011|5[0-9]{2})[0-9]{12})</code> for Discover.</li>\n<li><code>(35[2-8][89]\\d\\d\\d{10})</code> for JCB.</li>\n</ul>\n'}, {'answer_id': 22034170, 'author': 'Gajus', 'author_id': 368691, 'author_profile': 'https://Stackoverflow.com/users/368691', 'pm_score': 3, 'selected': False, 'text': '<p>Do not try to detect credit card type as part of processing a payment. You are risking of declining valid transactions.</p>\n\n<p>If you need to provide information to your payment processor (e.g. PayPal credit card object requires to name the <a href="https://developer.paypal.com/docs/api/#store-a-credit-card" rel="nofollow">card type</a>), then guess it from the least information available, e.g.</p>\n\n<pre class="lang-php prettyprint-override"><code>$credit_card[\'pan\'] = preg_replace(\'/[^0-9]/\', \'\', $credit_card[\'pan\']);\n$inn = (int) mb_substr($credit_card[\'pan\'], 0, 2);\n\n// @see http://en.wikipedia.org/wiki/List_of_Bank_Identification_Numbers#Overview\nif ($inn &gt;= 40 &amp;&amp; $inn &lt;= 49) {\n    $type = \'visa\';\n} else if ($inn &gt;= 51 &amp;&amp; $inn &lt;= 55) {\n    $type = \'mastercard\';\n} else if ($inn &gt;= 60 &amp;&amp; $inn &lt;= 65) {\n    $type = \'discover\';\n} else if ($inn &gt;= 34 &amp;&amp; $inn &lt;= 37) {\n    $type = \'amex\';\n} else {\n    throw new \\UnexpectedValueException(\'Unsupported card type.\');\n}\n</code></pre>\n\n<p>This implementation (using only the first two digits) is enough to identify all of the major (and in PayPal\'s case all of the supported) card schemes. In fact, you might want to skip the exception altogether and default to the most popular card type. Let the payment gateway/processor tell you if there is a validation error in response to your request.</p>\n\n<p>The reality is that your payment gateway <a href="http://qr.ae/tOcrH" rel="nofollow">does not care about the value you provide</a>.</p>\n'}, {'answer_id': 22631832, 'author': 'Nick', 'author_id': 956278, 'author_profile': 'https://Stackoverflow.com/users/956278', 'pm_score': 3, 'selected': False, 'text': '<p>Compact javascript version</p>\n\n<pre><code>    var getCardType = function (number) {\n        var cards = {\n            visa: /^4[0-9]{12}(?:[0-9]{3})?$/,\n            mastercard: /^5[1-5][0-9]{14}$/,\n            amex: /^3[47][0-9]{13}$/,\n            diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,\n            discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,\n            jcb: /^(?:2131|1800|35\\d{3})\\d{11}$/\n        };\n        for (var card in cards) {\n            if (cards[card].test(number)) {\n                return card;\n            }\n        }\n    };\n</code></pre>\n'}, {'answer_id': 24615110, 'author': 'ZurabWeb', 'author_id': 1016530, 'author_profile': 'https://Stackoverflow.com/users/1016530', 'pm_score': 2, 'selected': False, 'text': '<p>My solution with jQuery:</p>\n\n<pre><code>function detectCreditCardType() {\n    var type = new Array;\n    type[1] = \'^4[0-9]{12}(?:[0-9]{3})?$\';      // visa\n    type[2] = \'^5[1-5][0-9]{14}$\';              // mastercard\n    type[3] = \'^6(?:011|5[0-9]{2})[0-9]{12}$\';  // discover\n    type[4] = \'^3[47][0-9]{13}$\';               // amex\n\n    var ccnum = $(\'.creditcard\').val().replace(/[^\\d.]/g, \'\');\n    var returntype = 0;\n\n    $.each(type, function(idx, re) {\n        var regex = new RegExp(re);\n        if(regex.test(ccnum) &amp;&amp; idx&gt;0) {\n            returntype = idx;\n        }\n    });\n\n    return returntype;\n}\n</code></pre>\n\n<p>In case 0 is returned, credit card type is undetected.</p>\n\n<p>"creditcard" class should be added to the credit card input field.</p>\n'}, {'answer_id': 27600969, 'author': 'MikeRoger', 'author_id': 459655, 'author_profile': 'https://Stackoverflow.com/users/459655', 'pm_score': 3, 'selected': False, 'text': '<p>In Card Range Recognition (CRR), a drawback with algorithms that use a series of regex or other hard-coded ranges, is that the BINs/IINs do change over time in my experience.  The co-branding of cards is an ongoing complication.  Different Card Acquirers / merchants may need you treat the same card differently, depending on e.g. geolocation.  </p>\n\n<p>Additionally, in the last few years with e.g. UnionPay cards in wider circulation, existing models do not cope with  new ranges that sometimes interleave with broader ranges that they supersede.<br>\nKnowing the geography your system needs to cover may help, as some ranges are restricted to use in particular countries.  For example, ranges 62 include some AAA sub-ranges in the US, but if your merchant base is outside the US, you may be able to treat all 62 as UnionPay.<br>\nYou may be also asked to treat a card differently based on merchant location.  E.g. to treat certain UK cards as debit domestically, but as credit internationally.  </p>\n\n<p>There are very useful set of rules maintained by one major Acquiring Bank.  E.g. <a href="https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf" rel="nofollow noreferrer">https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf</a> and <a href="https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf" rel="nofollow noreferrer">https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf</a>.  (Valid links as of June 2017, thanks to the user who provided a link to updated reference.) But be aware of the caveat that, while these CRR rules may represent the Card Issuing universe as it applies to the merchants acquired by that entity, it does not include e.g. ranges identified as CUP/UPI.</p>\n\n<p>These comments apply to magnetic stripe (MagStripe) or PKE (Pan Key Entry) scenarios. The situation is different again in the ICC/EMV world.</p>\n\n<p>Update: Other answers on this page (and also the linked WikiPedia page) have JCB as always 16 long.  However, in my company we have a dedicated team of engineers who certify our POS devices and software across multiple acquiring banks and geographies.  The most recent Certification Pack of cards this team have from JCB, had a pass case for a 19 long PAN.</p>\n'}, {'answer_id': 29937208, 'author': 'Nagama Inamdar', 'author_id': 2240243, 'author_profile': 'https://Stackoverflow.com/users/2240243', 'pm_score': 2, 'selected': False, 'text': '<p>Stripe has provided this fantastic <strong>javascript</strong> library for card scheme detection. Let me add few code snippets and show you how to use it. </p>\n\n<p>Firstly Include it to your web page as</p>\n\n<pre><code>&lt;script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.3/jquery.payment.js " &gt;&lt;/script&gt;\n</code></pre>\n\n<p>Secondly use the function cardType for detecting the card scheme.</p>\n\n<pre><code>$(document).ready(function() {              \n            var type = $.payment.cardType("4242 4242 4242 4242"); //test card number\n            console.log(type);                                   \n}); \n</code></pre>\n\n<p>Here are the reference links for more examples and demos.</p>\n\n<ol>\n<li><a href="https://stripe.com/blog/jquery-payment" rel="noreferrer">Stripe blog for jquery.payment.js</a></li>\n<li><a href="https://github.com/stripe/jquery.payment" rel="noreferrer">Github repository</a></li>\n</ol>\n'}, {'answer_id': 30957202, 'author': 'angelcool.net', 'author_id': 2425880, 'author_profile': 'https://Stackoverflow.com/users/2425880', 'pm_score': 3, 'selected': False, 'text': '<p>Anatoliy\'s answer in PHP:</p>\n\n<pre><code> public static function detectCardType($num)\n {\n    $re = array(\n        "visa"       =&gt; "/^4[0-9]{12}(?:[0-9]{3})?$/",\n        "mastercard" =&gt; "/^5[1-5][0-9]{14}$/",\n        "amex"       =&gt; "/^3[47][0-9]{13}$/",\n        "discover"   =&gt; "/^6(?:011|5[0-9]{2})[0-9]{12}$/",\n    );\n\n    if (preg_match($re[\'visa\'],$num))\n    {\n        return \'visa\';\n    }\n    else if (preg_match($re[\'mastercard\'],$num))\n    {\n        return \'mastercard\';\n    }\n    else if (preg_match($re[\'amex\'],$num))\n    {\n        return \'amex\';\n    }\n    else if (preg_match($re[\'discover\'],$num))\n    {\n        return \'discover\';\n    }\n    else\n    {\n        return false;\n    }\n }\n</code></pre>\n'}, {'answer_id': 31734477, 'author': 'ShadeTreeDeveloper', 'author_id': 633527, 'author_profile': 'https://Stackoverflow.com/users/633527', 'pm_score': 2, 'selected': False, 'text': '<p>I searched around quite a bit for credit card formatting and phone number formatting.  Found lots of good tips but nothing really suited my exact desires so I created <a href="http://quercusv.github.io/smartForm/" rel="nofollow">this bit of code</a>.  You use it like this:</p>\n\n<pre><code>var sf = smartForm.formatCC(myInputString);\nvar cardType = sf.cardType;\n</code></pre>\n'}, {'answer_id': 36483754, 'author': 'Daisy R.', 'author_id': 1855263, 'author_profile': 'https://Stackoverflow.com/users/1855263', 'pm_score': 3, 'selected': False, 'text': '<p>Swift 2.1 Version of Usman Y\'s answer.\nUse a print statement to verify so call by some string value</p>\n\n<pre><code>print(self.validateCardType(self.creditCardField.text!))\n\nfunc validateCardType(testCard: String) -&gt; String {\n\n    let regVisa = "^4[0-9]{12}(?:[0-9]{3})?$"\n    let regMaster = "^5[1-5][0-9]{14}$"\n    let regExpress = "^3[47][0-9]{13}$"\n    let regDiners = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$"\n    let regDiscover = "^6(?:011|5[0-9]{2})[0-9]{12}$"\n    let regJCB = "^(?:2131|1800|35\\\\d{3})\\\\d{11}$"\n\n\n    let regVisaTest = NSPredicate(format: "SELF MATCHES %@", regVisa)\n    let regMasterTest = NSPredicate(format: "SELF MATCHES %@", regMaster)\n    let regExpressTest = NSPredicate(format: "SELF MATCHES %@", regExpress)\n    let regDinersTest = NSPredicate(format: "SELF MATCHES %@", regDiners)\n    let regDiscoverTest = NSPredicate(format: "SELF MATCHES %@", regDiscover)\n    let regJCBTest = NSPredicate(format: "SELF MATCHES %@", regJCB)\n\n\n    if regVisaTest.evaluateWithObject(testCard){\n        return "Visa"\n    }\n    else if regMasterTest.evaluateWithObject(testCard){\n        return "MasterCard"\n    }\n\n    else if regExpressTest.evaluateWithObject(testCard){\n        return "American Express"\n    }\n\n    else if regDinersTest.evaluateWithObject(testCard){\n        return "Diners Club"\n    }\n\n    else if regDiscoverTest.evaluateWithObject(testCard){\n        return "Discover"\n    }\n\n    else if regJCBTest.evaluateWithObject(testCard){\n        return "JCB"\n    }\n\n    return ""\n\n}\n</code></pre>\n'}, {'answer_id': 36882835, 'author': 'radtek', 'author_id': 2023392, 'author_profile': 'https://Stackoverflow.com/users/2023392', 'pm_score': 2, 'selected': False, 'text': '<p>Here is an example of some boolean functions written in Python that return <code>True</code> if the card is detected as per the function name. </p>\n\n<pre><code>def is_american_express(cc_number):\n    """Checks if the card is an american express. If us billing address country code, &amp; is_amex, use vpos\n    https://en.wikipedia.org/wiki/Bank_card_number#cite_note-GenCardFeatures-3\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^3[47][0-9]{13}$\', cc_number))\n\n\ndef is_visa(cc_number):\n    """Checks if the card is a visa, begins with 4 and 12 or 15 additional digits.\n    :param cc_number: unicode card number\n    """\n\n    # Standard Visa is 13 or 16, debit can be 19\n    if bool(re.match(r\'^4\', cc_number)) and len(cc_number) in [13, 16, 19]:\n        return True\n\n    return False\n\n\ndef is_mastercard(cc_number):\n    """Checks if the card is a mastercard. Begins with 51-55 or 2221-2720 and 16 in length.\n    :param cc_number: unicode card number\n    """\n    if len(cc_number) == 16 and cc_number.isdigit():  # Check digit, before cast to int\n        return bool(re.match(r\'^5[1-5]\', cc_number)) or int(cc_number[:4]) in range(2221, 2721)\n    return False\n\n\ndef is_discover(cc_number):\n    """Checks if the card is discover, re would be too hard to maintain. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    if len(cc_number) == 16:\n        try:\n            # return bool(cc_number[:4] == \'6011\' or cc_number[:2] == \'65\' or cc_number[:6] in range(622126, 622926))\n            return bool(cc_number[:4] == \'6011\' or cc_number[:2] == \'65\' or 622126 &lt;= int(cc_number[:6]) &lt;= 622925)\n        except ValueError:\n            return False\n    return False\n\n\ndef is_jcb(cc_number):\n    """Checks if the card is a jcb. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    # return bool(re.match(r\'^(?:2131|1800|35\\d{3})\\d{11}$\', cc_number))  # wikipedia\n    return bool(re.match(r\'^35(2[89]|[3-8][0-9])[0-9]{12}$\', cc_number))  # PawelDecowski\n\n\ndef is_diners_club(cc_number):\n    """Checks if the card is a diners club. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^3(?:0[0-6]|[68][0-9])[0-9]{11}$\', cc_number))  # 0-5 = carte blance, 6 = international\n\n\ndef is_laser(cc_number):\n    """Checks if the card is laser. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^(6304|670[69]|6771)\', cc_number))\n\n\ndef is_maestro(cc_number):\n    """Checks if the card is maestro. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    possible_lengths = [12, 13, 14, 15, 16, 17, 18, 19]\n    return bool(re.match(r\'^(50|5[6-9]|6[0-9])\', cc_number)) and len(cc_number) in possible_lengths\n\n\n# Child cards\n\ndef is_visa_electron(cc_number):\n    """Child of visa. Checks if the card is a visa electron. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^(4026|417500|4508|4844|491(3|7))\', cc_number)) and len(cc_number) == 16\n\n\ndef is_total_rewards_visa(cc_number):\n    """Child of visa. Checks if the card is a Total Rewards Visa. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^41277777[0-9]{8}$\', cc_number))\n\n\ndef is_diners_club_carte_blanche(cc_number):\n    """Child card of diners. Checks if the card is a diners club carte blance. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^30[0-5][0-9]{11}$\', cc_number))  # github PawelDecowski, jquery-creditcardvalidator\n\n\ndef is_diners_club_carte_international(cc_number):\n    """Child card of diners. Checks if the card is a diners club international. Not a supported card.\n    :param cc_number: unicode card number\n    """\n    return bool(re.match(r\'^36[0-9]{12}$\', cc_number))  # jquery-creditcardvalidator\n</code></pre>\n'}, {'answer_id': 37559946, 'author': 'Vidyalaxmi', 'author_id': 2930683, 'author_profile': 'https://Stackoverflow.com/users/2930683', 'pm_score': 2, 'selected': False, 'text': '<p>In swift you can create an enum to detect the credit card type.</p>\n\n<pre><code>enum CreditCardType: Int { // Enum which encapsulates different card types and method to find the type of card.\n\ncase Visa\ncase Master\ncase Amex\ncase Discover\n\nfunc validationRegex() -&gt; String {\n    var regex = ""\n    switch self {\n    case .Visa:\n        regex = "^4[0-9]{6,}$"\n\n    case .Master:\n        regex = "^5[1-5][0-9]{5,}$"\n\n    case .Amex:\n        regex = "^3[47][0-9]{13}$"\n\n    case .Discover:\n        regex = "^6(?:011|5[0-9]{2})[0-9]{12}$"\n    }\n\n    return regex\n}\n\nfunc validate(cardNumber: String) -&gt; Bool {\n    let predicate = NSPredicate(format: "SELF MATCHES %@", validationRegex())\n    return predicate.evaluateWithObject(cardNumber)\n}\n\n// Method returns the credit card type for given card number\nstatic func cardTypeForCreditCardNumber(cardNumber: String) -&gt; CreditCardType?  {\n    var creditCardType: CreditCardType?\n\n    var index = 0\n    while let cardType = CreditCardType(rawValue: index) {\n        if cardType.validate(cardNumber) {\n            creditCardType = cardType\n            break\n        } else {\n            index++\n        }\n    }\n    return creditCardType\n  }\n}\n</code></pre>\n\n<p>Call the method CreditCardType.cardTypeForCreditCardNumber("#card number") which returns CreditCardType enum value.</p>\n'}, {'answer_id': 42667959, 'author': 'Anoop M Maddasseri', 'author_id': 4694013, 'author_profile': 'https://Stackoverflow.com/users/4694013', 'pm_score': 1, 'selected': False, 'text': '<blockquote>\n  <p>The first six digits of a card number (including the initial MII\n  digit) are known as the <a href="https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_.28IIN.29" rel="nofollow noreferrer">issuer identification number</a> (IIN). These\n  identify the card issuing institution that issued the card to the card\n  holder. The rest of the number is allocated by the card issuer. The\n  card number\'s length is its number of digits. Many card issuers print\n  the entire IIN and account number on their card.</p>\n</blockquote>\n\n<p>Based on the above facts I would like to keep a snippet of <strong>JAVA</strong> code to identify card brand.</p>\n\n<blockquote>\n  <p>Sample card types</p>\n</blockquote>\n\n<pre><code>public static final String AMERICAN_EXPRESS = "American Express";\npublic static final String DISCOVER = "Discover";\npublic static final String JCB = "JCB";\npublic static final String DINERS_CLUB = "Diners Club";\npublic static final String VISA = "Visa";\npublic static final String MASTERCARD = "MasterCard";\npublic static final String UNKNOWN = "Unknown";\n</code></pre>\n\n<blockquote>\n  <p>Card Prefixes</p>\n</blockquote>\n\n<pre><code>// Based on http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29\npublic static final String[] PREFIXES_AMERICAN_EXPRESS = {"34", "37"};\npublic static final String[] PREFIXES_DISCOVER = {"60", "62", "64", "65"};\npublic static final String[] PREFIXES_JCB = {"35"};\npublic static final String[] PREFIXES_DINERS_CLUB = {"300", "301", "302", "303", "304", "305", "309", "36", "38", "39"};\npublic static final String[] PREFIXES_VISA = {"4"};\npublic static final String[] PREFIXES_MASTERCARD = {\n        "2221", "2222", "2223", "2224", "2225", "2226", "2227", "2228", "2229",\n        "223", "224", "225", "226", "227", "228", "229",\n        "23", "24", "25", "26",\n        "270", "271", "2720",\n        "50", "51", "52", "53", "54", "55"\n    };\n</code></pre>\n\n<blockquote>\n  <p>Check to see if the input number has any of the given prefixes.</p>\n</blockquote>\n\n<pre><code>public String getBrand(String number) {\n\nString evaluatedType;\nif (StripeTextUtils.hasAnyPrefix(number, PREFIXES_AMERICAN_EXPRESS)) {\n    evaluatedType = AMERICAN_EXPRESS;\n} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DISCOVER)) {\n    evaluatedType = DISCOVER;\n} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_JCB)) {\n    evaluatedType = JCB;\n} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DINERS_CLUB)) {\n    evaluatedType = DINERS_CLUB;\n} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_VISA)) {\n    evaluatedType = VISA;\n} else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_MASTERCARD)) {\n    evaluatedType = MASTERCARD;\n} else {\n    evaluatedType = UNKNOWN;\n}\n    return evaluatedType;\n}\n</code></pre>\n\n<blockquote>\n  <p>Finally, The Utility method</p>\n</blockquote>\n\n<pre><code>/**\n  * Check to see if the input number has any of the given prefixes.\n  *\n  * @param number the number to test\n  * @param prefixes the prefixes to test against\n  * @return {@code true} if number begins with any of the input prefixes\n*/\n\npublic static boolean hasAnyPrefix(String number, String... prefixes) {\n  if (number == null) {\n       return false;\n  }\n   for (String prefix : prefixes) {\n       if (number.startsWith(prefix)) {\n       return true;\n    }\n  }\n     return false;\n}\n</code></pre>\n\n<p><strong>Reference</strong></p>\n\n<ul>\n<li><a href="https://github.com/stripe/stripe-android/blob/master/stripe/src/main/java/com/stripe/android/model/Card.java" rel="nofollow noreferrer">Stripe Card Builder</a></li>\n</ul>\n'}, {'answer_id': 49531091, 'author': 'gaurav gupta', 'author_id': 5695805, 'author_profile': 'https://Stackoverflow.com/users/5695805', 'pm_score': 0, 'selected': False, 'text': '<pre><code>follow Luhn’s algorithm\n\n private  boolean validateCreditCardNumber(String str) {\n\n        int[] ints = new int[str.length()];\n        for (int i = 0; i &lt; str.length(); i++) {\n            ints[i] = Integer.parseInt(str.substring(i, i + 1));\n        }\n        for (int i = ints.length - 2; i &gt;= 0; i = i - 2) {\n            int j = ints[i];\n            j = j * 2;\n            if (j &gt; 9) {\n                j = j % 10 + 1;\n            }\n            ints[i] = j;\n        }\n        int sum = 0;\n        for (int i = 0; i &lt; ints.length; i++) {\n            sum += ints[i];\n        }\n        if (sum % 10 == 0) {\n           return true;\n        } else {\n            return false;\n        }\n\n\n    }\n\nthen call this method\n\nEdittext mCreditCardNumberEt;\n\n mCreditCardNumberEt.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n             int cardcount=   s.toString().length();\n                 if(cardcount&gt;=16) {\n                    boolean cardnumbervalid=   validateCreditCardNumber(s.toString());\n                    if(cardnumbervalid) {\n                        cardvalidtesting.setText("Valid Card");\n                        cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.green));\n                    }\n                    else {\n                        cardvalidtesting.setText("Invalid Card");\n                        cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red));\n                    }\n                }\n               else if(cardcount&gt;0 &amp;&amp;cardcount&lt;16) {\n                     cardvalidtesting.setText("Invalid Card");\n                     cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red));\n                }\n\n                else {\n                    cardvalidtesting.setText("");\n\n                }\n\n\n                }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n\n            }\n        });\n</code></pre>\n'}, {'answer_id': 58241706, 'author': 'OhhhThatVarun', 'author_id': 7436566, 'author_profile': 'https://Stackoverflow.com/users/7436566', 'pm_score': 1, 'selected': False, 'text': '<p>Try this for kotlin. Add Regex and add to the when statement.</p>\n\n<pre><code>private fun getCardType(number: String): String {\n\n        val visa = Regex("^4[0-9]{12}(?:[0-9]{3})?$")\n        val mastercard = Regex("^5[1-5][0-9]{14}$")\n        val amx = Regex("^3[47][0-9]{13}$")\n\n        return when {\n            visa.matches(number) -&gt; "Visa"\n            mastercard.matches(number) -&gt; "Mastercard"\n            amx.matches(number) -&gt; "American Express"\n            else -&gt; "Unknown"\n        }\n    }\n</code></pre>\n'}, {'answer_id': 62955455, 'author': 'Emanuel', 'author_id': 6638583, 'author_profile': 'https://Stackoverflow.com/users/6638583', 'pm_score': 2, 'selected': False, 'text': '<p>A javascript improve of @Anatoliy answer</p>\n<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">\r\n<div class="snippet-code">\r\n<pre class="snippet-code-js lang-js prettyprint-override"><code>function getCardType (number) {\n  const numberFormated = number.replace(/\\D/g, \'\')\n  var patterns = {\n    VISA: /^4[0-9]{12}(?:[0-9]{3})?$/,\n    MASTER: /^5[1-5][0-9]{14}$/,\n    AMEX: /^3[47][0-9]{13}$/,\n    ELO: /^((((636368)|(438935)|(504175)|(451416)|(636297))\\d{0,10})|((5067)|(4576)|(4011))\\d{0,12})$/,\n    AURA: /^(5078\\d{2})(\\d{2})(\\d{11})$/,\n    JCB: /^(?:2131|1800|35\\d{3})\\d{11}$/,\n    DINERS: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,\n    DISCOVERY: /^6(?:011|5[0-9]{2})[0-9]{12}$/,\n    HIPERCARD: /^(606282\\d{10}(\\d{3})?)|(3841\\d{15})$/,\n    ELECTRON: /^(4026|417500|4405|4508|4844|4913|4917)\\d+$/,\n    MAESTRO: /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)\\d+$/,\n    DANKORT: /^(5019)\\d+$/,\n    INTERPAYMENT: /^(636)\\d+$/,\n    UNIONPAY: /^(62|88)\\d+$/,\n  }\n  for (var key in patterns) {\n    if (patterns[key].test(numberFormated)) {\n      return key\n    }\n  }\n}\n\nconsole.log(getCardType("4539 5684 7526 2091"))</code></pre>\r\n</div>\r\n</div>\r\n</p>\n'}, {'answer_id': 64923841, 'author': 'Saharat Sittipanya', 'author_id': 10767168, 'author_profile': 'https://Stackoverflow.com/users/10767168', 'pm_score': 2, 'selected': False, 'text': '<blockquote>\n<p><strong>Swift 5+</strong></p>\n</blockquote>\n<pre><code>extension String {\n    \n    func isMatch(_ Regex: String) -&gt; Bool {\n        \n        do {\n            let regex = try NSRegularExpression(pattern: Regex)\n            let results = regex.matches(in: self, range: NSRange(self.startIndex..., in: self))\n            return results.map {\n                String(self[Range($0.range, in: self)!])\n            }.count &gt; 0\n        } catch {\n            return false\n        }\n        \n    }\n    \n    func getCreditCardType() -&gt; String? {\n        \n        let VISA_Regex = &quot;^4[0-9]{6,}$&quot;\n        let MasterCard_Regex = &quot;^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$&quot;\n        let AmericanExpress_Regex = &quot;^3[47][0-9]{5,}$&quot;\n        let DinersClub_Regex = &quot;^3(?:0[0-5]|[68][0-9])[0-9]{4,}$&quot;\n        let Discover_Regex = &quot;^6(?:011|5[0-9]{2})[0-9]{3,}$&quot;\n        let JCB_Regex = &quot;^(?:2131|1800|35[0-9]{3})[0-9]{3,}$&quot;\n        \n        if self.isMatch(VISA_Regex) {\n            return &quot;VISA&quot;\n        } else if self.isMatch(MasterCard_Regex) {\n            return &quot;MasterCard&quot;\n        } else if self.isMatch(AmericanExpress_Regex) {\n            return &quot;AmericanExpress&quot;\n        } else if self.isMatch(DinersClub_Regex) {\n            return &quot;DinersClub&quot;\n        } else if self.isMatch(Discover_Regex) {\n            return &quot;Discover&quot;\n        } else if self.isMatch(JCB_Regex) {\n            return &quot;JCB&quot;\n        } else {\n            return nil\n        }\n        \n    }\n    \n}\n</code></pre>\n<blockquote>\n<p><strong>Use.</strong></p>\n</blockquote>\n<pre><code>&quot;1234123412341234&quot;.getCreditCardType()\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/72768', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/12382/']