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:
200withContent-Type: application/json; charset=utf-8when at least one BIN starts with those digits,404when none does.Access-Control-Allow-Origin: *, so you can call it from browser JavaScript on any site.Cache-Control: public, max-age=86400— cache files for a day; they change only when the dataset is updated.- No key, no sign-up, no cookies. Only three digits leave your system, never a full BIN or card number.
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]}}
| Position | Field | Meaning |
|---|---|---|
| 0 | brand | Card network: Visa, Mastercard, American Express, RuPay, Elo, Mir… |
| 1 | type | Debit, Credit or Charge card |
| 2 | level | Product level: Classic, Gold, Platinum, Business, Prepaid… |
| 3 | issuer | Issuing bank or institution (normalized name) |
| 4 | iso2 | ISO 3166-1 alpha-2 country code |
| 5 | country | Country name |
| 6 | phone | Issuer phone number from the dataset (validated) |
| 7 | url | Issuer website from the dataset (validated) |
| 8 | bankPage | Path of our bank page, if the bank has 10+ BINs |
| 9 | countryPage | Path 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:
- Cache downloaded files (a day is fine; the data changes rarely) instead of requesting the same file for every lookup.
- Keep automated jobs to about one request per second. For bulk work, download the source dataset once instead of crawling all 770 files.
- Set a descriptive
User-Agentso we can contact you before blocking a misbehaving client. - No uptime guarantee. For production payment routing, use your acquirer's or the card networks' official BIN tables.
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.