<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fathin Dosunmu</title>
    <description>The latest articles on DEV Community by Fathin Dosunmu (@fathin_dosunmu).</description>
    <link>https://dev.to/fathin_dosunmu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3841424%2F292fa61c-53e4-4f93-baae-9ef0672779c1.jpg</url>
      <title>DEV Community: Fathin Dosunmu</title>
      <link>https://dev.to/fathin_dosunmu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fathin_dosunmu"/>
    <language>en</language>
    <item>
      <title>Why Claude Code Agents Get Stuck on Phone Verification (And How to Fix It)</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Tue, 07 Apr 2026 09:35:49 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/why-claude-code-agents-get-stuck-on-phone-verification-and-how-to-fix-it-35ak</link>
      <guid>https://dev.to/fathin_dosunmu/why-claude-code-agents-get-stuck-on-phone-verification-and-how-to-fix-it-35ak</guid>
      <description>&lt;h1&gt;
  
  
  Why Claude Code Agents Get Stuck on Phone Verification (And How to Fix It)
&lt;/h1&gt;

&lt;p&gt;Claude Code is the hottest developer tool of 2026. But there is a hidden bottleneck that kills agent workflows before they even start.&lt;/p&gt;

&lt;p&gt;It is phone verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You set up Claude Code. You give it access to your repo. It starts working then hits a wall. The agent needs to sign up for an API, create a service account, or verify a webhook. Every single one asks for a phone number.&lt;/p&gt;

&lt;p&gt;You give it a VoIP number. It gets rejected.&lt;/p&gt;

&lt;p&gt;This is not a Claude Code problem. It is the fundamental infrastructure problem for every autonomous AI agent in 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI Agents Cannot Use Regular Phone Numbers
&lt;/h2&gt;

&lt;p&gt;Services use carrier lookup databases (LERG, NPAC) to check if a phone number is a real mobile line or a VoIP/virtual number. AI agents typically get assigned VoIP numbers from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Twilio virtual numbers&lt;/li&gt;
&lt;li&gt;Google Voice&lt;/li&gt;
&lt;li&gt;SMS-Activate and similar bulk providers&lt;/li&gt;
&lt;li&gt;Cloud communication platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These get flagged as non-wireless in carrier databases. When Stripe, Google, or any serious platform runs a carrier lookup, the verification fails even if the number can technically receive SMS.&lt;/p&gt;

&lt;p&gt;Real SIM cards pass carrier lookup. Virtual numbers do not. That is the entire game.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Real SIM Phone API for AI Agents
&lt;/h2&gt;

&lt;p&gt;Instead of routing through virtual numbers, give your agent a real SIM-backed phone number. The carrier lookup sees it as a legitimate mobile line because it is one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AgentSIM&lt;/span&gt;

&lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentSIM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent phone: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Verification code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent now has a phone number that passes carrier lookup on Stripe, Google, WhatsApp, and every other service that checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for Claude Code Specifically
&lt;/h2&gt;

&lt;p&gt;Claude Code is not just writing code anymore. It is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting up infrastructure (deploying to Vercel, Railway, AWS)&lt;/li&gt;
&lt;li&gt;Creating service accounts (database connections, API keys, webhooks)&lt;/li&gt;
&lt;li&gt;Managing deployments (domain verification, SSL certificates)&lt;/li&gt;
&lt;li&gt;Integrating third-party services (payment processors, notification systems)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every single one of these tasks can trigger phone verification. Your agent hits one and the entire workflow stops.&lt;/p&gt;

&lt;p&gt;A real SIM number removes the bottleneck entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Passes Carrier Lookup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio virtual&lt;/td&gt;
&lt;td&gt;$1/month&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Voice&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMS-Activate&lt;/td&gt;
&lt;td&gt;$0.10/number&lt;/td&gt;
&lt;td&gt;Sometimes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real SIM API&lt;/td&gt;
&lt;td&gt;$0.99/session&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Physical SIM plus modem&lt;/td&gt;
&lt;td&gt;$30+/month&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For an agent that needs verification occasionally, the per-session model is the sweet spot. You only pay when your agent actually needs a number.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use This
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Building autonomous agents that sign up for services&lt;/li&gt;
&lt;li&gt;Claude Code workflows that deploy infrastructure&lt;/li&gt;
&lt;li&gt;AI agents that need WhatsApp Business API access&lt;/li&gt;
&lt;li&gt;Any agent hitting phone number rejected errors&lt;/li&gt;
&lt;li&gt;Testing verification flows without burning real numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;AgentSIM provides real SIM phone numbers as an API built specifically for AI agent workflows. It is MCP-native, so it integrates directly with Claude Code, Cursor, and any agent framework.&lt;/p&gt;

&lt;p&gt;10 free sessions per month. After that, $0.99/session.&lt;/p&gt;

&lt;p&gt;AgentSIM: &lt;a href="https://agentsim.dev" rel="noopener noreferrer"&gt;https://agentsim.dev&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Built this because my own agents kept hitting phone verification walls. If you are running autonomous agents in 2026, you will hit this too. Might as well solve it once.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Built an Autonomous Phone Verification Agent (Full Code + Tutorial)</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Mon, 06 Apr 2026 22:28:52 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/i-built-an-autonomous-phone-verification-agent-full-code-tutorial-2374</link>
      <guid>https://dev.to/fathin_dosunmu/i-built-an-autonomous-phone-verification-agent-full-code-tutorial-2374</guid>
      <description>&lt;p&gt;You built an AI agent that can browse the web, fill forms, and make decisions. But it hits a wall every single time:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"This phone number cannot be used for verification."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Stripe. WhatsApp. Google. All of them run a carrier lookup. All of them block VoIP. And every cloud phone API returns &lt;code&gt;line_type: VoIP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your agent is stuck. Not because it's dumb. Because the infrastructure is wrong.&lt;/p&gt;

&lt;p&gt;Today I'll show you how to fix it. Full code. Real results.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem in 30 Seconds
&lt;/h2&gt;

&lt;p&gt;When Stripe receives a phone number, it doesn't just send an SMS. First, it queries the LERG/NPAC databases to check: &lt;strong&gt;what type of number is this?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://lookups.twilio.com/v2/PhoneNumbers/+16505550001
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"line_type_intelligence"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"type"&lt;/span&gt;: &lt;span class="s2"&gt;"voip"&lt;/span&gt;,
    &lt;span class="s2"&gt;"carrier"&lt;/span&gt;: &lt;span class="s2"&gt;"Twilio Inc."&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;strong&gt;REJECTED&lt;/strong&gt;. Stripe blocks VoIP numbers for verification. Always.&lt;/p&gt;

&lt;p&gt;The same check happens at Google, WhatsApp, Telegram, banks. If your agent uses a cloud phone number, it will fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Real SIM Infrastructure
&lt;/h2&gt;

&lt;p&gt;The solution isn't a hack. It's the right infrastructure. AgentSIM provisions numbers on &lt;strong&gt;real physical SIM cards&lt;/strong&gt; through Telnyx. Carrier lookup returns &lt;code&gt;line_type: mobile&lt;/code&gt; -- exactly what Stripe, Google, and WhatsApp expect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+14155551234&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;carrier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T-Mobile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line_type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mobile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building the Agent
&lt;/h2&gt;

