A hashed phone number is a phone number with an extra step
Published 2026-10-24
“We only send hashed data” is the sentence that makes a customer-list upload feel safe. The idea behind it is that a hash is one-way, so the platform gets a code and not a person. For a phone number, one-way does not mean much. There are only 6.4 billion possible US and Canadian phone numbers. We hashed all of them on one ordinary cloud VM in 5 minutes 40 seconds, and the hidden number came back.
A hashed contact is still a contact. It is still personal data, and the ad platforms say so in their own documentation.
The test
A script picked a random number, normalised it the way Meta’s Conversions API documents (1 plus ten
digits, no symbols), printed only its SHA-256 hash and kept nothing else. The number was in the fictional
555-01xx range, so a real person’s number appears nowhere in this test.
Every North American number has the form NXX-NXX-XXXX: an area code, an exchange and a line number. N is a digit from 2 to 9 and X is any digit. That gives 800 × 800 × 10,000 = 6,400,000,000 possible numbers. Every real US and Canadian number is one of them.
A 40-line C program hashed each one in Meta’s format and compared it with the target:
| Numbers tried | 6,400,000,000 (every NXX-NXX-XXXX) |
| Hardware | 4-vCPU cloud VM, Intel Xeon 2.80 GHz, no GPU |
| Time | 339.7 seconds |
| Speed | 18.84 million hashes a second |
| Matches | exactly 1: 18365550172, the hidden number |
There was one match, and it was the right one. That is the property that makes hashes useful for matching: one input gives one output. For the same reason, anyone who can list the inputs can reverse the hash.
This was the slow method: general-purpose CPU code, no tuning, no graphics card. Narrow the guess and it
gets faster. Meta’s documentation prints an example hash, e323ec62…3176, for the number
(650) 555-1212. We started from the hash alone and guessed only the area code. One thread tried the
8 million numbers in area code 650 and found 16505551212 in 2.1 seconds.
What the platforms and regulators already say
None of this is new to the people who receive the hashes.
- Meta calls the fields it wants hashed “Contact Information”, which it defines as “information that personally identifies individuals, such as names, email addresses, and phone numbers”. Its systems are designed to refuse that data unhashed. In Meta’s own words, hashing changes the format. The data still identifies a person.
- Google’s Data Manager API wants the phone number in E.164 (
+18005550100) and then SHA-256 hashed. The format is different from Meta’s (Google keeps the plus sign), so the two hashes of one number are different. The input space is the same 6.4 billion numbers. - The FTC’s Office of Technology wrote in July 2024 that companies “should not act or claim as if hashing personal information renders it anonymized”. It says hashing over common identifiers such as email addresses and phone numbers can be reversed, and it lists enforcement cases where hashing was part of the story: Nomi, BetterHelp, Premom and InMarket.
- The GDPR, Recital 26, treats pseudonymised data that can be attributed to a person with additional information as data on an identifiable person. Its test is “the costs of and the amount of time required for identification” with the technology available. For phone numbers we measured both: one rented VM and under six minutes.
Email addresses cannot be listed exhaustively the way phone numbers can. But nobody who matches them needs to list every address. A platform holds the plain email addresses of its own users. It hashes them with the same rule as you and looks up your hash. Matching is re-identification, and it is the service you are paying for. The platform does not have to break the hash. It already holds the input that produces it.
What hashing does, and what it does not do
Hashing still does a job. Meta and Google require it. It keeps the plain address or number out of the request body, and so out of logs and intermediate systems on the way. That is transport hygiene. A hash cannot keep the person out of the data, because a hash that a platform can match identifies that person.
A salted hash, with a secret value added before hashing, is much harder to reverse. For the same reason, no platform can match it, because the platform does not have your salt. A salt works for the identifiers you store yourself. It does not work for an upload whose purpose is to be matched.
What to do differently
- Do not call a hashed upload “anonymous” or “anonymised” in a privacy policy, a consent banner, a DPA or a sales deck. The FTC has said in writing that this is the claim it looks for.
- Give a hashed list the same rules as the plain list. It needs the same legal basis or consent, the same retention period, the same deletion on request and the same access control. If a customer asks to be deleted, delete their hash from your audience files too.
- Write down where each hashed identifier goes. “We send SHA-256 phone numbers to Meta and Google” is a disclosure of phone numbers to Meta and Google. Your records of processing should say that.
- Salt what you keep, not what you send. For your own stored lookup keys, use a salted or keyed hash. For platform uploads, the plain SHA-256 is the only form that matches.
So a hash does not hide the person. It does one thing: it matches, and only when both sides hashed exactly the same string. Eight ad platforms each describe that string differently, and one email address gives three different hashes by their written rules, five with Google’s code samples. That is the thing to test before you switch trackers.
Sources
- Meta's Conversions API: phone numbers are hashed. Remove symbols, letters and any leading zeros, and include the country code. Example: the US number (650)555-1212 normalises to 16505551212, with the expected SHA-256 output e323ec626319ca94ee8bff2e4c87cf613be6ea19919ed1364124e16807ab3176. verified 2026-10-24
- Meta's Conversions API: its systems are designed not to accept unhashed Contact Information, which Meta describes as information that personally identifies individuals, such as names, email addresses and phone numbers, that it uses for matching purposes only. verified 2026-10-24
- Google's Data Manager API: phone_number is hashed with SHA-256 and uses E.164 format, with the plus sign and the country code. The US number (800)555-0100 is normalised to +18005550100. verified 2026-10-24
- NANP numbers are ten digits long, in the format NXX-NXX-XXXX, where N is any digit 2-9 and X is any digit 0-9: a three-digit area code, a three-digit central office code and a four-digit line number. verified 2026-10-24
- FTC Office of Technology, 24 July 2024: companies should not act or claim as if hashing personal information renders it anonymized. Hashes can still be used to identify users, and hashing can be reversed when it is performed over common identifiers such as email addresses and phone numbers. The post cites FTC cases against Nomi, BetterHelp, Premom and InMarket. verified 2026-10-24
- GDPR Recital 26: personal data which have undergone pseudonymisation, and which could be attributed to a natural person by the use of additional information, should be considered information on an identifiable natural person. Whether a person is identifiable takes account of all the means reasonably likely to be used, including the costs of and the amount of time required for identification, given the technology available at the time. verified 2026-10-24