How We Made Truecaller Finally Work on iPhone
EngineeringiOSHow We Made Truecaller Finally Work on iPhone

How We Made Truecaller Finally Work on iPhone

Ahmed Alnaqah's Profile Picture

Ahmed Alnaqah

Jun 30, 202511 min read

This blog examines the technical foundations of our implementation of Live Caller ID Lookup. It’s a story about challenges, workarounds, and eventually, a breakthrough in a system that can deliver real-time Caller ID at a global scale, without knowing who you are, where you are, or who is calling you.

Truecaller's Mission

Truecaller exists to protect users from spam and scam calls, help them identify legitimate businesses, and enable people to recognise each other even before picking up the phone.

But delivering this experience also demands a deep commitment to privacy: protecting the privacy of the people using our service. Caller ID is inherently sensitive. When someone looks up a phone number, it can reveal patterns of communication, intent, or personal associations. From the very beginning, we knew that if Truecaller were to succeed at scale, it would need to do so in a way that puts user privacy first.

This blog explores the technical foundations of how we achieved exactly that. It’s a story about challenges, workarounds, and eventually, a breakthrough in a system that can deliver real-time Caller ID at a global scale, without knowing who you arewhere you are, or who is calling you.

The Early Days of Caller ID on iOS

Back in 2009, delivering Caller ID on iPhone felt almost like a hack. There was no native support for identifying callers. When users received a call from an unknown number, they had to copy that number manually, open the Truecaller app, paste it, and then search to find out who was calling. It was clunky and far from the seamless experience we envisioned.

This changed in 2016 when Apple introduced the Call Directory Extension. For the first time, iOS offered a mechanism to recognize phone numbers as calls came in. The extension allowed apps like Truecaller to preload a list of numbers and associated identities. When a call arrived, iOS would check this local directory and display the corresponding name if it matched.

Call Directory Extension Diagram

However, the Call Directory Extension came with limitations. The memory allocated to the extension was small. The extension can crash or silently fail for multiple reasons. Plus, updating the list wasn’t straightforward.

To handle multiple sources feeding data into the call directory, we implemented separate extensions for each source. This modular approach helped isolate logic and reduce the risk of cascading failures across the system. It also allowed us to work around another important constraint: the limited number of contacts each extension can register. By distributing the contact data across multiple extensions, we were able to extend the overall capacity of identifiable numbers beyond what a single extension could support.

However, this design introduced a new challenge. Onboarding users now requires manually enabling each extension through iOS Settings, something that couldn’t be done programmatically. This extra step added friction to the setup process and increased the likelihood of incomplete activation, which could result in missed identifications.

To keep the directory up to date, we implemented a background task scheduler to update the list periodically. Unfortunately, iOS deprioritises background activity unless the app is frequently used, which means the data could quickly become stale for infrequent users. Onboarding also became hard, users had to manually enable the extension from settings, something many never did. And beyond onboarding, this offline approach was fundamentally limited. Truecaller can identify billions of phone numbers, but the Call Directory Extension had a hard cap on the number of entries it could handle. Supporting such scale through preloaded offline lists was simply not feasible.

Siri Shortcut

Siri Shortcut Diagram

In 2023, we tried a new approach: using App Shortcuts. We created a shortcut that allowed users to invoke a Caller ID lookup by simply asking Siri, pressing the action button on iPhone 15 Pro and above, or by double-tapping on the back of the iPhone. When triggered, the shortcut would take a screenshot of the incoming call screen, extract the number using OCR, and then perform a search in the Truecaller database.

While innovative, this method was far from ideal. It required users to perform a manual step and go through a non-trivial setup process. It was clever, but it lacked the reliability and ease that users expected.

A Breakthrough with iOS 18

At WWDC 2024, Apple introduced a feature that finally addressed many of these limitations: Live caller ID lookup. This feature, designed specifically for apps like Truecaller, allows apps to perform real-time lookups of incoming calls while preserving user privacy. The underlying technology is based on Private Information Retrieval (PIR).

Live Caller ID Lookup Apple Documentation

From the iOS 18 feature document by Apple

This is one of the most exciting breakthroughs for real-time communication privacy. Live Caller ID Lookup in iOS 18 is a major leap forward, not just for Truecaller, but for the developer community and millions of users who depend on trusted communication. This breakthrough succeeds by meeting three essential requirements:

  1. User identity must be protected — The system must ensure that no personal identifiers, such as IP address or device metadata, are exposed to the service provider.
  2. The query itself must remain private — Even the phone number being queried should stay hidden from all parties except the device making the request. This is made possible through techniques like homomorphic encryption and PIR.
  3. It must work in real time — Despite the privacy-preserving mechanisms, the system must maintain a seamless user experience during a live incoming call.

