• Blackhat Pakistan — Ethical Hacking, Hacking Tools & Cybersecurity Tutorials

How to Make a Gift Card Checker 2026

Blackhatpakistan

Administrator
Staff member
Joined
Dec 30, 2024
Messages
435
Reaction score
219
Points
62
Website
blackhatpakistan.net
Points
1,378
USD
1,378
gpb6ye.png


A gift card checker probes card balance through the issuer's own balance-check flow — and every issuer's flow is a different gate with different abuse signals. Starbucks, Walmart, Amazon, Visa-prepaid, Target, Sephora: each runs a web endpoint where card number plus PIN returns remaining balance, and each prices the probing differently — rate limits, CAPTCHA escalation after N checks per IP, IP-reputation scoring, and velocity flags that fire when the same card number gets checked from multiple geographies in short windows. The checker's architecture follows the same pipeline as every other checker (prefilter, probe layer, classification, output classes) with one domain-specific twist: balance-probe flows are session-bearing multi-step requests, which means fingerprint-coherence and proxy-binding disciplines apply at every probe. This is gift-card checking decoded: the issuer-gate map, the balance-flow anatomy, the anti-abuse signals that end runs, and the output records that feed resale and cashout pipelines. Post your balance-check log — cleanest live-rate gets pinned to Carding-method, first fifteen get the per-program escalation threshold table via PM.

TL;DR - Gift card formats split into two probe-relevant classes: store-branded cards (Starbucks, Amazon, Walmart, Target and the long tail) whose balance-check flows live on the retailer's own web properties, and network-prepaid cards (Visa/Mastercard prepaid gift) whose balance inquiry lives on the program's portal — the card-number format differs per class and the PIN requirement differs (store cards often check with number alone, network-prepaid almost always requires the PIN — which is why checker input for network prepaid is number|pin pairs). The balance-check flow follows a common shape: GET the check page (session cookie + anti-CSRF token captured), POST the card number (and PIN) to the check endpoint with the token, parse the response (balance value, card status active/used/locked, sometimes expiry) — the multi-step, session-bearing pattern that demands per-probe fingerprint coherence. Anti-abuse layer: rate limits per IP (429s after check-count thresholds), CAPTCHA escalation (reCAPTCHA/Turnstile appearing after N checks per IP or on suspicious IP-reputations), card-level velocity flags (same card checked repeatedly or from shifting geographies raises issuer alarms — some programs lock cards on suspicious-check patterns), and IP-reputation scoring (datacenter exits hit CAPTCHA walls faster than residential on every major program). Survival stack: sticky residential per-session binding, per-IP check pacing below program thresholds, captcha-class routing to solve-or-park, card-level check-count caps (a card checked twice is data; a card checked eight times is a flag).

55vs1l.png


THE ISSUER-GATE MAP

- Store-branded programs: number-only or number+PIN depending on program (the queue segmentation handles mixed lists); check flows on the retailer's own domain with program-specific field sets; number-shape validation per program (a 15-digit number routed to a 16-digit program dies at prefilter); pacing thresholds differ per program and shift with the program's risk posture — the operational test is small-batch calibration runs graphing check-count-against-escalation on fresh residential exits.
- Network-prepaid programs (Visa/Mastercard gift): number|pin pairs per line — the PIN is required on nearly all network-prepaid check portals, and lines without PINs route to their own queue or park rather than failing silently in the main probe; Luhn-checksum prefilter applies (same layer-one economics as CC checking — malformed numbers never earn probe requests); balance band typically $25-$500 face.
- Session-flow anatomy across programs: GET check page through the bound sticky residential exit (session cookie captured, UA fingerprint fixed for the session, anti-CSRF token extracted — left/right extraction on the token input or JSON-path where the program exposes an API-layer token endpoint); POST card number (and PIN) with the extracted token, session cookie, and mirrored Referer/Origin headers matching the check page's origin (mismatched origin headers are free detection signals the bot-layers happily score); response parsing extracts balance value, card status, and sometimes expiry.
- Prefilter economics: dedup collapses duplicate card numbers; prior-result exclusion pulls known balances, locked cards, and dead cards from re-probe queues unless a refresh-pass flag explicitly includes them; format parsing normalizes paste-format variance (spaces, dashes stripped) and validates length/prefix against program shape before any probe request fires.

