Finding Prime Phone Numbers on Twilio
While writing a treasure hunt inspired by the DEFCON badge challenges, I needed a prime phone number. That is, a phone number which also happens to be a prime number.
Using the Twilio API, I made a script to find prime phone numbers. Prime numbers are the coolest numbers out there (apart from e and π). So I built primenumbers.io where you can find your very own prime phone number. You can easily set it up to forward to your phone using Twimlets or TwiML Bins.
Let’s look at how to make this script to find prime phone numbers in NodeJS.
Step 1: Getting Phone Numbers from Twilio
First install the Twilio Node library:
$ npm install -S twilio
Twilio is a telephony service for developers. You can get phone numbers from around the world and use their API to program those numbers. If you don’t have a Twilio account, you’ll need to sign up for one on twilio.com to get your API credentials.
You’ll find your account SID and auth token on your dashboard. Set these as environment variables. It’s a bad idea to add them to your code in case you push them to GitHub by accident.
$ export TWILIO_AC_SID=<your-account-sid>
$ export TWILIO_AUTH_TOKEN=<your-auth-token>
Add these lines to your
.bashrc to use the environment variables later.
Now we can start using the twilio API. Create a file
index.js and write in the following code:
This makes a call to Twilio’s available phone numbers resource (documentation here). This requests a list of phone numbers which are available for provisioning. You can only search for numbers from one country at a time. In this case, we have searched for numbers from the US.
The API call takes in an options object which corresponds to the querystring parameters that can be sent to that endpoint. For the US and Canada, we can ask for a specific area code. Here, we’ve asked for numbers with the area code 650.
The method returns a promise that resolves when the response is received from the server. Once the promise resolves, we print the output to the console. You should see something like this:
Great! You’ve successfully retrieved a list of available phone numbers from Twilio. Now let’s test a list for prime phone numbers.
Step 2: Testing the Numbers for Primality
To test for primality, we’re going to install the
primality npm module:
$ npm install -S primality
Make sure to require the module by adding
var primality = require('primality') to the top of
Now add the following code on the fulfilment of
This initiates an empty array
verifiedPrimes to hold our prime phone numbers. Then for each phone number, we test if it’s prime. If it is prime, and isn’t already in the array, we add the phone number to
verifiedPrimes. In this code, we’re removing the first two characters of the phone number because that is the country code “+1”. We want to ignore country codes.
Run this script and you should see some prime phone numbers! Sometimes the script outputs two or three numbers. Sometimes it outputs none. Since the distribution of primes is (sorta) random and the phone numbers sent from Twilio appear random, we can’t guarantee that we’ll always get a certain number of primes from Twilio’s 30 phone numbers.
How many numbers on average should we expect? The prime number counting function π(x), tells us the number of primes the are below the number x. So we can find out what portion of phone numbers with the area code 650 are prime:
That means 4.43% of the phone numbers we receive from Twilio should be prime. So the average number of primes for 30 numbers between that range would be 0.0443*30=1.33. That seems about right, as we tend to get 1 or 2 numbers whenever we run the script.
Step 3: Getting even more Numbers
But one or two prime phone numbers aren’t going to cut it. We want a list of at least 20 primes to choose from! Unfortunately, we can’t choose how many results to get from the available numbers resource. So let’s make a call to the Twilio available numbers resource 20 times.
We’ll do that by putting the call to the Twilio API in a
for loop. Then we’ll add all of the promises from those calls to an array. Using
Promise.all we can create a new promise that resolves when all of the promises in the array resolves:
Now instead of doing the primality test when just one promise from the Twilio API resolves, we’ll do it when they all resolve — i.e. when
This script should print out about 26 prime prone numbers. However you may get far fewer numbers:
And if you run the script again, you may receive exactly the same output. What’s going on here?
If you make too many requests to the available numbers resource in a short period of time, Twilio will start caching the results. Every promise returns the same cached data. That means you don’t get more than 30 unique phone numbers to test for primality. So the script outputs far fewer numbers and outputs the same numbers every time.
Step 4: Hacking the Twilio API to get Unique Responses
Luckily this is an easy problem to solve. First of all let’s add a small function to our script to generate a random integer between two integers:
Next, simply add
Contains: getRandomInt(10,99) to the options object passed into the Twilio API call. The
Contains option asks Twilio to return phone numbers that contain a specific string of numbers. Each iteration of the
for loop will ask Twilio to search for numbers with a different pair of digits. This will bypass the caching problem.
Running the script now, gives us a long list of prime phone numbers to choose from:
Step 5: Numbers Outside the US
Now let’s clean up our script a bit and make it so that it works with more countries. Twilio offers numbers from 44 countries so we want to be able to search for prime phone numbers from any of them.
Let’s wrap all of the business logic in a function. Let’s pass to that function an ISO two-letter country code and an area code:
Now let’s generalize our API call to use
isoCountry instead of
areaCode instead of
Now that we’re working with numbers from any country, removing the country code becomes more complex. Country code lengths can vary quite a bit, from “+1” in the US to the Dominican Republic’s “+1829”. Here's a module that lists all of the 44 country codes Twilio uses. Download it into your project directory and include it in your script using
var countries = require('./countries');. Now for any ISO two-letter code we can find the length of the calling code using
countries[isoCountry].code.length. In the case of
'GB' that would be length
'+44'. So now our primality test becomes:
primeNumberPromise completes the function. Add the following to your script to call the function for the US and the UK: