
Share:
)
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.
Prevent SIM Swap Fraud in Python With the Identity Insights API
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:
A Vonage Developer Account
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:
Network Registry capability enabled, and select “Playground”
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
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 thesim_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 returnsswapped = true
If
hours < 500
, it returnsswapped = 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:
)
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.