# How to block fraudulent customers in Stripe

- Tool: Stripe
- Difficulty: Beginner
- Time required: 15 minutes
- Compatibility: Stripe API v2024-12+, Radar included on all accounts
- Last updated: March 2026

## TL;DR

Stripe Radar is a machine learning fraud detection system included with every Stripe account. You can enhance it with custom rules to block specific emails, IP addresses, countries, or card fingerprints. This guide covers enabling Radar, creating block rules, managing block lists, and handling blocked payments — all through the Dashboard and API.

## Blocking Fraudulent Payments with Stripe Radar

Stripe Radar uses machine learning trained on billions of transactions across the Stripe network to detect fraud. It is enabled by default and blocks high-risk payments automatically. You can extend Radar with custom rules to block specific customer attributes — email domains, IP addresses, card countries, or repeat offenders. For businesses needing more control, Radar for Fraud Teams ($0.07/screened transaction) adds manual review queues and advanced rules.

## Before you start

- A Stripe account in live or test mode
- Access to the Stripe Dashboard
- Node.js 18 or later for API examples
- Stripe Node.js SDK: npm install stripe

## Step-by-step guide

### 1. Understand Stripe Radar's default protection

Radar runs automatically on every payment. It assigns a risk score and blocks payments that exceed the threshold. No code changes are needed for basic protection.

```
// Radar evaluates every PaymentIntent automatically
// Risk levels: normal, elevated, highest
// Check a charge's risk assessment:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

async function checkRiskLevel(chargeId) {
  const charge = await stripe.charges.retrieve(chargeId);
  const outcome = charge.outcome;

  console.log('Risk level:', outcome.risk_level); // normal, elevated, highest
  console.log('Risk score:', outcome.risk_score); // 0-100
  console.log('Seller message:', outcome.seller_message);
  console.log('Type:', outcome.type); // authorized, blocked, manual_review
}

checkRiskLevel('ch_chargeId');
```

**Expected result:** Console displays the charge's risk assessment including risk level, score, and whether it was blocked.

### 2. Create custom block rules in the Dashboard

Go to Dashboard → Radar → Rules. Create rules to block payments matching specific criteria. Rules use Stripe's rule language.

```
// Example Radar rules (create these in Dashboard → Radar → Rules):
//
// Block payments from disposable email domains:
//   Block if :email_domain: in ('mailinator.com', 'guerrillamail.com', 'tempmail.com')
//
// Block payments from specific countries:
//   Block if :card_country: in ('XX', 'YY')
//
// Block payments over a threshold from new customers:
//   Block if :is_new_customer: and :amount_in_usd: > 500
//
// Block if CVC check fails:
//   Block if :cvc_check: = 'fail'
//
// Block if ZIP code does not match:
//   Block if :zip_check: = 'fail' and :amount_in_usd: > 100

console.log('Create these rules in Dashboard → Radar → Rules');
```

**Expected result:** Custom rules are created in the Radar Dashboard and will apply to all future payments.

### 3. Manage block lists via the API

Add specific emails, card fingerprints, or IP addresses to block lists using the Stripe API. Blocked entries are checked on every payment.

```
// Add an email to the block list
async function blockEmail(email) {
  const rule = await stripe.radar.valueListItems.create({
    value_list: 'rsl_blockedEmails', // Create this list first in Dashboard
    value: email,
  });
  console.log('Blocked email:', rule.value);
}

// Add a card fingerprint to the block list
async function blockCard(cardFingerprint) {
  const rule = await stripe.radar.valueListItems.create({
    value_list: 'rsl_blockedCards',
    value: cardFingerprint,
  });
  console.log('Blocked card fingerprint:', rule.value);
}

// Create a value list first
async function createBlockList() {
  const list = await stripe.radar.valueLists.create({
    alias: 'blocked_emails',
    name: 'Blocked Emails',
    item_type: 'email',
  });
  console.log('Block list created:', list.id);
}

createBlockList();
```

**Expected result:** Block lists are created and populated. Any payment from a blocked email or card is automatically declined.

### 4. Handle blocked payments in your webhook

When Radar blocks a payment, you receive a charge.failed or payment_intent.payment_failed event with an outcome type of 'blocked'. Handle this in your webhook to log fraud attempts.

