AgentSIMOTP sessions for agents
← Blog
5 min read

Why Stripe Blocks VoIP Numbers — and What Actually Works for Agent Testing

A technical breakdown of how Stripe's carrier-lookup pipeline rejects VoIP and programmable numbers, plus an honest guide to testing phone-auth flows with AgentSIM.


If you're building AI agents that interact with phone-verification flows, you've likely seen: "This phone number cannot be used for verification." Stripe — and other strict consumer platforms — block programmable/VoIP numbers at the carrier-lookup level, before any SMS is ever sent. Here's how that pipeline works, why it matters, and what you can honestly do about it.

Why Stripe Blocks Programmable Numbers

When you submit a phone number, Stripe queries carrier databases before sending any SMS:

  1. LERG (Local Exchange Routing Guide) — Maps every North American number to its carrier and line type
  2. NPAC (Number Portability Administration Center) — Tracks numbers ported between carriers
  3. HLR (Home Location Register) — Real-time check of mobile network registration

If the lookup returns line_type: "voip" — instant rejection. The SMS is never sent.

Who Gets Blocked

ProviderLERG CarrierLine TypeStripe Result
TwilioTwilio IncvoipBlocked
Google VoiceGooglevoipBlocked
VonageVonagevoipBlocked
TextNowTextNowvoipBlocked
AgentSIMTelnyx-class CPaaSvoip / programmableMay be blocked

A Stripe security engineer confirmed the underlying logic on Hacker News:

"We reject VoIP phone numbers due to proven fraud activity. VoIP numbers can be obtained with no identity verification, recycled instantly after use, and are disproportionately associated with account takeover attempts."

The bottom line for AI agents: Stripe, Google, WhatsApp, Meta, financial institutions, and other strict consumer platforms are designed to require a real, mobile-classified number tied to a physical SIM on a consumer carrier. Programmable numbers — including AgentSIM — are the wrong tool for those flows. If your agent needs to pass Stripe consumer-account phone verification, you need a genuine mobile number outside any CPaaS provider.

What AgentSIM Is (and Is Not)

AgentSIM provisions programmable US phone numbers via API — the same class of infrastructure as Twilio or Vonage. These are not physical SIM cards and are not registered on a consumer cellular network. They are optimised for a different set of problems:

  • Auth flows you own — testing your own app's login, 2FA, or signup OTP
  • CI / QA automation — headless and parallel test suites that need a real phone number endpoint
  • Browser-agent QA — agents that drive a browser through sign-up or onboarding flows in staging
  • Verified-compatible targets — services empirically known to accept programmable numbers (see docs.agentsim.dev/supported-services)

For strict consumer platforms that enforce mobile-only classification, check the support map before assuming AgentSIM will work — it may not, and no programmable-number provider can guarantee it will.

Using AgentSIM for Flows You Own

When you control the target service — your staging environment, your own 2FA flow, a verified-compatible third-party service — AgentSIM gives agents a clean API: provision a number, wait for the OTP, parse it, release it.

Install

pip install agentsim-sdk playwright
playwright install chromium

Async OTP Session (Example: Your Own Auth Flow)

import agentsim
from playwright.async_api import async_playwright
import asyncio
 
agentsim.configure(api_key="asm_live_xxx")
 
async def test_signup_otp():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        await page.goto("https://staging.yourapp.com/signup")
 
        # Fill registration fields...
 
        # Phone verification step
        async with agentsim.provision(
            agent_id="signup-test",
            country="US"
        ) as num:
            print(f"Using: {num.number}")
 
            await page.fill('[name="phone"]', num.number)
            await page.click('button:has-text("Send code")')
 
            # Wait for the OTP to arrive
            otp = await num.wait_for_otp(timeout=120)
            print(f"OTP code: {otp.otp_code}")
 
            await page.fill('[name="code"]', otp.otp_code)
            await page.click('button:has-text("Verify")')
        # Number auto-released
 
        print("Verification complete!")
        await browser.close()
 
asyncio.run(test_signup_otp())

Synchronous Version

import agentsim
 
agentsim.configure(api_key="asm_live_xxx")
 
with agentsim.provision_sync(agent_id="ci-test-agent") as num:
    print(f"Phone: {num.number}")
    # Enter number in your target flow...
    otp = num.wait_for_otp_sync(timeout=60)
    print(f"Code: {otp.otp_code}")
    # Enter code to complete verification...
# Auto-released

With MCP (Claude Code / Cursor / Windsurf)

{
  "mcpServers": {
    "agentsim": {
      "url": "https://mcp.agentsim.dev/mcp",
      "headers": {
        "Authorization": "Bearer asm_live_xxx"
      }
    }
  }
}

Your AI coding agent calls provision_number → enters it in the target flow → calls wait_for_otp → enters the code. No SDK needed.

Understanding the Carrier Lookup Signal

When a programmable number is looked up, the result differs from a mobile number:

// Programmable/CPaaS number — may be blocked by strict platforms:
{
  "number": "+14155552671",
  "carrier": "Telnyx LLC",
  "line_type": "voip",
  "hlr_status": "unreachable"
}
 
// Mobile number on consumer carrier — required by strict platforms:
{
  "number": "+19876543210",
  "carrier": "T-Mobile USA",
  "line_type": "mobile",
  "hlr_status": "active"
}

Strict platforms like Stripe use this signal to gate delivery. No programmable-number provider can change how LERG classifies their OCN block — that classification is set at the carrier level, not by the provider.

Where AgentSIM Fits

Use CaseAgentSIMReal Mobile Number
Testing your own 2FA/OTP flowYesNot needed
CI/QA — parallel number provisioningYesImpractical
Browser-agent signup testing (staging)YesNot needed
Verified-compatible third-party servicesCheck support mapMay not be needed
Stripe consumer account signupNoRequired
Google/WhatsApp/Meta account creationNoRequired
Financial institution verificationNoRequired

Get Started