u6o8dn.png


CODE: INPUT NORMALIZER + PREFILTER

Formats first: store-card programs parsed to their expected field sets, network-prepaid normalized to number|pin pairs, Luhn filter where the format uses it, dedup, and queue segmentation by program. The prefilter keeps the probe layer clean — malformed lines never earn probe requests.

Code:
# gift card prefilter: normalize, Luhn-check, dedup, segment by program

import re

PROGRAMS = {

    "starbucks":  {"digits": 16, "luhn": True,  "pin": False},

    "amazon":     {"digits": 16, "luhn": True,  "pin": False},

    "walmart":    {"digits": 16, "luhn": True,  "pin": False},

    "visa_prep":  {"digits": 16, "luhn": True,  "pin": True},

    "mc_prep":    {"digits": 16, "luhn": True,  "pin": True},

}

def luhn(num):

    digits = [int(d) for d in num][::-1]

    total = 0

    for i, d in enumerate(digits):

        if i % 2 == 1:

            d *= 2

            if d > 9:

                d -= 9

        total += d

    return total % 10 == 0

def normalize_line(line):

    line = line.strip()

    if "|" in line:

        num, pin = line.split("|", 1)

    else:

        num, pin = line, None

    num = re.sub(r"[\s\-]", "", num)

    return num, pin

def classify_program(num, pin):

    for prog, spec in PROGRAMS.items():

        if len(num) == spec["digits"]:

            if spec["pin"] and not pin:

                return prog, "PIN_MISSING"  # park, don't silently drop

            if spec["luhn"] and not luhn(num):

                return prog, "LUHN_FAIL"

            return prog, "OK"

    return "unknown", "SHAPE_FAIL"

def prefilter(lines):

    queues = {}

    seen = set()

    rejected = 0

    for line in lines:

        if not line.strip():

            continue

        num, pin = normalize_line(line)

        if num in seen:

            rejected += 1

            continue

        seen.add(num)

        prog, status = classify_program(num, pin)

        if status != "OK":

            rejected += 1

            continue

        queues.setdefault(prog, []).append((num, pin))

    return queues, rejected

demo = ["4111 1111 1111 1111|123", "4111-1111-1111-1111|123", "5500000000000004|999", "bad-line"]

q, rej = prefilter(demo)

print("queues:", {k: len(v) for k, v in q.items()}, "| rejected:", rej)

ANTI-ABUSE SURVIVAL

- Pacing per program: per-IP check-counts kept below observed escalation thresholds — the thresholds differ per program and shift with the program's risk posture; the pacing knob is per-IP-per-program, which multiplies with the proxy pool's size to decide throughput — more clean exits, more parallel pacing windows, more checks/hour without escalation.
- Captcha-escalation handling: the appearance of a challenge widget mid-run (after N checks on one exit) parks that exit's session and routes the current card to the captcha-branch (solve-and-retry on a fresh session, or park for a later pass on fresher egress); the run report tracks escalation-rate per program per exit-range — a rising escalation rate means the range's reputation is aging, rotate before the whole program starts CAPTCHA-first on that range.
- Card-level velocity caps: each card number gets a max-check-count per run (two is the working default — initial check plus one confirm) and a re-probe cooldown across runs (a card re-checked the next day earns its refresh; a card re-checked in the same hour is operator error or a stuck retry loop, both of which raise issuer-side flags on the card itself); the caps live in the runner's state layer (checked-card registry with timestamps), not in the input files.
- Egress hygiene: sticky residential per session (never datacenter on check endpoints — the reputation scoring hits datacenter ranges immediately on the major programs), session exits rotating between worker-pools (not per-card within a worker — session coherence preserved per binding, pool diversity across bindings), and DNS-resolution discipline (remote resolution via the exit, no local-DNS leak fingerprints).

dreddd.png


CODE: SESSION FLOW + VELOCITY-REGISTRY

The balance-flow probe carries the session through all cards checked in that worker's binding; the velocity-registry enforces the per-run check-count cap and the cross-run cooldown in state, not in input files.