Below is a real-world example of how Live Caller ID looks for a Truecaller user on iOS 18:

Live Caller ID Lookup Example on iOS

Let’s break down how this all works under the hood.

1. Preserve User Identity

One of the most critical privacy challenges in building a Live Caller ID system is ensuring that the identity of the user making a query is never exposed. When a device receives a phone call and needs to look up the caller’s identity, it must send a request to Truecaller's servers. But without the right safeguards, that request could leak sensitive metadata, such as the user’s IP address, location, or other device-specific information.

To solve this, Apple designed the system so that apps provide an extension containing a server endpoint and credentials. When a call is received, iOS uses Private Information Retrieval (PIR) to send the query. However, this request doesn’t come directly from the user’s device. Instead, it's relayed through an Oblivious HTTP Relay, which strips all identifying metadata. This ensures that, from Truecaller’s perspective, all incoming queries look identical, completely anonymous, and encrypted end-to-end.

Oblivious HTTP Relay Diagram

From Truecaller's perspective, all incoming queries look the same, they come from Apple’s relay, and they're end-to-end encrypted. We have no insight into the user’s IP address, location, or device. This ensures user anonymity by design. If you're curious about the underlying tech, Apple’s implementation follows the OHTTP RFC 9458.

But there's a catch: because any device can technically use this relay, Truecaller needs a way to confirm that the request is coming from a real Truecaller user, without knowing who that user is. To solve this, we use a cryptographic protocol called Privacy Pass. More info on this is in RFC 9578.

Verifying Without Tracking

With Privacy Pass, the Truecaller app issues a set of single-use tokens to authenticated users. These tokens are like digital coins. When iOS needs to perform a query, it submits one of these tokens anonymously. The backend verifies that our service issued the token and that it hasn’t been used before, but it cannot trace the token back to any specific user.

Privacy Pass Without Relay Diagram

This method gives us what we need: confidence that the query comes from a legitimate user, and a guarantee that every token is used only once. At the same time, it prevents access to the user’s identity, location, and behavior. The only thing we know is that a valid token was used.

Privacy Pass With Relay Diagram

Final result after using both OHTTP Relay and Privacy Pass Issuance Protocol

2. Preserving the Query

The query refers to the phone number that iOS is trying to identify in real time. This number is essential for retrieving the correct caller identity from our database. However, if exposed, it could potentially reveal sensitive information about who the user interacts with others, or even allow unwanted profiling of user behavior. Preserving the query means ensuring that even the phone number being looked up remains private (hidden) from Truecaller, Apple, and any intermediaries involved in the request.

To fully preserve the privacy of the query, we need more than just encryption, we need a method that allows the service to process encrypted data without ever decrypting it, and a way for the client to know where to look without revealing what it's looking for.

Understanding Homomorphic Encryption

To fully understand how we preserve query privacy, it helps to understand the concept of homomorphic encryption through a real-world example.

Imagine you want to build a payroll app where users can calculate their net salary based on their gross salary. However, they don’t want to reveal their gross salary to your service. With homomorphic encryption, this becomes possible. You can encrypt the gross salary on the client side and send it to the server. The server then performs the tax and deduction calculations directly on the encrypted data. It sends back an encrypted result, which the client can decrypt to reveal their net salary. At no point does the server know the actual gross or net salary, it simply processes encrypted values.

Example of Homomorphic Encryption

Example of homomorphic encryption

This is the power of homomorphic encryption: it allows mathematical operations to be applied directly on encrypted data, and the decrypted result of that operation matches what would have been produced if the operation had been applied to the raw data.

Now let’s apply Homomorphic Encryption to preserve the confidentiality of Caller ID queries from the service.

We’ve already discussed how homomorphic encryption enables the mathematical processing of encrypted data. Now, let’s apply that idea to our problem.

There are two challenges we need to solve:

  1. We need to represent the data in a format that supports mathematical operations.
  2. The client must know exactly where to look in the data so it doesn't expose anything about the query.

To do this, the service must first share some structured information about the dataset with the client.

We begin by splitting our database into shards. For example, imagine we divide our dataset into 8 shards. Then, each shard is further divided into 21 pieces, these are our buckets. Each phone number is mapped to a single bucket using a deterministic allocation function. For example, the number +9999 will always land in a specific shard and bucket.

Phone Numbers Allocated in a Specific Shard and a Specific Bucket

Phone numbers are allocated in a specific shard and a specific bucket

The client receives metadata about how this data is structured. This allows it to know where any given number should be located. Suppose the number the client wants to query maps to shard 3, bucket 11.

