Random 10 digit number generator
Uniform ten-digit draws over all 10 billion values, phone-number-shaped but deliberately not phone numbers.
Ten digits looks like a phone number and is not one
A North American phone number is ten digits, which is why this length gets searched for. It is also why the first thing to say is that a random ten-digit string is almost never a valid number.
The North American Numbering Plan splits the ten digits into a three-digit area code, a three-digit central office code and a four-digit line number. Both the area code and the central office code must begin with a digit from 2 to 9. A uniformly random draw satisfies both of those only 64% of the time, so more than a third of generated values are structurally invalid before you check anything else. Then come the further restrictions, the codes that are reserved rather than assigned, and the fact that most valid-shaped combinations have never been allocated to a carrier at all.
| Position | Field | Allowed | Uniform draw satisfies it |
|---|---|---|---|
| 1 | Area code, first digit | 2-9 | 80% |
| 2-3 | Area code, remainder | 0-9, with reserved patterns excluded | Mostly |
| 4 | Central office code, first digit | 2-9 | 80% |
| 5-6 | Central office code, remainder | 0-9, with reserved patterns excluded | Mostly |
| 7-10 | Line number | 0-9 | Always |
Do not use generated digits as test phone numbers
This is the part that causes real harm. If you seed a test database with random ten-digit values and any of them happen to be valid, they belong to somebody. The first time a test run reaches a live SMS gateway, a stranger receives your verification codes, and at volume you have built an accidental spam campaign against real people.
Use the reserved range instead. The numbers 555-0100 through 555-0199 in any area code are set aside for fictional use, which is why they appear in films and documentation and why they are never assigned to a subscriber. That is 100 numbers per area code, enough for most fixtures, and they are safe by construction rather than by luck. If you need more, most SMS providers publish their own test numbers that accept messages and never deliver them.
Never route a message to a randomly generated number, even in staging. The reserved 555-01xx range and your provider test numbers exist precisely so that this cannot happen by accident.
Ten digits overflows a 32-bit integer
The largest ten-digit value is 9,999,999,999. A signed 32-bit integer tops out at 2,147,483,647 and an unsigned one at 4,294,967,295, so most ten-digit values do not fit in either. Declare the column INT and the majority of your identifiers will be rejected or truncated on insert, depending on how forgiving the database is configured to be.
The correct type for a ten-digit identifier is a string: CHAR(10) or VARCHAR. That handles the width problem and the leading-zero problem at the same time. If you insist on a numeric column, it has to be a 64-bit integer, and you still have to pad on the way out because 0123456789 stored as a number is 123456789.
The size of the space
Ten digits give 10,000,000,000 values and 10 x log2(10) = 33.22 bits. Duplicates appear at 1% after 14,178 draws and at 50% after 117,741, so even ten billion values is not a uniqueness guarantee at any scale worth calling a scale.
As entropy, 33.22 bits sits in the weak band. It is far too small for a token or a key, and it is only appropriate as an identifier that is protected by something other than being hard to guess.
Doing this in your own code
JavaScript
// 10 independent digits, uniform, leading zeros preserved.
// 250 is Math.floor(256 / 10) * 10. Bytes at or above it are thrown away,
// which is what keeps every digit at exactly 1 in 10.
function randomDigits(n) {
const buf = new Uint8Array(1);
let out = "";
while (out.length < n) {
crypto.getRandomValues(buf);
if (buf[0] >= 250) continue;
out += buf[0] % 10;
}
return out;
}
randomDigits(10); // a 10-character string, never a number The usual shortcut, Math.floor(Math.random() * 9e5) + 1e5, cannot produce a leading zero and draws from a PRNG whose state is recoverable from its output.
Python 3.6+
import secrets
# Draw the digits. This never becomes an int, so leading zeros survive.
"".join(secrets.choice("0123456789") for _ in range(10))
# Or draw one integer and pad it back to width.
f"{secrets.randbelow(10 ** 10):010d}" random.randint() uses the Mersenne Twister and is not a security boundary. secrets draws from os.urandom.
Go
import (
"crypto/rand"
"fmt"
"math/big"
)
limit := new(big.Int).Exp(big.NewInt(10), big.NewInt(10), nil)
v, err := rand.Int(rand.Reader, limit)
if err != nil {
panic(err)
}
// The width verb is the part that keeps the leading zeros.
fmt.Printf("%010d\n", v) Java
import java.security.SecureRandom;
SecureRandom rnd = new SecureRandom();
StringBuilder sb = new StringBuilder(10);
for (int i = 0; i < 10; i++) {
sb.append(rnd.nextInt(10));
}
String value = sb.toString(); nextInt(bound) already rejects the unusable top of the range, so it is unbiased for a bound of 10.
PHP 7+
// random_int() is backed by the system CSPRNG.
// rand() and mt_rand() are not, and must not be used here.
$value = str_pad((string) random_int(0, 10 ** 10 - 1), 10, '0', STR_PAD_LEFT); Shell
# 10 digits straight from the kernel CSPRNG.
# tr keeps only ASCII digits, so every byte that survives is uniform over 0-9.
LC_ALL=C tr -dc '0-9' < /dev/urandom | head -c 10; echo Questions
Are these real phone numbers?
Almost never. Both the area code and the central office code must start with a digit from 2 to 9, which a uniform draw satisfies only 64% of the time, and most valid-shaped combinations have never been assigned to a carrier. Treat the output as a ten-digit identifier that happens to be phone-shaped.
What should I use for test phone numbers?
The reserved fictional range 555-0100 to 555-0199, which is never assigned to a subscriber, or the test numbers your SMS provider publishes. Both are safe by design. Random digits are not, because a valid one belongs to a real person who will receive whatever your test harness sends.
Will a 10-digit number fit in an INT column?
No. Signed 32-bit integers stop at 2,147,483,647 and unsigned at 4,294,967,295, while ten-digit values run to 9,999,999,999. Use CHAR(10) or VARCHAR, which also preserves leading zeros, or a 64-bit integer if it must be numeric.
Can the output start with 0?
Yes, and one in ten does, because each digit is drawn independently. That is another reason to store the value as a string: 0123456789 held as a number is 123456789, which is a different, nine-character value.
How many can I generate before two are the same?
The chance of a duplicate reaches 1% at 14,178 draws and 50% at 117,741. Collisions arrive near the square root of the space, so ten billion values gives you roughly a hundred thousand draws, not ten billion.