Code:
# session-bearing balance probe + checked-card velocity registry

import requests, time, re

MAX_CHECKS_PER_RUN = 2       # initial + one confirm

REPROBE_COOLDOWN_S = 86400   # 24h cross-run cooldown

checked_registry = {}  # card_num -> [timestamps]

def extract_csrf(page_html):

    # left/right extraction on hidden token input

    m = re.search(r'name="_csrf"[^>]*value="([^"]+)"', page_html)

    if not m:

        m = re.search(r'value="([^"]+)"[^>]*name="_csrf"', page_html)

    return m.group(1) if m else None

def check_balance(session, check_url, card_num, pin=None, proxy_str=None):

    """Session-bearing probe: page-GET, token extract, POST with mirrored headers."""

    r = session.get(check_url, timeout=20)

    token = extract_csrf(r.text)

    if not token:

        return "NO_TOKEN"

    payload = {"cardNumber": card_num}

    if pin:

        payload["pin"] = pin

    payload["_csrf"] = token

    # mirrored Referer/Origin matching the check page

    headers = {"Referer": check_url, "Origin": check_url.rsplit("/", 1)[0]}

    r2 = session.post(check_url, data=payload, headers=headers, timeout=20)

    if r2.status_code == 429:

        return "DEFER_429"

    if "captcha" in r2.text.lower() or "challenge" in r2.text.lower():

        return "CHALLENGE"

    bal = re.search(r'"balance"\s*:\s*"?([\d.]+)', r2.text)

    status = re.search(r'"status"\s*:\s*"(\w+)"', r2.text)

    if bal and status:

        return (status.group(1), float(bal.group(1)))

    return "UNKNOWN"

def velocity_gate(card_num, run_id):

    """Enforce per-run cap + cross-run cooldown. Returns True if check allowed."""

    now = time.time()

    history = checked_registry.get(card_num, [])

    # cross-run cooldown: any check within cooldown window blocks

    if history and (now - history[-1]) < REPROBE_COOLDOWN_S:

        return False  # cooldown active

    # per-run cap: count checks from this run

    run_checks = [t for t in history if run_id in str(t)]  # simplified

    if len(run_checks) >= MAX_CHECKS_PER_RUN:

        return False

    checked_registry.setdefault(card_num, []).append(now)

    return True

# usage: gate before every probe, never rely on input-file dedup alone

print("velocity gate: max", MAX_CHECKS_PER_RUN, "checks/run, cooldown", REPROBE_COOLDOWN_S, "s")

DETECTION LAYER

What runs against a gift-card checker: per-IP rate limits escalating to 429s and then CAPTCHA after check-count thresholds; IP-reputation scoring that hits datacenter exits immediately on major programs; card-level velocity flags that lock cards checked repeatedly or from shifting geographies (some programs hard-lock on suspicious-check patterns); CSRF-token freshness windows (tokens expire, stale-token posts fail cleanly but leave a logged failure against the session); and session-coherence fingerprinting (mid-session exit changes are a deterministic bot-signal on these flows). The detection surface is the program's own abuse-monitoring stack — every probe is a logged event, which is why the velocity caps and sticky-binding discipline are not optional at volume.

o9485r.png


OPSEC CHECKLIST

- Sticky residential per session, never datacenter on check endpoints — the reputation scoring on major programs hits datacenter ranges immediately; the proxy-class decision multiplies into every other survival knob.
- Calibrate pacing per program before volume: small-batch test runs on fresh exits graph the check-count-against-escalation curve per program — the thresholds differ and shift, and guessing them burns exits in the first hour.
- Card-level velocity caps enforced in state, not judgment: max two checks per card per run, cross-run cooldown registry — a card checked eight times is a flag, not a data point.
- Escalation-rate tracking per exit-range: the run report's early-warning — escalation creeping up on a range means rotate before ban-wave; the range's reputation ages faster than the operator notices.
- PIN-bearing lines never silently dropped: network-prepaid lines without PINs park in their own queue — silent drops corrupt the input census and hide list-quality problems.
- Balance-value discipline: the parsed balance feeds the output record exactly as the program reports it (decimal-formatted, currency-tagged where multi-currency) — resale markets price by program+balance, so the record's sort keys are the handoff contract.

TEST YOURSELF: SIX QUESTIONS

Score honestly: (1) what is the difference between store-branded and network-prepaid gift card formats, and which one requires number|pin pairs? (2) why is the balance-check flow session-bearing, and what does that demand of the probe layer? (3) your Starbucks queue escalates to CAPTCHA after 20 checks on one exit but your Visa-prepaid queue escalates after 6 — what does that tell you about per-program pacing? (4) a card returns "locked" with a lock-reason code — which class file does it join, and why does it not go to the resale queue regardless of prior balance? (5) what does the checked-card registry enforce that input files cannot? (6) your run report shows escalation-rate creeping up on one exit range while other ranges stay flat — what is the actionable move before the ban-wave? Zero to one: you read the TL;DR. Two to three: re-run your last batch's escalation-rate-per-range numbers and compare to the program thresholds. Four plus: post your scoreboard with live-rate per program.

uqtsvt.png


POST YOUR LOG

Scoreboard format: programs in batch, checks-per-hour per program, escalation-rate per exit-range per program, live-rate per program (active-with-balance count / total checked), balance-distribution stats on live-class (min/median/max), zero-class count, locked-class count with lock-reasons, dead count, challenge-parked count, wall time. Field-log framing, own cards only. Cleanest live-rate gets pinned to Carding-method, first fifteen posters get the per-program escalation threshold table via PM — observed check-count-against-CAPTCHA curves per major program by exit-range age, plus the network-prepaid PIN-handling queue pattern.

FAQ

- Q: How does a gift card balance checker actually work?

A: The issuer's own check flow: session page-load (capture cookie + anti-CSRF token), POST the card number (and PIN where required) to the check endpoint, parse the response for balance value and card status — multi-step session-bearing requests per program, which is why per-probe fingerprint coherence and sticky residential binding matter exactly like every other session-flow checker.
- Q: Why do gift card checkers hit CAPTCHA so fast?

A: Rate limits per IP escalate to CAPTCHA after check-count thresholds, and IP-reputation scoring hits datacenter exits immediately on major programs. The survival stack: sticky residential per session, per-IP pacing below observed escalation thresholds (calibrated per program), captcha-class routing to solve-or-park, and escalation-rate-per-range tracking so aging exit ranges rotate before CAPTCHA-first becomes the default.
- Q: What input format does the checker expect?

A: Store cards: the program's expected fields (number-only or number+PIN depending on program — the queue segmentation handles mixed lists). Network prepaid (Visa/Mastercard gift): number|pin pairs per line — the PIN is required on nearly all network-prepaid check portals, and lines without PINs route to their own queue or park rather than failing silently in the main probe.
- Q: Should I re-check cards from previous runs?

A: Only under a refresh flag with cooldown discipline — prior results (balances, dead, locked) exclude from default re-probe queues because balances rarely change on checked cards, re-probing known-dead wastes budget, and check-velocity on the same cards raises issuer-side flags; the checked-card registry with timestamps enforces both the per-run cap and the cross-run cooldown.
- Q: What does the locked class mean?

A: The program reports the card as locked/suspended — often issuer-side security response (velocity flags, fraud holds, or the card being reported) — recorded with the lock-reason where the response carries one; locked-class feeds program-trend analysis (which programs lock aggressively on check patterns) and does not join the resale queue regardless of prior balance, since a locked card does not convert at the issuer.
- Q: How do balances feed resale and cashout?

A: Live-class records carry program + parsed balance + currency + timestamp — resale markets price programs differently (store-brand at spread discounts by program liquidity, network-prepaid closer to face on the right markets); freshness matters (balance-checked-today records price better than week-old), which is why the timestamp rides every handoff record.

RELATED

Carding Tools 2026 - BIN Checkers & Validators

How CC Checkers Actually Work - Response Codes, CPM and Accuracy

Cashout Pipeline 2026 - Material to Landed Money

Proxies for Carding 2026 - Complete Proxy Guide
 
Threads
1,152Threads
Messages
2,308Messages
Members
3,771Members
Latest member
BlotmotLatest member
Top