&lt;p&gt;Here's the complete code. Three steps. ~3.5 seconds end to end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentsim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Provision a Number
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AgentSIM&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;agentsim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentSIM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capabilities&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Carrier: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;carrier&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Number: +14155551234
&lt;/span&gt;    &lt;span class="c1"&gt;# Carrier: T-Mobile
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Wait for OTP
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OTP: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Service: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# OTP: 847291
&lt;/span&gt;    &lt;span class="c1"&gt;# Service: stripe
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. The OTP is parsed automatically -- code extracted, service detected, structured JSON returned. No regex. No human reading SMS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Autonomous Flow with Playwright
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;async_playwright&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_on_stripe&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;async_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://connect.stripe.com/setup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input[name=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;phone&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;button[type=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;submit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input[name=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;button[type=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;submit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Phone verified&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real Performance Numbers
&lt;/h2&gt;

&lt;p&gt;This isn't theoretical. Here's what's running in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Provision time:&lt;/strong&gt; 212ms average&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OTP delivery:&lt;/strong&gt; 3.5s average&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $0.99 per session (provision + OTP + release)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compare to alternatives:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Carrier Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;$1.15/number + usage&lt;/td&gt;
&lt;td&gt;line_type: VoIP (blocked)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JoltSMS&lt;/td&gt;
&lt;td&gt;$50/number/month&lt;/td&gt;
&lt;td&gt;line_type: mobile (works)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared virtual&lt;/td&gt;
&lt;td&gt;$0.30-2/number&lt;/td&gt;
&lt;td&gt;line_type: VoIP (blocked)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AgentSIM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.99/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;line_type: mobile (works)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At 100 verifications/month: JoltSMS costs $5,000. AgentSIM costs $99. &lt;strong&gt;50x cheaper.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for AI Agents
&lt;/h2&gt;

&lt;p&gt;AI agents are autonomous by design. They browse, decide, and act. But if every action that requires phone verification needs a human to read an SMS, your agent isn't autonomous -- it's a puppet.&lt;/p&gt;

&lt;p&gt;Real SIM infrastructure removes the last human bottleneck. Your agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and verify Stripe Connect accounts&lt;/li&gt;
&lt;li&gt;Set up WhatsApp Business API&lt;/li&gt;
&lt;li&gt;Verify Google accounts for service access&lt;/li&gt;
&lt;li&gt;Register on any platform requiring SMS verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without human involvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP Native
&lt;/h2&gt;

&lt;p&gt;If you're building with Claude Code, Cursor, or Windsurf -- AgentSIM has a built-in MCP server. One command to add it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add agentsim &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @agentsim/mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your agent can provision numbers through natural language: "I need a US phone number to verify a Stripe account"&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Free
&lt;/h2&gt;

&lt;p&gt;AgentSIM gives you &lt;strong&gt;10 free sessions per month&lt;/strong&gt; -- no credit card, no commitment. If the OTP doesn't arrive, you're not charged.&lt;/p&gt;

&lt;p&gt;Get started at &lt;a href="https://agentsim.dev/sign-up" rel="noopener noreferrer"&gt;agentsim.dev/sign-up&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One session = one number, one OTP, one verification. Your agent does the rest.&lt;/p&gt;




&lt;p&gt;Open source at &lt;a href="https://github.com/agentsimdev/agentsim" rel="noopener noreferrer"&gt;github.com/agentsimdev/agentsim&lt;/a&gt;. Docs at &lt;a href="https://docs.agentsim.dev" rel="noopener noreferrer"&gt;docs.agentsim.dev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Complete Guide to Phone Verification for AI Agents in 2026</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Sun, 29 Mar 2026 20:23:26 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/the-complete-guide-to-phone-verification-for-ai-agents-in-2026-3j7</link>
      <guid>https://dev.to/fathin_dosunmu/the-complete-guide-to-phone-verification-for-ai-agents-in-2026-3j7</guid>
      <description>&lt;p&gt;This is the definitive reference for phone verification in the AI agent ecosystem. Whether you're building browser automation, account creation workflows, or multi-service onboarding — this guide covers every approach, what works, what doesn't, and why.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verification Landscape in 2026
&lt;/h2&gt;

&lt;p&gt;Phone verification is now the primary gatekeeper for online services. As AI agents become more capable, the verification infrastructure has evolved to detect and block automated signups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Services That Block VoIP Numbers
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Block Severity&lt;/th&gt;
&lt;th&gt;Error Message&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stripe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block&lt;/td&gt;
&lt;td&gt;"This phone number cannot be used for verification"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block + behavioral&lt;/td&gt;
&lt;td&gt;"This number cannot be used"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WhatsApp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block&lt;/td&gt;
&lt;td&gt;"Unsupported phone numbers, such as VoIP"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent failure&lt;/td&gt;
&lt;td&gt;Code never arrives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Risk-based&lt;/td&gt;
&lt;td&gt;Error 399287 "BadReputation"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vercel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block&lt;/td&gt;
&lt;td&gt;Registration rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DocuSign&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block&lt;/td&gt;
&lt;td&gt;Registration rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Banks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Detection Stack
&lt;/h3&gt;

