https://a.storyblok.com/f/270183/1368x665/359ade8d2c/25sep_dev_blog_sim-swap-id-insight.jpg

Prevent SIM Swap Fraud in Python With the Identity Insights API

Published on September 23, 2025

Time to read: 4 minutes

SIM swap fraud is a rising threat in mobile security, where attackers hijack a victim’s phone number by transferring it to a new SIM card. This allows them to intercept calls, texts, and even two-factor authentication codes. Scary!

In this tutorial, we’ll use the Vonage Identity Insights API in Python to detect potential SIM swaps and protect your users.

>> TL;DR: Get the full working code on GitHub

Prerequisites

To follow along, you’ll need:

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Project Setup

Create a Vonage Application

  • To create an application, go to the Create an Application page on the Vonage Dashboard, and define a Name for your Application.

  • If needed, click on "generate public and private key". A private key (.key file) will be generated. Download and store it securely. This key is needed for authentication when making API requests. Note: Private keys will not work unless the application is saved.

  • Choose the capabilities you need (e.g., Voice, Messages, RTC, etc.) and provide the required webhooks (e.g., event URLs, answer URLs, or inbound message URLs). These will be described in the tutorial.

  • To save and deploy, click "Generate new application" to finalize the setup. Your application is now ready to use with Vonage APIs.

Your Python script will use the Network Registry Sandbox. In order to do that, create a Vonage application in the Vonage Dashboard with: 

  1. Network Registry capability enabled, and select “Playground”

  2. Generate a private.key, you will need to move this to the root of your directory in the following section

Create Your Project and Install Dependencies

  1. Create your project folder and files in your terminal.

mkdir sim_swap_checker
cd sim_swap_checker
touch main.py .env

>> You can now move your downloaded private.key into the sim_swap_checker directory

2. Set up a virtual environment.

This ensures your dependencies stay isolated from your system Python.

python3 -m venv venv

source venv/bin/activate

3. Install the required packages.

We'll use requests to make HTTP requests to the Identity Insights API, python-dotenv to securely load our API credentials from an environment file, and vonage-jwt to generate secure JWT tokens for authenticating our requests.

pip install requests python-dotenv vonage-jwt

Configure Your ENV File

Add the ID of your Vonage Application and the default phone number + period in hours for which the API will perform the SIM Swap check.

You can see in the Identity Insights API Reference that the Sim Swap insight relies on a single parameter called period, we’ll call it hour, and set the default as 240.

VONAGE_APPLICATION_ID=your_application_id
VONAGE_PRIVATE_KEY_PATH=./private.key
PHONE_NUMBER=+990123455
DEFAULT_HOURS=240

Write the Python Script to Check for a Sim Swap

Step 1: Set Up the Imports and Environment

In the main.py file, let’s build the main script that checks whether a SIM swap has occurred within a user-defined timeframe (defaulting to 240 hours, or 10 days).

Start by importing the required libraries and loading environment variables from .env file. This ensures we don’t hardcode sensitive values and makes it easier to quickly update the phone number and time period to test different values.

# main.py
import requests
from dotenv import load_dotenv
import os
from vonage_jwt import JwtClient

load_dotenv()

API_URL = "https://api-eu.vonage.com/v0.1/identity-insights"
PHONE_NUMBER = os.getenv("PHONE_NUMBER")
DEFAULT_HOURS = int(os.getenv("DEFAULT_HOURS"))
application_id = os.getenv("VONAGE_APPLICATION_ID")
private_key_path = os.getenv("VONAGE_PRIVATE_KEY_PATH")

Step 2: Authenticate with JWT

Before we can make any calls to the Identity Insights API, we need to authenticate using a JSON Web Token (JWT). This is required for all Vonage Network APIs.

A JWT securely identifies your application using your APPLICATION_ID and private key, and includes metadata like when it was issued ( iat) and when it expires ( exp). These tokens are signed using the RS256 algorithm and typically remain valid for just a few minutes, making them secure and short-lived.

Below your environment variables, initialize your JwtClient. We’ll use this client to generate the actual JWT when making the API request.

with open(private_key_path, "r") as f:
    private_key_str = f.read()

jwt_client = JwtClient(application_id, private_key_str)

Step 3: Define the Core SIM Swap Check Function

Next, we’ll continue below and define a check_sim_swap() function that takes in a phone number and a period in hours. It uses the JWT client to authenticate and sends a POST request to the Identity Insights API.

