Prices increase in 00D : 00H : 00M Upgrade now Pay less later.

Blog / Technical Guide

Hard vs Soft Email Bounce: Fix Bounce Rate with MailValid API (2026)

Hard vs Soft Email Bounce: Fix Bounce Rate with MailValid API (2026)

Every Bounce Type Costs You Differently — Here's How to Stop Them All

Not all email bounces are created equal. A hard bounce destroys your sender reputation permanently. A soft bounce is a warning shot. And catch-all bounces? They're invisible — they look like deliveries but never reach a human inbox.

If you're running cold outreach, newsletters, or any high-volume email program, understanding bounce classification isn't optional — it's survival. ESPs track your bounce rate by type, and each category triggers different penalties.

Cut your bounce rate with MailValid → 100 free credits

This guide breaks down hard bounces, soft bounces, and catch-all traps. You'll learn the exact SMTP response codes that identify each type, how to diagnose your bounce rate, and how to integrate MailValid's email verification API to prevent bounces before they happen.

Hard Bounces: Permanent Delivery Failures

A hard bounce means the email address is permanently unreachable. The mailbox doesn't exist, the domain is dead, or the server explicitly rejects the recipient.

Common Hard Bounce SMTP Codes

Code Meaning Why It Happens
550 Mailbox unavailable Address doesn't exist
551 User not local Domain exists, user doesn't
552 Mailbox full (permanent) Rare — usually soft, but some servers treat as hard
553 Mailbox name not allowed Invalid format or restricted
554 Transaction failed Blacklisted or policy rejection

The Reputation Impact

Hard bounces are the most damaging bounce type because they signal list quality problems. Gmail, Outlook, and Yahoo track your hard bounce rate per campaign. Exceed 2% hard bounces and you enter the danger zone. Exceed 5% and you're likely throttled or blacklisted.

The fix is simple: Never send to an unverified address. MailValid's SMTP-level verification catches hard bounces before your message ever leaves your server.

Soft Bounces: Temporary Delivery Failures

Soft bounces indicate a temporary problem. The address might be valid, but the server can't accept mail right now.

Common Soft Bounce SMTP Codes

Code Meaning Typical Cause
421 Service not available Server overload or maintenance
450 Mailbox unavailable Often greylisting — try again later
451 Local error in processing Server-side temporary issue
452 Insufficient system storage Mailbox full
4xx Various temporary failures Greylisting, rate limiting, DNS timeout

When Soft Bounces Become Hard Bounces

The danger with soft bounces is that they degrade over time. A "mailbox full" address eventually gets deactivated by the provider. A greylisted server might permanently block you if you retry too aggressively.

Best practice: Retry soft bounces 2-3 times over 72 hours, then suppress the address if it still fails. For cold email, it's safer to remove soft-bouncing addresses entirely — your reputation is worth more than one additional contact.

Catch-All Bounces: The Invisible Problem

Catch-all domains are the most insidious bounce type because they don't bounce at all — at least not in the traditional sense.

A catch-all server accepts every email sent to its domain, regardless of whether the specific mailbox exists. Your ESP reports "delivered," but the message may never reach a real inbox. No reply. No open. No bounce notification.

How Catch-All Domains Distort Your Metrics

Metric Real Address Catch-All Domain
Delivery status Delivered Delivered (unconfirmed)
Open rate Trackable Often 0%
Reply rate Trackable Often 0%
Bounce rate Accurate Underreported
Reputation impact Normal Hidden risk

You may be sending emails that never reach a person while your delivery metrics look healthy. Over time, ESPs notice the zero engagement from these "delivered" emails and can penalize your domain anyway.

Detecting Catch-All Domains

Standard regex or MX checks can't identify catch-alls. It requires SMTP-level probing — attempting delivery to a randomized, guaranteed-nonexistent address at the same domain. If the server accepts it, the domain is catch-all.

MailValid flags catch-all domains as is_catch_all: true in every verification response.

Bounce Rate Benchmarks by Email Type

Bounce Type Acceptable Warning Critical
Hard bounce 0-1% 1-2% 2%+
Soft bounce 0-3% 3-5% 5%+
Catch-all "delivered" 0-5% 5-10% 10%+
Overall bounce 0-2% 2-5% 5%+

If your overall bounce rate exceeds 3%, pause all campaigns and clean your list immediately. This developer walkthrough on lowering bounce rates shows how to automate that cleanup.

How to Prevent Bounces with MailValid's API

Prevention is cheaper than recovery. Here's how to wire MailValid into your email workflow, using the documented request and response shape.

Python: Verify and Classify Before Sending

import requests

API_KEY = "your_mailvalid_api_key"