&lt;p&gt;Every major service uses some combination of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;LERG lookup&lt;/strong&gt; — Checks carrier and line type from the master phone database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPAC query&lt;/strong&gt; — Checks if the number was ported from mobile to VoIP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HLR query&lt;/strong&gt; — Real-time check of mobile network registration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavioral analysis&lt;/strong&gt; — Pattern detection (creation velocity, geographic consistency)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reputation scoring&lt;/strong&gt; — Number history, abuse reports, fraud databases&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Every Approach Ranked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Twilio / Vonage / VoIP Providers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $1-15/month per number&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success rate:&lt;/strong&gt; 0% on Stripe, Google, WhatsApp, banks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it fails:&lt;/strong&gt; Numbers registered as &lt;code&gt;voip&lt;/code&gt; in LERG. Every service blocks them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use:&lt;/strong&gt; Voice bots, customer support, non-verification use cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Google Voice / TextNow / Free Services
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; Free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success rate:&lt;/strong&gt; 0% on most services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it fails:&lt;/strong&gt; Same VoIP detection. Plus, automating these violates ToS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use:&lt;/strong&gt; Never for production AI agents&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Prepaid SIM Cards (Manual)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $3-10 per SIM + manual labor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success rate:&lt;/strong&gt; ~90% (some services block prepaid)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it's problematic:&lt;/strong&gt; Doesn't scale. Requires physical SIM management, manual number rotation, and someone physically handling the phones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use:&lt;/strong&gt; One-off testing, not production automation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ AgentSIM (Real SIM API)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $0.99/session, 10 free/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success rate:&lt;/strong&gt; 98-100% across all services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it works:&lt;/strong&gt; Real SIM cards on real carrier networks (T-Mobile, AT&amp;amp;T, Verizon). Numbers pass LERG, NPAC, and HLR checks because they ARE mobile numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use:&lt;/strong&gt; Production AI agent verification at any scale&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentsim-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern 1: Basic OTP Verification
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signup-bot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# num.number is a real E.164 mobile number
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Phone: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# +14155552671
&lt;/span&gt;
    &lt;span class="c1"&gt;# Enter number on whatever service needs verification
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;enter_phone_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Wait for OTP — real SMS on real SIM
&lt;/span&gt;    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# "391847"
&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;enter_verification_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Number auto-released when context exits
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern 2: With Browser Automation (Playwright)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;async_playwright&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;automated_signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service_url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;async_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;browser-signup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Fill phone field
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[type=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button:has-text(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Get OTP from real SIM
&lt;/span&gt;            &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Enter code
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[name=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button:has-text(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern 3: Synchronous (Non-Async)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sync-bot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;enter_phone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;enter_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern 4: MCP Integration (Claude Code / Cursor / Windsurf)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentsim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.agentsim.dev/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer asm_live_xxx"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your AI agent calls &lt;code&gt;provision_number&lt;/code&gt; and &lt;code&gt;wait_for_otp&lt;/code&gt; as MCP tools — no SDK installation needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 5: Auto-Rerouting (Fallback Countries)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;global-bot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;auto_reroute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# Try another country if US fails
&lt;/span&gt;        &lt;span class="n"&gt;max_reroutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;on_reregistration_needed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;handle_new_number&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentsim.exceptions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OtpTimeoutError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PoolExhaustedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;RateLimitError&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;OtpTimeoutError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SMS didn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t arrive in 60s — service may have blocked this number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;PoolExhaustedError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No numbers available — try a different country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Too many requests — back off and retry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cost Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Setup cost&lt;/th&gt;
&lt;th&gt;Per-verification cost&lt;/th&gt;
&lt;th&gt;Stripe&lt;/th&gt;
&lt;th&gt;Google&lt;/th&gt;
&lt;th&gt;WhatsApp&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$1.15/number + SMS&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Voice&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepaid SIM&lt;/td&gt;
&lt;td&gt;$5-10/SIM&lt;/td&gt;
&lt;td&gt;Manual labor&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AgentSIM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.99/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Free tier: 10 sessions/month. No subscription required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rate limit aggressively&lt;/strong&gt; — Most bans come from velocity, not carrier detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use realistic browser fingerprints&lt;/strong&gt; — Headless detection is separate from phone verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotate IPs&lt;/strong&gt; — Don't create multiple accounts from the same IP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warm up accounts&lt;/strong&gt; — Login and use accounts normally after creation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle failures gracefully&lt;/strong&gt; — Use try/except with AgentSIM's typed exceptions&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AgentSIM:&lt;/strong&gt; &lt;a href="https://agentsim.dev" rel="noopener noreferrer"&gt;agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.agentsim.dev" rel="noopener noreferrer"&gt;docs.agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python SDK:&lt;/strong&gt; &lt;a href="https://pypi.org/project/agentsim-sdk/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Server:&lt;/strong&gt; &lt;a href="https://smithery.ai/servers/agentsim/agentsim" rel="noopener noreferrer"&gt;Smithery&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/agentsimdev" rel="noopener noreferrer"&gt;github.com/agentsimdev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples:&lt;/strong&gt; &lt;a href="https://github.com/agentsimdev/agentsim-examples" rel="noopener noreferrer"&gt;github.com/agentsimdev/agentsim-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>tutorial</category>
      <category>automation</category>
    </item>
    <item>
      <title>VoIP vs Real SIM: Why Your AI Agent Phone Number Gets Blocked</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Sun, 29 Mar 2026 20:23:14 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/voip-vs-real-sim-why-your-ai-agent-phone-number-gets-blocked-1khg</link>
      <guid>https://dev.to/fathin_dosunmu/voip-vs-real-sim-why-your-ai-agent-phone-number-gets-blocked-1khg</guid>
      <description>&lt;p&gt;Every week, a developer posts on Stack Overflow or Reddit: "My Twilio number gets rejected at Stripe/Google/WhatsApp." The answer is always the same — VoIP numbers fail carrier lookup. But &lt;em&gt;why&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;This is the deep technical explanation of how carrier detection works, what databases are involved, and why real SIM is the only reliable solution for AI agent verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Carrier Lookup Infrastructure
&lt;/h2&gt;

&lt;p&gt;When a service like Stripe verifies your phone number, it doesn't just check a blocklist. It queries a chain of authoritative databases:&lt;/p&gt;

&lt;h3&gt;
  
  
  LERG (Local Exchange Routing Guide)
&lt;/h3&gt;

&lt;p&gt;The LERG is the master database of North American phone numbers. Maintained by iconectiv (formerly Telcordia), it maps every NPA-NXX (area code + exchange) to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operating Company Number (OCN)&lt;/strong&gt; — Who owns this number block&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line type&lt;/strong&gt; — Mobile, landline, VoIP, toll-free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate center&lt;/strong&gt; — Geographic location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LATA&lt;/strong&gt; — Local Access and Transport Area&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Twilio buys a block of numbers from Bandwidth, those numbers are registered in LERG under Bandwidth's OCN with line_type &lt;code&gt;voip&lt;/code&gt;. This is permanent and public.&lt;/p&gt;

&lt;h3&gt;
  
  
  NPAC (Number Portability Administration Center)
&lt;/h3&gt;

&lt;p&gt;NPAC tracks ported numbers. If a number was originally Verizon mobile but got ported to Twilio, NPAC records this. Services that do deep verification check NPAC to see if a mobile number was ported to a VoIP provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  HLR (Home Location Register)
&lt;/h3&gt;

&lt;p&gt;The HLR is the real-time database on each carrier's network. When you query a T-Mobile number via HLR, it returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether the number is currently registered on the network&lt;/li&gt;
&lt;li&gt;The IMSI (International Mobile Subscriber Identity)&lt;/li&gt;
&lt;li&gt;The serving MSC (Mobile Switching Center)&lt;/li&gt;
&lt;li&gt;Roaming status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VoIP numbers don't exist in any HLR — they route through internet gateways, not cell towers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Services Use This Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stripe's Approach
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Receive phone number
2. Query LERG → Get OCN and line_type
3. If line_type = "voip" → REJECT
4. If line_type = "mobile" → Query HLR for active registration
5. If HLR active → SEND SMS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Google's Approach (More Aggressive)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Receive phone number
2. Query LERG → Get carrier and line_type
3. If line_type = "voip" → REJECT
4. If carrier is known VoIP provider (even if line_type is ambiguous) → REJECT
5. Query HLR → Check active mobile registration
6. Check behavioral patterns (creation velocity, geo-consistency)
7. If all checks pass → SEND SMS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WhatsApp's Approach (Strictest)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Receive phone number
2. Query LERG + NPAC for current carrier
3. Check against WhatsApp's internal VoIP blocklist
4. Query HLR for active mobile registration
5. Check number history (spam reports, previous bans)
6. If all checks pass → SEND SMS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why VoIP Numbers Are Detectable
&lt;/h2&gt;

&lt;p&gt;It's not just about databases. VoIP numbers have fundamental technical differences:&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Topology
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mobile:&lt;/strong&gt; Phone → Cell tower → MSC → SMS Center → Delivery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VoIP:&lt;/strong&gt; API call → Internet → SIP gateway → SMS aggregator → Delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The routing path is different. Services can detect SIP gateways in the delivery chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Number Allocation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mobile carriers&lt;/strong&gt; get number blocks directly from regulators&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VoIP providers&lt;/strong&gt; lease from wholesale carriers (Bandwidth, Peerless)&lt;/li&gt;
&lt;li&gt;LERG records who owns each block — this is public information&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Registration Status
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mobile:&lt;/strong&gt; Continuously registered with a cell tower via SIM card&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VoIP:&lt;/strong&gt; No network registration. Numbers exist only in software databases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real SIM vs VoIP: Technical Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Characteristic&lt;/th&gt;
&lt;th&gt;VoIP Number&lt;/th&gt;
&lt;th&gt;Real SIM Number&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LERG line_type&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;voip&lt;/code&gt; or &lt;code&gt;nonFixedVoip&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mobile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLR registration&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;✅ Active on tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carrier in LERG&lt;/td&gt;
&lt;td&gt;Twilio/Bandwidth/Vonage&lt;/td&gt;
&lt;td&gt;T-Mobile/AT&amp;amp;T/Verizon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Physical SIM card&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cell tower connection&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IMSI on network&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMS routing&lt;/td&gt;
&lt;td&gt;Internet → SIP gateway&lt;/td&gt;
&lt;td&gt;Carrier SMS Center&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stripe verification&lt;/td&gt;
&lt;td&gt;❌ 0% success&lt;/td&gt;
&lt;td&gt;✅ 100% success&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google verification&lt;/td&gt;
&lt;td&gt;❌ 0% success&lt;/td&gt;
&lt;td&gt;✅ 98% success&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WhatsApp verification&lt;/td&gt;
&lt;td&gt;❌ 0% success&lt;/td&gt;
&lt;td&gt;✅ 100% success&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  AgentSIM: Real SIM for AI Agents
&lt;/h2&gt;

&lt;p&gt;AgentSIM bridges the gap. It provisions actual SIM cards on carrier networks and exposes them via API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# +14155552671 (real T-Mobile number)
&lt;/span&gt;
    &lt;span class="c1"&gt;# This number passes LERG, NPAC, and HLR checks
&lt;/span&gt;    &lt;span class="c1"&gt;# because it IS a real mobile number
&lt;/span&gt;
    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# "391847"
# Auto-released
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MCP Integration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentsim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.agentsim.dev/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer asm_live_xxx"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;VoIP detection isn't going away. It's getting more sophisticated as fraud scales. The only reliable solution for AI agents that need phone verification is real SIM-backed numbers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;code&gt;pip install agentsim-sdk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://agentsim.dev" rel="noopener noreferrer"&gt;agentsim.dev&lt;/a&gt; — 10 free sessions/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.agentsim.dev" rel="noopener noreferrer"&gt;docs.agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/agentsimdev" rel="noopener noreferrer"&gt;github.com/agentsimdev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Fix: WhatsApp 'Unsupported phone numbers such as VoIP' for AI Agents</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Sun, 29 Mar 2026 20:22:06 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/fix-whatsapp-unsupported-phone-numbers-such-as-voip-for-ai-agents-3k6f</link>
      <guid>https://dev.to/fathin_dosunmu/fix-whatsapp-unsupported-phone-numbers-such-as-voip-for-ai-agents-3k6f</guid>
      <description>&lt;p&gt;If you're building AI agents that need WhatsApp Business API access, you've seen this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unsupported phone numbers, such as VoIP, landlines, and premium rate numbers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WhatsApp has the strictest phone verification in the industry. Here's why, and how to solve it.&lt;/p&gt;




&lt;h2&gt;
  
  
  WhatsApp's Verification Requirements
&lt;/h2&gt;

&lt;p&gt;WhatsApp's official FAQ is explicit:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Unsupported phone numbers, such as VoIP, landlines, and premium rate numbers, are not eligible for registration."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unlike Stripe or Google which silently reject, WhatsApp tells you exactly why. Their system performs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Carrier database lookup&lt;/strong&gt; — Checks LERG/NPAC for line type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HLR query&lt;/strong&gt; — Verifies active mobile network registration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical abuse check&lt;/strong&gt; — Numbers previously used for spam are permanently blocked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Country-carrier validation&lt;/strong&gt; — Number must be from a carrier operating in the declared country&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why WhatsApp Is Stricter
&lt;/h3&gt;

&lt;p&gt;WhatsApp is the primary communication platform in 180+ countries. They block VoIP because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spam prevention:&lt;/strong&gt; VoIP numbers are 40x more likely to be used for bulk spam&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity verification:&lt;/strong&gt; Each WhatsApp account = one real person/business&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carrier agreements:&lt;/strong&gt; Meta has direct relationships with mobile carriers worldwide&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Every VoIP Provider Fails
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;WhatsApp result&lt;/th&gt;
&lt;th&gt;Error message&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;td&gt;"Unsupported phone number"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vonage&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;td&gt;"Unsupported phone number"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Voice&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;td&gt;"Unsupported phone number"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bandwidth&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;td&gt;"Unsupported phone number"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AgentSIM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅ Passes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Registration successful&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Fix: AgentSIM for WhatsApp
&lt;/h2&gt;

&lt;p&gt;AgentSIM numbers pass WhatsApp verification because they're real SIM cards on real mobile networks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentsim-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WhatsApp Business API Registration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_whatsapp_business&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whatsapp-setup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Registering WhatsApp with: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Use the number in WhatsApp Business API registration
&lt;/span&gt;        &lt;span class="c1"&gt;# via Meta's Cloud API or on-premise API
&lt;/span&gt;        &lt;span class="n"&gt;registration_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;register_with_meta_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# or "voice"
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Wait for verification code
&lt;/span&gt;        &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WhatsApp code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Complete verification
&lt;/span&gt;        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;verify_with_meta_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WhatsApp Business registered!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Number auto-released after context exit
&lt;/span&gt;
&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;register_whatsapp_business&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  With Playwright (Web Registration)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;async_playwright&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_whatsapp_web&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;async_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://business.facebook.com/wa/manage/phone-numbers/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whatsapp-reg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[name=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button:has-text(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[name=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button:has-text(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  With MCP (Claude Code / Cursor)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentsim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.agentsim.dev/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer asm_live_xxx"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Carrier Verification Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;VoIP Number&lt;/th&gt;
&lt;th&gt;AgentSIM Number&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LERG line_type&lt;/td&gt;
&lt;td&gt;&lt;code&gt;voip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mobile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carrier name&lt;/td&gt;
&lt;td&gt;Twilio Inc&lt;/td&gt;
&lt;td&gt;T-Mobile USA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLR status&lt;/td&gt;
&lt;td&gt;No mobile registration&lt;/td&gt;
&lt;td&gt;Active on network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WhatsApp eligible&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Important Notes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;One number per WhatsApp account&lt;/strong&gt; — WhatsApp enforces 1:1 mapping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Number history matters&lt;/strong&gt; — Previously-banned numbers may still be blocked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business verification separate&lt;/strong&gt; — Phone verification is step 1; Meta business verification is step 2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the number active&lt;/strong&gt; — WhatsApp may re-verify periodically&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Monthly cost&lt;/th&gt;
&lt;th&gt;WhatsApp success rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;$1-15/number&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Voice&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AgentSIM&lt;/td&gt;
&lt;td&gt;$0.99/session&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://agentsim.dev" rel="noopener noreferrer"&gt;agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.agentsim.dev" rel="noopener noreferrer"&gt;docs.agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/agentsimdev" rel="noopener noreferrer"&gt;github.com/agentsimdev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;10 free sessions per month. Real SIM numbers that pass WhatsApp's strict verification.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>whatsapp</category>
      <category>automation</category>
    </item>
    <item>
      <title>Fix: Stripe 'This phone number cannot be used for verification' with AI Agents</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Sun, 29 Mar 2026 20:03:50 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/fix-stripe-this-phone-number-cannot-be-used-for-verification-with-ai-agents-3249</link>
      <guid>https://dev.to/fathin_dosunmu/fix-stripe-this-phone-number-cannot-be-used-for-verification-with-ai-agents-3249</guid>
      <description>&lt;p&gt;If you're building AI agents that need to create Stripe accounts, you've hit this wall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This phone number cannot be used for verification.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your agent fills out the form perfectly, reaches phone verification, and — rejected. This guide explains exactly what's happening and how to solve it with real SIM-backed numbers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Stripe Blocks Your Number
&lt;/h2&gt;

&lt;p&gt;Stripe performs carrier lookups against multiple databases before sending any verification SMS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;LERG (Local Exchange Routing Guide)&lt;/strong&gt; — The authoritative database of North American phone numbers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPAC (Number Portability Administration Center)&lt;/strong&gt; — Tracks number porting between carriers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time HLR queries&lt;/strong&gt; — Verify active network registration on the carrier side&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your number comes back as &lt;code&gt;voip&lt;/code&gt; or &lt;code&gt;nonFixedVoip&lt;/code&gt;, it's rejected immediately. The code is never sent.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;line_type returned&lt;/th&gt;
&lt;th&gt;Stripe result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;&lt;code&gt;voip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Voice&lt;/td&gt;
&lt;td&gt;&lt;code&gt;voip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vonage&lt;/td&gt;
&lt;td&gt;&lt;code&gt;voip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TextNow&lt;/td&gt;
&lt;td&gt;&lt;code&gt;voip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ Blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AgentSIM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;mobile&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅ Passes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Twilio/VoIP Numbers Fail
&lt;/h2&gt;

&lt;p&gt;Every VoIP provider's number ranges are catalogued in LERG. When Stripe queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+19875551234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"carrier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Twilio Inc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"line_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"voip"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instant rejection. This isn't a bug — it's by design. Financial services block VoIP to prevent synthetic identity fraud.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Real SIM Numbers via AgentSIM
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://agentsim.dev" rel="noopener noreferrer"&gt;AgentSIM&lt;/a&gt; provisions actual SIM-backed phone numbers from carriers like T-Mobile. These return &lt;code&gt;mobile&lt;/code&gt; in carrier lookups because they ARE mobile numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentsim-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe-setup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# num.number is a real mobile number (E.164 format)
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Using: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# +14155552671
&lt;/span&gt;
    &lt;span class="c1"&gt;# Enter the number in Stripe verification form
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;enter_phone_on_stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Wait for the OTP to arrive via real SMS
&lt;/span&gt;    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 391847
&lt;/span&gt;
    &lt;span class="c1"&gt;# Enter the code — verification passes
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;enter_code_on_stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Number auto-released when context exits
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  With Playwright (Full Automation)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;async_playwright&lt;/span&gt;

&lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asm_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_stripe_account&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;async_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dashboard.stripe.com/register&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[name=email]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent@company.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe-setup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[name=phone]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;button:has-text(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Send code&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[name=code]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;button:has-text(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Verify&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  With MCP (Claude Code / Cursor / Windsurf)
&lt;/h3&gt;

&lt;p&gt;If you're using an AI coding agent, AgentSIM has a native MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentsim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.agentsim.dev/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer asm_live_xxx"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then your agent can call &lt;code&gt;provision_number&lt;/code&gt; and &lt;code&gt;wait_for_otp&lt;/code&gt; as MCP tools directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AgentSIM Numbers Pass
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;VoIP Number&lt;/th&gt;
&lt;th&gt;AgentSIM Number&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LERG lookup&lt;/td&gt;
&lt;td&gt;&lt;code&gt;voip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mobile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carrier name&lt;/td&gt;
&lt;td&gt;Twilio Inc&lt;/td&gt;
&lt;td&gt;T-Mobile USA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLR query&lt;/td&gt;
&lt;td&gt;No network reg&lt;/td&gt;
&lt;td&gt;Active on tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fraud score&lt;/td&gt;
&lt;td&gt;High (70-90)&lt;/td&gt;
&lt;td&gt;Clean (0-10)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;AgentSIM uses real SIM cards on real carrier networks. The numbers aren't spoofed or masked — they're genuine mobile numbers that pass every verification check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Monthly cost&lt;/th&gt;
&lt;th&gt;Stripe success rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;$1-15/number&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Voice&lt;/td&gt;
&lt;td&gt;Free (ToS risk)&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AgentSIM&lt;/td&gt;
&lt;td&gt;$0.99/session&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;10 free sessions per month. No subscription required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://agentsim.dev" rel="noopener noreferrer"&gt;agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.agentsim.dev" rel="noopener noreferrer"&gt;docs.agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Server:&lt;/strong&gt; &lt;a href="https://smithery.ai/servers/agentsim/agentsim" rel="noopener noreferrer"&gt;Smithery&lt;/a&gt; · &lt;a href="https://npmjs.com/package/@agentsim/mcp" rel="noopener noreferrer"&gt;npm&lt;/a&gt; · &lt;a href="https://pypi.org/project/agentsim-mcp/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/agentsimdev" rel="noopener noreferrer"&gt;github.com/agentsimdev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stop fighting VoIP detection. Use real mobile numbers that work.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>stripe</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why Your AI Agent's Phone Number Gets Blocked (And How to Fix It)</title>
      <dc:creator>Fathin Dosunmu</dc:creator>
      <pubDate>Tue, 24 Mar 2026 13:46:06 +0000</pubDate>
      <link>https://dev.to/fathin_dosunmu/why-your-ai-agents-phone-number-gets-blocked-and-how-to-fix-it-48k5</link>
      <guid>https://dev.to/fathin_dosunmu/why-your-ai-agents-phone-number-gets-blocked-and-how-to-fix-it-48k5</guid>
      <description>&lt;p&gt;You built an AI agent that onboards to a new service, creates an account, fills in a form, and gets all the way to SMS verification — then hits a wall.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"This phone number cannot be used for verification."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or worse: the code is never sent and no error appears at all. Your agent just sits there waiting.&lt;/p&gt;

&lt;p&gt;This is the VoIP blocking problem. It affects every AI agent that needs a real phone identity, and it's getting worse as fraud rates on virtual numbers rise. This guide explains exactly what's happening, why every major service blocks VoIP numbers, and what the working alternatives are.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: VoIP Numbers Fail Production Verification
&lt;/h2&gt;

&lt;p&gt;Most developers building phone-capable AI agents reach for the obvious choices: Google Voice, TextNow, Twilio programmable numbers, Telnyx, or Vonage. These are cheap, API-accessible, and work fine in development. They fail in production.&lt;/p&gt;

&lt;p&gt;The services your agent needs to verify with — Stripe, Google, Amazon, WhatsApp, Microsoft, financial institutions — all run carrier lookup checks before sending verification codes. If the lookup returns &lt;code&gt;nonFixedVoip&lt;/code&gt; or &lt;code&gt;fixedVoip&lt;/code&gt;, the request is rejected. The code is never sent.&lt;/p&gt;

&lt;p&gt;Here's the list of confirmed blockers, with the evidence:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Block Type&lt;/th&gt;
&lt;th&gt;User-Facing Message&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stripe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard error&lt;/td&gt;
&lt;td&gt;"This phone number cannot be used for verification"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent or vague&lt;/td&gt;
&lt;td&gt;"Something went wrong" / "This number cannot be used"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent delivery failure&lt;/td&gt;
&lt;td&gt;Code simply never arrives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WhatsApp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard error&lt;/td&gt;
&lt;td&gt;"Unsupported phone numbers, such as VoIP, landlines..."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft Entra ID&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Risk-based block&lt;/td&gt;
&lt;td&gt;Error 399287 "BadReputation"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vercel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block at signup&lt;/td&gt;
&lt;td&gt;Registration rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DocuSign&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard block at signup&lt;/td&gt;
&lt;td&gt;Registration rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Banks (BMO and others)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent or misleading&lt;/td&gt;
&lt;td&gt;Codes not delivered, vague errors&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These aren't edge cases. They're deliberate product decisions backed by fraud data, and the blocking is accelerating.&lt;/p&gt;

&lt;p&gt;A fintech security professional on Hacker News described Stripe's logic directly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"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."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;WhatsApp's official FAQ states it explicitly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Unsupported phone numbers, such as VoIP, landlines, and premium rate numbers, are not eligible for registration."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Microsoft's documentation lists VoIP support status plainly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Phone extensions and VOIP numbers are not supported for MFA."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For AI agent developers, this creates a hard requirement: your agent needs a number that carrier lookup APIs classify as &lt;code&gt;mobile&lt;/code&gt;, not &lt;code&gt;voip&lt;/code&gt;. Understanding how that classification works is the first step to solving it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Carrier Lookup Works: The Technical Infrastructure
&lt;/h2&gt;

&lt;p&gt;When Stripe, Google, or WhatsApp receives a phone number for verification, they don't just check a blocklist. They query a carrier lookup API that interrogates multiple interconnected telecom databases. Here's how the chain works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Parse NPA-NXX
&lt;/h3&gt;

&lt;p&gt;Every US phone number in E.164 format starts with the country code (+1), followed by a 10-digit number. The first 6 digits — the NPA (Numbering Plan Area, aka area code) and NXX (exchange code, aka the first 3 of the 7-digit local number) — form the lookup key.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;+14155551234&lt;/code&gt;: NPA = 415, NXX = 555.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Query the LERG
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Local Exchange Routing Guide (LERG)&lt;/strong&gt; is a database published by iconectiv, the FCC-designated North American Numbering Plan Administrator. It maps every NPA-NXX block to an &lt;strong&gt;Operating Company Number (OCN)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The LERG contains multiple tables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LERG1&lt;/strong&gt; — OCN information including carrier name, type, and state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LERG6&lt;/strong&gt; — NPA NXX assignments (which carrier owns which blocks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LERG7&lt;/strong&gt; — Switch data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LERG12&lt;/strong&gt; — LRN (Location Routing Number) assignments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The OCN lookup tells you which carrier was originally assigned the number block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Check NPAC for Porting
&lt;/h3&gt;

&lt;p&gt;Number portability changed everything. Under FCC LNP (Local Number Portability) rules, any US number can be ported from one carrier to another. The &lt;strong&gt;Number Portability Administration Center (NPAC)&lt;/strong&gt;, also operated by iconectiv, records every porting event.&lt;/p&gt;

&lt;p&gt;When a number is ported, NPAC stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current &lt;strong&gt;SPID&lt;/strong&gt; (Service Provider ID)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;LRN&lt;/strong&gt; (Location Routing Number) for routing&lt;/li&gt;
&lt;li&gt;The porting date and history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The SPID is critical: it encodes the line type directly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SPID Carrier Type&lt;/th&gt;
&lt;th&gt;Line Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Type 0&lt;/td&gt;
&lt;td&gt;Wireline (ILEC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type 1&lt;/td&gt;
&lt;td&gt;Wireline (CLEC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type 2&lt;/td&gt;
&lt;td&gt;Wireless / Mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type 3&lt;/td&gt;
&lt;td&gt;VoIP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If NPAC shows a porting event and the current SPID has carrier type 3, the number is VoIP — even if the original LERG assignment was to a mobile carrier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Look Up OCN Type
&lt;/h3&gt;

&lt;p&gt;Each OCN has a carrier type classification assigned by the FCC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ILEC&lt;/strong&gt; — Incumbent Local Exchange Carrier (traditional landline providers: AT&amp;amp;T, Verizon wireline)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLEC&lt;/strong&gt; — Competitive Local Exchange Carrier (alternative wireline providers)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WIRELESS&lt;/strong&gt; — Mobile Network Operators (AT&amp;amp;T Mobility, T-Mobile, Verizon Wireless)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VOIP&lt;/strong&gt; — Voice over IP providers (Google Voice, Twilio, Bandwidth, Lingo)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CABLE&lt;/strong&gt; — Cable companies offering phone service (Comcast Xfinity, Cox)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Classify and Return
&lt;/h3&gt;

&lt;p&gt;The carrier lookup API combines the LERG OCN type and the NPAC porting data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if current_spid_type == 3 → VoIP (ported to VoIP)
else if ocn_type == WIRELESS → mobile
else if ocn_type == VOIP → VoIP (never ported)
else if ocn_type == ILEC/CLEC/CABLE → landline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result propagates into two major sub-categories for VoIP:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fixedVoip&lt;/strong&gt; — VoIP numbers tied to a specific physical location or device. Examples: Comcast Business Voice, enterprise PBX systems, some CLEC offerings. These require a physical installation at a premises address. They're considered more legitimate and some services allow them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nonFixedVoip&lt;/strong&gt; — VoIP numbers that can be obtained online with no physical address or device requirement. Examples: Google Voice, TextNow, Vonage, Twilio programmable numbers, Telnyx numbers. These can be created with a credit card, no identity verification, and cancelled instantly. This is the category most aggressively blocked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Signals
&lt;/h3&gt;

&lt;p&gt;Beyond the core LERG/NPAC/OCN chain, carrier lookup APIs may also query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HLR (Home Location Register)&lt;/strong&gt; — Mobile carrier subscriber databases. A failed HLR lookup for a supposedly mobile number is a strong VoIP indicator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CNAM databases&lt;/strong&gt; — Caller Name databases. VoIP numbers frequently show unusual or generic names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ANI/SS7 Information Digits&lt;/strong&gt; — In real-time call signaling, Information Digits classify the call origin. VoIP calls carry digit codes that differ from mobile calls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proprietary fraud databases&lt;/strong&gt; — IPQS, Telesign, and others maintain additional lists of numbers with fraud history.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Carrier Lookup API Ecosystem
&lt;/h2&gt;

&lt;p&gt;There are eight major APIs developers use to perform carrier lookup. Understanding their differences helps you predict how the services your agent needs to verify with are classifying your numbers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;th&gt;Line Type Field&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Twilio Lookup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;$0.008/req ($0.00385 volume)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;line_type_intelligence.type&lt;/code&gt;: &lt;code&gt;landline&lt;/code&gt;, &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;fixedVoip&lt;/code&gt;, &lt;code&gt;nonFixedVoip&lt;/code&gt;, &lt;code&gt;personal&lt;/code&gt;, &lt;code&gt;tollFree&lt;/code&gt;, &lt;code&gt;premium&lt;/code&gt;, &lt;code&gt;unknown&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Industry standard; real-time NPAC; Stripe and Vercel use this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Telnyx Number Lookup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Telnyx&lt;/td&gt;
&lt;td&gt;Pay-as-you-go; free tier&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;carrier.type&lt;/code&gt;: &lt;code&gt;voip&lt;/code&gt;, &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;landline&lt;/code&gt; + OCN, SPID, LRN, ported_status&lt;/td&gt;
&lt;td&gt;Exposes raw OCN/SPID data; good for debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IPQS Phone Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;IPQualityScore&lt;/td&gt;
&lt;td&gt;Free tier + volume&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;VOIP&lt;/code&gt; (boolean) + &lt;code&gt;line_type&lt;/code&gt;: &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;landline&lt;/code&gt;, &lt;code&gt;VoIP&lt;/code&gt;, &lt;code&gt;prepaid&lt;/code&gt; + &lt;code&gt;fraud_score&lt;/code&gt; (0–100)&lt;/td&gt;
&lt;td&gt;Includes fraud scoring; claims 99%+ accuracy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vonage Number Insight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vonage (Ericsson)&lt;/td&gt;
&lt;td&gt;Tiered: Basic/Standard/Advanced&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;network_type&lt;/code&gt;: &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;landline&lt;/code&gt;, &lt;code&gt;virtual&lt;/code&gt;, &lt;code&gt;unknown&lt;/code&gt;, &lt;code&gt;pager&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;"Virtual" maps to VoIP; Vonage uses it to block VoIP on their own platform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Abstract Phone Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AbstractAPI&lt;/td&gt;
&lt;td&gt;Free 250/mo → tiered paid&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;phone_carrier.line_type&lt;/code&gt;: &lt;code&gt;Wireless&lt;/code&gt;, &lt;code&gt;Landline&lt;/code&gt;, &lt;code&gt;VOIP&lt;/code&gt; + &lt;code&gt;is_voip&lt;/code&gt; boolean&lt;/td&gt;
&lt;td&gt;Good free tier; 190+ countries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Numverify&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;apilayer&lt;/td&gt;
&lt;td&gt;Free 100/mo → $9.99–$99.99/mo&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;line_type&lt;/code&gt;: &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;landline&lt;/code&gt;, &lt;code&gt;special_services&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;No dedicated VoIP type; limited granularity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ekata Phone Intelligence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ekata (Mastercard)&lt;/td&gt;
&lt;td&gt;Enterprise/custom&lt;/td&gt;
&lt;td&gt;Carrier info, prepaid check, validity, velocity&lt;/td&gt;
&lt;td&gt;200M+ monthly queries; enterprise fraud context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Telesign Phone ID&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Telesign (TransUnion)&lt;/td&gt;
&lt;td&gt;Pay-as-you-go; free trial&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;phone_type&lt;/code&gt;: &lt;code&gt;landline&lt;/code&gt;, &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;VoIP&lt;/code&gt; + carrier name, registration status&lt;/td&gt;
&lt;td&gt;TransUnion identity network; banks and fintech use this&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Code Example: Running Your Own Carrier Lookup
&lt;/h3&gt;

&lt;p&gt;Before building anything, verify how your number is classified. Here's how to query Twilio's API directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twilio.rest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;phone_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lookups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;phone_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+14155551234&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;line_type_intelligence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;lti&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;line_type_intelligence&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Line type: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# e.g., "nonFixedVoip"
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mobile country code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mobile_country_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mobile network code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mobile_network_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;twilio&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twilio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;twilio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountSid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lookups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v2&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;phoneNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+14155551234&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line_type_intelligence&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lti&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineTypeIntelligence&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Line type: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// e.g., "nonFixedVoip"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`MCC: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;mobileCountryCode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`MNC: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;mobileNetworkCode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this on any number you plan to use with your agent. If you see &lt;code&gt;nonFixedVoip&lt;/code&gt; or &lt;code&gt;fixedVoip&lt;/code&gt;, that number will fail verification on Stripe, Google, WhatsApp, and most financial services.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Every Major Service Blocks VoIP: Service-by-Service Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stripe
&lt;/h3&gt;

&lt;p&gt;Stripe's phone verification runs during identity verification (Stripe Identity), account security setup, and certain high-risk payment flows. The technical mechanism combines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Carrier lookup (Twilio Line Type Intelligence or equivalent)&lt;/li&gt;
&lt;li&gt;Rejection if &lt;code&gt;line_type_intelligence.type&lt;/code&gt; is &lt;code&gt;fixedVoip&lt;/code&gt; or &lt;code&gt;nonFixedVoip&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Additional risk scoring: velocity checks, geographic mismatch between IP and carrier region, and number reputation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The error is explicit: "This phone number cannot be used for verification."&lt;/p&gt;

&lt;p&gt;There's no workaround via retry or different country codes. The check is at the carrier level, not the number level. Using a different Twilio number won't help — all Twilio programmable numbers share the same OCN (Bandwidth, BW Communications, or similar CLEC/VoIP providers), and those OCNs are classified as VoIP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google
&lt;/h3&gt;

&lt;p&gt;Google's blocking is more nuanced and less consistent than Stripe's, which makes it harder to debug. The mechanisms include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Line-type checking at account creation.&lt;/strong&gt; New Google account registrations check carrier type. Numbers classified as nonFixedVoip fail with "Something went wrong" or "This number cannot be used for verification."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Carrier range blacklisting.&lt;/strong&gt; Google maintains its own reputation database of carrier OCN ranges with abuse history. Even mobile numbers from certain prepaid carriers or MVNOs with high abuse rates get blocked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;eSIM complications.&lt;/strong&gt; A March 2026 Reddit thread in r/GMail documented widespread blocking of Philippine eSIM numbers despite them technically registering as mobile. Google appears to apply additional geographic and carrier-origin checks beyond the basic line-type lookup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon OTPs stopped routing to Google Voice.&lt;/strong&gt; As documented in Google Support forum posts from May 2024: "Amazon will no longer send OTP codes to Google Voice numbers." This means Amazon specifically targeted the Google Voice OCN range for SMS filtering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Amazon
&lt;/h3&gt;

&lt;p&gt;Amazon's blocking operates at the SMS routing layer through AWS SNS (Simple Notification Service), which Amazon uses to send OTP codes for its verification flows.&lt;/p&gt;

&lt;p&gt;The mechanism is carrier-type filtering: SNS checks the carrier type of the destination number before routing. If the number is VoIP, the message is silently dropped. No error is returned to the sender, and no code arrives for the recipient.&lt;/p&gt;

&lt;p&gt;For AI agents, this is the worst type of failure: the agent triggers the verification request, receives a success response from the API call, then waits indefinitely for a code that was discarded before it left Amazon's infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  WhatsApp
&lt;/h3&gt;

&lt;p&gt;WhatsApp's policy is explicit and documented. From their official FAQ:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Unsupported phone numbers, such as VoIP, landlines, and premium rate numbers, are not eligible for registration on WhatsApp."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The technical check happens at WhatsApp account registration. The carrier lookup is performed before the verification SMS is sent. VoIP numbers receive an immediate rejection error.&lt;/p&gt;

&lt;p&gt;WhatsApp also blocks verification via short-code SMS to VoIP numbers as a secondary mechanism — even if a VoIP number somehow passed the initial registration check, the short-code routing would filter it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microsoft Entra ID (Azure AD MFA)
&lt;/h3&gt;

&lt;p&gt;Microsoft's multi-factor authentication blocks VoIP via error code &lt;strong&gt;399287&lt;/strong&gt;, classified as "BadReputation" in their carrier reputation database.&lt;/p&gt;

&lt;p&gt;Microsoft Learn documentation (updated March 2026) is direct:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Phone extensions and VOIP numbers are not supported for MFA."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Microsoft applies per-number reputation tracking, not just per-OCN classification. A number that passes carrier lookup as "mobile" but has been associated with fraud attempts on other Microsoft accounts may still receive a BadReputation score.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vercel and DocuSign
&lt;/h3&gt;

&lt;p&gt;Both Vercel and DocuSign use Twilio Lookup's Line Type Intelligence directly in their onboarding flows. The code path is approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;line_type_intelligence&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nonFixedVoip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fixedVoip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid phone number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Banks and Financial Institutions
&lt;/h3&gt;

&lt;p&gt;Banks present a more heterogeneous blocking landscape because each institution implements its own carrier check. The patterns are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Silent blocking:&lt;/strong&gt; The verification SMS is simply never sent. The bank's UI shows a spinner and eventually times out. No error message indicates the phone type issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misleading errors:&lt;/strong&gt; BMO's documented case (Reddit r/PersonalFinanceCanada, February 2026): "BMO seems to have blocked 2FA verification from a landline VoIP number." The user received a generic error that didn't indicate the carrier type issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Post-enrollment blocking:&lt;/strong&gt; Some banks validate at SMS routing time rather than at enrollment. This means an agent may successfully register a VoIP number, only to find that OTP codes are never delivered at login time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Alternatives: What Actually Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Physical SIM Cards
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Physical SIM cards inserted in modems or smartphones. AT&amp;amp;T, Verizon, T-Mobile SIM cards register the OCN in LERG as WIRELESS. HLR lookups succeed. Carrier lookup returns &lt;code&gt;mobile&lt;/code&gt; across all APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification result:&lt;/strong&gt; Mobile on 100% of carrier lookup APIs. Passes all verification services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems for agents:&lt;/strong&gt; Requires physical hardware, $50–$80/month per number, no programmatic provisioning API, scale limited by hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. eSIM (Embedded SIM)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; eSIM profiles provisioned remotely via the SM-DP+ protocol. Connects to the carrier's mobile network exactly like a physical SIM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification result:&lt;/strong&gt; Functionally identical to physical SIM for LERG/NPAC classification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems for agents:&lt;/strong&gt; Google has documented blocking eSIM numbers from certain carriers. Not all carriers support programmatic eSIM provisioning.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. MVNO Numbers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; MVNOs (Mint Mobile, Google Fi, Tracfone) lease network capacity from MNOs. Numbers registered on LERG as WIRELESS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification result:&lt;/strong&gt; Generally classified as &lt;code&gt;mobile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems for agents:&lt;/strong&gt; Some MVNO OCN ranges are specifically blacklisted by high-fraud services. No programmatic provisioning API.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Number Porting (VoIP to Mobile)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Under FCC LNP rules, any US number can be ported from one carrier to another. Porting a VoIP number to a mobile carrier reclassifies it in NPAC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification result:&lt;/strong&gt; The number becomes &lt;code&gt;mobile&lt;/code&gt; permanently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems for agents:&lt;/strong&gt; Takes hours to days. One-time operation per number. Not suitable for dynamic provisioning at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Silent Network Authentication (SNA)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Carrier-level authentication that verifies phone number ownership using the SIM's authenticated data session — invisible in 1–4 seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification result:&lt;/strong&gt; Requires a real mobile SIM. Cannot be spoofed by VoIP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems for agents:&lt;/strong&gt; Requires mobile data (not Wi-Fi). Not universally supported yet. Only an authentication mechanism, not provisioning.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Real SIM Number APIs (The Programmatic Solution)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Services like AgentSIM operate physical SIM cards in carrier-connected modems, and expose those numbers via API. Provision a number, receive an OTP via API webhook or long-poll, release when done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification result:&lt;/strong&gt; &lt;code&gt;mobile&lt;/code&gt; on all carrier lookup APIs. Passes Stripe, Google, Amazon, WhatsApp, Microsoft Entra, and bank verifications.&lt;/p&gt;




&lt;h2&gt;
  
  
  AgentSIM: Real Mobile Numbers via API
&lt;/h2&gt;

&lt;p&gt;AgentSIM is built specifically for this use case. Every provisioned number is backed by a physical SIM on a US carrier network. Carrier lookup returns &lt;code&gt;mobile&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python: Complete OTP Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AgentSimClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Provision a real mobile number
&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe-onboarding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Phone number: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# e.g. +14085551234 — carrier lookup returns "mobile"
&lt;/span&gt;
&lt;span class="c1"&gt;# 2. Enter session.number into the service that will send the OTP
&lt;/span&gt;
&lt;span class="c1"&gt;# 3. Wait for the OTP (blocks until received, up to 60s)
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OTP code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;agentsim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OtpTimeoutError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Timeout — retry with new number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 4. Always release the number when done
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript: Complete OTP Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OtpTimeoutError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PoolExhaustedError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@agentsim/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyWithStripe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// await using releases the number automatically on exit (TypeScript 5.2+)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;provision&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stripe-onboarding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ttlSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Phone number: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// e.g. +14085551234 — carrier lookup returns "mobile"&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForOtp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`OTP: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;otpCode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;otpCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;OtpTimeoutError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No OTP in 60s — carrier retry may be needed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;PoolExhaustedError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No US numbers available&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MCP Integration
&lt;/h3&gt;

&lt;p&gt;If you're using Claude Code, Cursor, or any MCP-compatible assistant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentsim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"streamable-http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.agentsim.dev/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"x-api-key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asm_live_..."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, your assistant can call &lt;code&gt;provision_number&lt;/code&gt;, &lt;code&gt;wait_for_otp&lt;/code&gt;, and &lt;code&gt;release_number&lt;/code&gt; autonomously — no human intervention required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementation Guide: Verifying Numbers Before Use
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Python: Check Number Type Before Sending OTP
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twilio.rest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_line_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lookups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;phone_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;line_type_intelligence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lti&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;line_type_intelligence&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lti&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lti&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_mobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_line_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mobile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript: Check Number Type
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Telnyx&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;telnyx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getLineType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phoneNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;telnyx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Telnyx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TELNYX_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;telnyx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numberLookup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phoneNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;carrier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;carrier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;carrier&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;carrier&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;carrier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;carrier&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;portedStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;carrier&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;ported_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Does this affect Twilio numbers specifically, or all VoIP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All VoIP numbers are affected, not just Twilio. Twilio programmable numbers are classified &lt;code&gt;nonFixedVoip&lt;/code&gt; because Twilio's OCN is classified as a VoIP/CLEC provider in LERG. The same applies to Telnyx, Bandwidth, Vonage, Plivo, Sinch, and every other CPaaS provider's programmable numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: My Twilio number worked on Google last year. Why is it failing now?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VoIP blocking has been tightening progressively. A number or OCN range that was tolerated in 2023 may now be explicitly blocked. Google in particular has been documented increasing eSIM and VoIP restrictions in early 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What about prepaid mobile numbers? Do they pass?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prepaid mobile numbers from major carriers (AT&amp;amp;T Prepaid, T-Mobile Prepaid, Verizon Prepaid) pass carrier lookup as &lt;code&gt;mobile&lt;/code&gt;. However, fraud-sensitive services apply additional velocity and reputation scoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I port my existing Twilio number to a mobile carrier?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, in principle. After porting, NPAC updates the SPID and the number is reclassified as mobile. This is a one-time operation — not suitable for dynamic number provisioning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Will this change as AI agent use cases grow?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The direction is toward stricter verification, not looser. Silent Network Authentication (SNA) is emerging as a more secure alternative — it requires a real SIM and mobile data, making it impossible to fake with VoIP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What about international numbers?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VoIP blocking is primarily a US/Canada phenomenon due to the specific LERG/NPAC infrastructure. AgentSIM currently supports US numbers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The VoIP blocking problem is structural, not accidental. Services block VoIP numbers because the LERG/NPAC/OCN infrastructure exposes carrier type reliably, VoIP numbers have statistically higher fraud rates, and blocking is technically trivial once carrier lookups are already running.&lt;/p&gt;

&lt;p&gt;For AI agents that need SMS verification to pass Stripe, Google, WhatsApp, Amazon, Microsoft, or financial institutions, the only path forward is a number that carrier lookup APIs classify as &lt;code&gt;mobile&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://docs.agentsim.dev/quickstart" rel="noopener noreferrer"&gt;docs.agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP server:&lt;/strong&gt; &lt;code&gt;mcp.agentsim.dev/mcp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get an API key:&lt;/strong&gt; &lt;a href="https://console.agentsim.dev" rel="noopener noreferrer"&gt;console.agentsim.dev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>python</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
