Advertisement

Free BIN Lookup API

Look up card BINs from your own code: 374,788 BINs served as static JSON with CORS enabled. No API key, no sign-up, no rate-limit headers — just credit the data source.

Advertisement
Requests GET https://fakecreditcard.co/data/bin/401.json and decodes the entry for the last digits.
{
  "brand": "Visa",
  "type": "Credit",
  "level": "Traditional",
  "issuer": "JPMorgan Chase Bank N.A.",
  "iso2": "US",
  "country": "United States",
  "phone": "",
  "url": "",
  "bankPage": "/bin-list/united-states/jpmorgan-chase-bank",
  "countryPage": "/bin-list/united-states/"
}
374,788BINs
770JSON files
CORSany origin
0API keys needed
Advertisement

Endpoint

GET https://fakecreditcard.co/data/bin/{first 3 digits}.json

Each file holds every BIN that starts with the same three digits — 1,000 BINs in 401.json, for example. Download the file for the first three digits of your BIN, then read the entry for digits 4–6. Responses are plain static files:

Response format

To keep files small, every string is stored once in s (a string table), and each BIN in r is a list of indexes into it. Index 0 is always the empty string, and trailing empty values are left out. This is the real entry for BIN 401135, cut down to that one BIN:

{"s":["","Visa","Credit","Traditional","JPMorgan Chase Bank N.A.","US","United States","/bin-list/united-states/jpmorgan-chase-bank","/bin-list/united-states/"],"r":{"135":[1,2,3,4,5,6,0,0,7,8]}}
PositionFieldMeaning
0brandCard network: Visa, Mastercard, American Express, RuPay, Elo, Mir…
1typeDebit, Credit or Charge card
2levelProduct level: Classic, Gold, Platinum, Business, Prepaid…
3issuerIssuing bank or institution (normalized name)
4iso2ISO 3166-1 alpha-2 country code
5countryCountry name
6phoneIssuer phone number from the dataset (validated)
7urlIssuer website from the dataset (validated)
8bankPagePath of our bank page, if the bank has 10+ BINs
9countryPagePath of our country BIN list page

Decoded, the entry above reads:

{
  "brand": "Visa",
  "type": "Credit",
  "level": "Traditional",
  "issuer": "JPMorgan Chase Bank N.A.",
  "iso2": "US",
  "country": "United States",
  "phone": "",
  "url": "",
  "bankPage": "/bin-list/united-states/jpmorgan-chase-bank",
  "countryPage": "/bin-list/united-states/"
}

Code examples

curl + jq

curl -s https://fakecreditcard.co/data/bin/401.json | jq --arg k 135 '.s as $s | .r[$k] as $a
  | ["brand","type","level","issuer","iso2","country","phone","url","bankPage","countryPage"]
  | to_entries | map({(.value): $s[$a[.key] // 0]}) | add'

JavaScript (browser or Node 18+)

const FIELDS = ['brand', 'type', 'level', 'issuer', 'iso2', 'country', 'phone', 'url', 'bankPage', 'countryPage'];

async function lookupBin(bin) {
  const digits = String(bin).replace(/\D/g, '').slice(0, 8);
  const res = await fetch(`https://fakecreditcard.co/data/bin/${digits.slice(0, 3)}.json`);
  if (!res.ok) return null;                       // 404: no BIN starts with these 3 digits
  const shard = await res.json();
  const row = shard.r[digits.slice(3, 6)];
  if (!row) return null;
  return Object.fromEntries(FIELDS.map((f, i) => [f, shard.s[row[i] || 0]]));
}

lookupBin('401135').then(console.log);

Python (standard library)

import json
import urllib.error
import urllib.request

FIELDS = ['brand', 'type', 'level', 'issuer', 'iso2', 'country', 'phone', 'url', 'bankPage', 'countryPage']

def lookup_bin(bin_):
    digits = ''.join(c for c in str(bin_) if c.isdigit())[:8]
    req = urllib.request.Request(f'https://fakecreditcard.co/data/bin/{digits[:3]}.json', headers={'User-Agent': 'my-app/1.0'})
    try:
        with urllib.request.urlopen(req, timeout=10) as r:
            shard = json.load(r)
    except urllib.error.HTTPError:
        return None                                # 404: no BIN starts with these 3 digits
    row = shard['r'].get(digits[3:6])
    if row is None:
        return None
    return {f: shard['s'][row[i]] if i < len(row) else '' for i, f in enumerate(FIELDS)}

print(lookup_bin('401135'))

PHP

<?php
function lookup_bin($bin) {
    $digits = substr(preg_replace('/\D/', '', (string) $bin), 0, 8);
    $json = @file_get_contents('https://fakecreditcard.co/data/bin/' . substr($digits, 0, 3) . '.json');
    if ($json === false) {
        return null;                               // 404: no BIN starts with these 3 digits
    }
    $shard = json_decode($json, true);
    $key = substr($digits, 3, 3);
    if (!isset($shard['r'][$key])) {
        return null;
    }
    $fields = array('brand', 'type', 'level', 'issuer', 'iso2', 'country', 'phone', 'url', 'bankPage', 'countryPage');
    $out = array();
    foreach ($fields as $i => $f) {
        $out[$f] = $shard['s'][isset($shard['r'][$key][$i]) ? $shard['r'][$key][$i] : 0];
    }
    return $out;
}

print_r(lookup_bin('401135'));

Fair use

There is no hard rate limit, because there is no server code to enforce one — the files are served like images. Please keep it that way for everyone:

Attribution (CC BY 4.0)

The data is bin-list-data by Venelin Kochev, licensed under CC BY 4.0, normalized by Fakecreditcard. If you use it in an app, a website or a dataset, credit it where your users can see it — for example in your footer, about page or README:

BIN data: <a href="https://fakecreditcard.co/bin-api">Fakecreditcard BIN API</a>, based on
<a href="https://github.com/venelinkochev/bin-list-data">bin-list-data</a> (CC BY 4.0)

What the data can and cannot tell you

A BIN identifies the card network and the issuing institution of a range of card numbers. It says nothing about a particular card or cardholder and cannot tell whether a card exists or can be charged. Typical uses are showing the right card logo while a customer types, routing and reporting by card type or country, and BIN-based rules in test environments. To try those rules with safe data, generate numbers for any BIN with the BIN generator.

Frequently asked questions

Is the BIN API really free?

Yes. There is no key, no sign-up and no paid tier. The data files are static JSON on our web server, so the only conditions are the CC BY 4.0 attribution and fair use: cache what you download and do not hammer the server.

Why does the API return a whole file instead of one BIN?

Each file holds every BIN that shares the same first three digits. That keeps the API static (fast, cacheable, no server code) and private: the request only reveals three digits, never the full BIN or card number.

How do I look up an 8-digit BIN?

Use the first six digits. The dataset is keyed on 6-digit BINs; an 8-digit BIN falls inside the 6-digit range that shares its first six digits, so take bin.slice(0, 3) for the file and bin.slice(3, 6) for the key.

Can I use the BIN data commercially?

Yes, under the terms of CC BY 4.0: credit the source with a link, mention the license, and indicate if you changed the data. See the attribution snippet on this page.

How often is the data updated?

When the upstream bin-list-data dataset is updated and we rebuild the site. The ?v= parameter our own tools use changes with every data update; responses are cacheable for a day.

Related tools

Data source

BIN data: bin-list-data by Venelin Kochev (a lite version of binlookup.io), licensed under CC BY 4.0. Changes made by Fakecreditcard: issuer, brand and country names re-cased and standardized, spelling variants of the same issuer merged, malformed phone numbers and web addresses removed.

Advertisement