def classify_email(email):
    """Verify an email and return bounce risk classification."""
    resp = requests.post(
        "https://mailvalid.io/api/v1/verify/single",
        headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
        json={"email": email}
    )
    result = resp.json()["result"]

    if not result["is_valid"]:
        return {"risk": "HIGH", "type": "hard_bounce", "reason": result["status_reason"]}

    if result["is_catch_all"]:
        return {"risk": "MEDIUM", "type": "catch_all", "reason": "Domain accepts all emails"}

    if result["is_disposable"]:
        return {"risk": "HIGH", "type": "disposable", "reason": "Temporary email domain"}

    if result["is_role_based"]:
        return {"risk": "LOW", "type": "role_based", "reason": "Generic address (info, sales, etc.)"}

    return {"risk": "LOW", "type": "verified", "reason": result["status_reason"]}

# Example usage
emails = [
    "ceo@startup.com",
    "fake@nonexistent-domain.xyz",
    "admin@enterprise.com",
    "temp@10minutemail.com"
]

for email in emails:
    classification = classify_email(email)
    print(f"{email}: {classification['risk']} risk — {classification['type']}")

JavaScript: Real-Time Bounce Prevention

async function getBounceRisk(email) {
  const response = await fetch('https://mailvalid.io/api/v1/verify/single', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ email })
  });
  const { result } = await response.json();

  if (!result.is_valid) return { send: false, reason: result.status_reason, risk: 'hard_bounce' };
  if (result.is_catch_all) return { send: false, reason: 'catch_all', risk: 'hidden_risk' };
  if (result.is_disposable) return { send: false, reason: 'disposable', risk: 'hard_bounce' };
  return { send: true, risk: 'low' };
}

// Block high-risk addresses before they enter your sequence
const risk = await getBounceRisk('user@company.com');
if (!risk.send) {
  console.log(`Block: ${risk.reason} (${risk.risk})`);
}

Bulk Verification with Bounce Classification

For lists larger than a handful of addresses, use the bulk endpoint (POST /api/v1/verify/bulk, up to 10,000 emails per request, processed asynchronously) rather than looping single calls:

import requests
import time

API_KEY = "your_mailvalid_api_key"

def submit_bulk_verification(emails):
    resp = requests.post(
        "https://mailvalid.io/api/v1/verify/bulk",
        headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
        json={"emails": emails}
    )
    return resp.json()["job_id"]

def get_bulk_results(job_id):
    while True:
        status = requests.get(
            f"https://mailvalid.io/api/v1/verify/bulk/{job_id}",
            headers={"X-API-Key": API_KEY}
        ).json()
        if status["status"] == "completed":
            return status["results"]
        time.sleep(5)

job_id = submit_bulk_verification(["a@example.com", "b@example.com"])
results = get_bulk_results(job_id)
for r in results:
    print(f"{r['email']}: {r['status']}")

Building a Bounce-Resistant Email Workflow

Here's a workflow worth adopting for teams sending at meaningful volume:

1. Verify at Point of Capture

Use the JavaScript snippet above to validate emails in real-time as users type them into signup forms or lead capture pages.

2. Pre-Send Bulk Verification

Run every list through MailValid's bulk API 24 hours before sending. Remove all HIGH and MEDIUM risk addresses.

3. Segment by Risk Level

  • LOW risk: Primary sending sequence
  • MEDIUM risk (catch-all): Separate test sequence with low volume
  • HIGH risk: Suppressed permanently

4. Monitor Post-Send Bounces

Even verified lists can generate some soft bounces. Monitor your ESP's bounce reports and suppress repeat offenders.

5. Re-verify Quarterly

Email lists decay continuously. Re-verify your entire database every 90 days.

MailValid Pricing

Plan Monthly Price Credits Per-Email Cost
Free $0 100 (one-time) —
Pay as you go One-time packs from $8 2,000 – 1,000,000 $0.004 → ~$0.0009
Plus $29/mo 10,000 $0.0029
Plus $79/mo 50,000 $0.00158
Plus $129/mo 100,000 $0.00129
Enterprise Custom 250,000+/mo Custom

Credits never expire on any plan, and unknown results are free.

FAQ: Email Bounce Classification

What's worse: hard bounce or soft bounce?

Hard bounces are worse for reputation because they prove you're sending to non-existent addresses. However, a high soft bounce rate also signals poor list hygiene.

Can I fix a hard bounce?

No. Hard bounces are permanent. The only fix is removing the address from your list and preventing similar addresses from entering in the future.

How does MailValid detect catch-all domains?

MailValid attempts verification on a randomized address at the target domain. If the server accepts it, the domain is flagged as catch-all (is_catch_all: true).

Can I try MailValid for free?

Yes — 100 free verification credits, no credit card required. Start here →

Stop Guessing, Start Verifying

Bounce classification isn't academic — it's the difference between a healthy sender reputation and a blacklisted domain. Hard bounces, soft bounces, and catch-all traps each require different responses, but they all share one prevention strategy: verify before you send.

Get 100 free credits and classify your list risk today →

See MailValid's pricing →

Last Updated - 8 October 2026

M

MailValid Team

Email verification experts

Share:

Join teams that verify before they send

Stop letting bad emails hurt your deliverability

100 free credits. From $0.0008/email after. Credits never expire. No credit card required.

More from MailValid

Verify 100 emails free Start Free