Phone Numbers Allocated in a Specific Shard and a Specific Bucket - Part 2

We now serialize the shard into an array of buckets. To isolate the bucket we want, say bucket 11, we construct a bitmask array that contains a 1 at the index of bucket 11 and 0s elsewhere. When this bitmask is multiplied (via dot product) with the serialized shard array, the result is just the data in bucket 11.

This is a simplified example to illustrate the concept. In practice, the actual implementation involves more complexity, but the core idea remains the same: isolate the data you want without revealing what you’re asking for.

Example for a Bit-Mask of the Buckets

Example for a bit-mask of the buckets

This transformation allows us to apply mathematical operations, like multiplication, on structured encrypted data.

The client then builds this bitmask, encrypts it, and sends it along with an indication that it wants to query shard 3.

On the service side, we load shard 3, perform the encrypted dot product with the encrypted bitmask, and return the encrypted result.

Shard on Device

When the client receives this result, it decrypts it, and now it has the content of bucket 11. Throughout this process, the service never knows what number was queried or which bucket was targeted.

Shard on Device Processing

This is how we use PIR and homomorphic computation to preserve the content of the query itself, completing the privacy guarantees for Live caller ID lookup.

Summary: How Truecaller Preserves Privacy

Up to this point, we've explored the many layers of privacy preservation built into our Live Caller ID Lookup system. Let’s recap what Truecaller knows and, more importantly, what it doesn’t know:

  • We don’t know the user’s identity. The Privacy Pass Issuance Protocol completely hides who is making the request. We only know that it is a Truecaller user.
  • We don’t know the user’s IP address, location, or device details. The Oblivious HTTP Relay strips all metadata before the query reaches our servers.
  • We don’t know the phone number being searched. PIR and homomorphic encryption ensure the query itself is fully opaque.

All we know is that a Truecaller user (validated via Privacy Pass Protocol) queried a specific shard, for example, something possibly in shard 3. That’s it.

This strict separation of data and identity is what enables us to offer a truly privacy-first Caller ID experience.

3. Performance Considerations

Balancing Shard Size and Latency

Delivering real-time performance while preserving user privacy requires carefully balancing speed and confidentiality.

Let’s start with the structure of the shards. If each shard contains too few records, then even knowing which shard is being queried might expose information about the caller. On the other hand, if shards contain too many records, the query processing time will increase. It’s a classic trade-off between privacy and latency. We need enough data in each shard to make access patterns uninformative, but not so much that it degrades performance.

Understanding iOS Dual Queries

Another key aspect of performance is how iOS interacts with our system. When a call is received, iOS sends two requests: one for blocking and one for identity. The block query returns a single bit, either 0 or 1, to indicate whether the call should be blocked. This decision must be made quickly, before the phone even rings.

The identity query, in contrast, returns richer data like name, image, and category. Although it can tolerate a slightly longer delay, both queries are always sent. This is done intentionally to prevent behavioural fingerprinting, so the system can’t infer user preferences based on whether a block or identity lookup was performed.

This means every single call results in both lookups, whether or not blocking or identification is required. It’s a privacy-aware design, but it also adds a significant cost in terms of throughput.

Optimizing for Real-Time Performance

To mitigate this, performance tuning is essential. One highly recommended practice is to keep all shard data in memory. Doing so avoids expensive disk reads and allows encrypted queries to be executed immediately.

With shards resident in memory, query execution becomes CPU-bound, and sub-100ms latency becomes a realistic goal. This optimisation is critical to delivering a real-time user experience while upholding the privacy guarantees that Live caller ID lookup is built upon.

Apple’s PIR system ensures that these real-time lookups don’t compromise privacy, and for the first time, it allows us to offer a Live caller ID lookup experience on iOS that is both powerful and private.

What’s Next?

If you’re intrigued by how privacy-preserving technology can be applied to real-time communication, there’s a lot more to explore. You can:

At Truecaller, we’ve adopted these technologies by running Swift code at scale in our backend services. Leveraging the swift-homomorphic-encryption library in production allows us to process PIR queries securely and efficiently, helping us deliver private caller identification at global scale.

This journey from manual copy-paste workflows to Siri hacks and now to real-time, privacy-first architecture illustrates the evolution of Caller ID on iOS. With Live Caller ID Lookup in iOS 18, we're finally able to deliver the experience Truecaller was always meant to offer, providing Caller ID at the moment it matters most, while maintaining the highest standards of user privacy and trust.

Ahmed Alnaqah's Profile Picture

Ahmed Alnaqah

Jun 30, 202511 min read

iOS

Keep reading