# main.py

def check_sim_swap(phone_number, hours):

    jwt_token = jwt_client.generate_application_jwt()

    headers = {
        "Authorization": f"Bearer {jwt_token}",
        "Content-Type": "application/json"
    }

    payload = {
        "phone_number": phone_number,
        "purpose": "FraudPreventionAndDetection",
        "insights": {
            "format": {},
            "sim_swap": {
                "period": hours
            }
        }
    }

    print(f"\n🔍 Checking SIM swap status for {phone_number}...")
    res = requests.post(API_URL, headers=headers, json=payload)

    if res.status_code != 200:
        print("❌ Error:", res.status_code, res.text)
        return

    data = res.json()

This code sets the purpose to "FraudPreventionAndDetection", a requirement for using SIM swap insights. If the API returns anything other than a 200 OK, we print the error to the console and exit.

Step 4: Parse and Display SIM Swap Results

Next, we extract the SIM swap data and check the response status. If everything is OK, we display whether a swap was detected during the given timeframe and when the last SIM swap occurred.

   sim_swap_info = data.get("insights", {}).get("sim_swap", {})
    status_code = sim_swap_info.get("status", {}).get("code")

    if status_code != "OK":
        print(f"\n⚠️ SIM Swap check failed. Status: {status_code}")
        print("   Message:", sim_swap_info.get("status", {}).get("message"))
        return

    swapped = sim_swap_info.get("swapped")
    swap_time = sim_swap_info.get("latest_sim_swap_at")

    print(f"\n🔒 SIM Swap Results:")
    print(f"   SIM Swapped: {'❌ Yes' if swapped else '✅ No'}")
    print(f"   Last SIM Swap: {swap_time if swap_time else 'None detected'}")

Step 5: Add a CLI Wrapper for Interactivity

Finally, we add a main block so users can run the script interactively from the command line. It prompts for the phone number and number of hours to check, falling back to defaults if none are entered.

The Virtual Operator has 9 phone numbers for the Identity Insights API that you can use for testing. The API returns deterministic SIM swap responses:

  • If hours > 500, it returns swapped = true

  • If hours < 500, it returns swapped = false

You can also try testing with allowlist numbers in the Network Registry Playground.

if __name__ == "__main__":
    print("=== Vonage Identity Insights - SIM Swap Checker ===")
    phone = input(f"Enter phone number [Default: {PHONE_NUMBER}]: ").strip() or PHONE_NUMBER
    hours = input(f"How many hours ago to check for? [Default: {DEFAULT_HOURS}]: ").strip() or DEFAULT_HOURS
    hours = int(hours)
    check_sim_swap(phone, hours)

>> Make sure that this code is not auto-indented by your linter to be inside the check_sim_swap function.

Test the Script with the Virtual Operator

You can now test your little app!

python3 main.py

First, you can use the default values and see that the Sim was not swapped:

(venv)   sim_swap_checker python main.py
=== Vonage Identity Insights - SIM Swap Checker ===
Enter phone number [Default: +990123455]: 
How many hours ago to check for? [Default: 240]: 

🔍 Checking SIM swap status for +990123455...

🔒 SIM Swap Results:
   SIM Swapped: No
   Last SIM Swap: 2025-07-10T08:48:55.143Z

And then you can use a value for hours being higher than 500 to see a Sim Swap:

(venv)   sim_swap_checker python main.py
=== Vonage Identity Insights - SIM Swap Checker ===
Enter phone number [Default: +990123455]: 
How many hours ago to check for? [Default: 240]: 600

🔍 Checking SIM swap status for +990123455...

🔒 SIM Swap Results:
   SIM Swapped: Yes
   Last SIM Swap: 2025-07-10T08:50:16.733Z

Conclusion

With just a few lines of Python and the Vonage Identity Insights API, you can identify SIM swap events and proactively flag high-risk scenarios in your applications. While this demo uses the Virtual Operator for testing, the same setup works in production once your application is registered in theNetwork Registry.

Got questions or building something cool? Join us in theVonage Community Slack, follow ourYouTube channel, or subscribe to the Developer Newsletter for updates.

Share:

https://a.storyblok.com/f/270183/384x384/e4e7d1452e/benjamin-aronov.png
Benjamin AronovDeveloper Advocate

Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.