```
const express = require('express');
const app = express();

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  if (event.type === 'charge.failed') {
    const charge = event.data.object;
    if (charge.outcome && charge.outcome.type === 'blocked') {
      console.log('FRAUD BLOCKED:', {
        chargeId: charge.id,
        riskScore: charge.outcome.risk_score,
        riskLevel: charge.outcome.risk_level,
        reason: charge.outcome.reason,
        email: charge.billing_details?.email,
        ip: charge.metadata?.customer_ip,
      });
      // Log to your fraud monitoring system
    }
  }

  res.json({ received: true });
});

app.listen(3000);
```

**Expected result:** Your webhook handler logs all Radar-blocked payments for fraud monitoring and investigation.

## Complete code example

File: `fraud-blocking.js`

```javascript
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const express = require('express');
const app = express();

app.use(express.json());

// Block a customer by email
app.post('/api/fraud/block-email', async (req, res) => {
  try {
    const item = await stripe.radar.valueListItems.create({
      value_list: req.body.listId,
      value: req.body.email,
    });
    res.json({ blocked: item.value });
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

// List all blocked items
app.get('/api/fraud/blocked/:listId', async (req, res) => {
  try {
    const items = await stripe.radar.valueListItems.list({
      value_list: req.params.listId,
      limit: 100,
    });
    res.json(items.data.map(i => ({ id: i.id, value: i.value })));
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

// Remove a block
app.delete('/api/fraud/unblock/:itemId', async (req, res) => {
  try {
    await stripe.radar.valueListItems.del(req.params.itemId);
    res.json({ unblocked: true });
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

// Webhook for fraud events
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body, sig, process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }
  if (event.type === 'charge.failed') {
    const charge = event.data.object;
    if (charge.outcome?.type === 'blocked') {
      console.log(`Blocked: ${charge.id} | Risk: ${charge.outcome.risk_score}`);
    }
  }
  if (event.type === 'radar.early_fraud_warning.created') {
    console.log('Early fraud warning:', event.data.object.charge);
  }
  res.json({ received: true });
});

app.listen(3000, () => console.log('Fraud blocking server on port 3000'));
```

## Common mistakes

- **Creating overly broad block rules that catch legitimate customers** — undefined Fix: Start with review rules instead of block rules. Monitor for false positives before promoting to block.
- **Not passing billing details to Stripe for Radar to evaluate** — undefined Fix: Include email, name, and address in PaymentIntent billing_details. More data gives Radar better fraud detection.
- **Relying solely on Radar without monitoring blocked charges** — undefined Fix: Set up webhooks for charge.failed and radar.early_fraud_warning.created to track and investigate fraud patterns.
- **Blocking by IP address only, which catches users behind shared IPs** — undefined Fix: Use multiple signals (email, card fingerprint, device fingerprint) rather than IP alone.

## Best practices

- Pass billing_details (email, name, address) on every PaymentIntent for better Radar accuracy
- Start with review rules and promote to block rules after confirming the pattern
- Use Radar value lists for dynamic blocking instead of hardcoding blocked emails
- Monitor the radar.early_fraud_warning.created webhook for proactive fraud detection
- Review Radar's blocked and elevated-risk payments weekly to tune your rules
- Combine CVC and ZIP checks with amount thresholds for nuanced fraud prevention
- For high-volume businesses, consider Radar for Fraud Teams for manual review queues

## Frequently asked questions

### Is Stripe Radar free?

Basic Radar is included with every Stripe account at no extra cost. Radar for Fraud Teams, which adds manual review queues and advanced rules, costs $0.07 per screened transaction.

### Can I block an entire country with Radar?

Yes. Create a rule like 'Block if :card_country: in (XX, YY)' where XX and YY are ISO country codes. Be careful as this blocks all legitimate customers from those countries too.

### How do I unblock a customer who was incorrectly blocked?

Remove their email, card fingerprint, or IP from the Radar value list via Dashboard or API. The next payment attempt from that customer will be evaluated normally.

### What is a card fingerprint?

A card fingerprint is a unique hash of the card number. Different customers using the same card have the same fingerprint, making it useful for blocking specific cards regardless of which account uses them.

### Can RapidDev help set up advanced fraud rules?

Yes. RapidDev can help configure Radar rules, build fraud monitoring dashboards, and implement custom fraud detection logic tailored to your business patterns.

---

Source: https://www.rapidevelopers.com/stripe-guide/how-to-block-fraudulent-customers-in-stripe
© RapidDev — https://www.rapidevelopers.com/stripe-guide/how-to-block-fraudulent-customers-in-stripe
