
I researched whether there are retrievable identifiers in iOS similar to Android's SSAID
This page has been translated by machine translation. View original
In iOS app development, there may be a need to identify devices or users. A question I often hear from Android developers is: "Is there an iOS equivalent to Android's SSAID (Android ID) that persists after app reinstallation?"
The short answer is: iOS does not have an officially supported identifier that persists after app reinstallation. This is intentional, due to Apple's privacy-first design.
This article explains in detail the types of identifiers available in iOS, their acquisition conditions, when they change, and how they differ from Android.
What is Android SSAID?
Let me briefly touch on Android's SSAID (Settings.Secure.ANDROID_ID or Android ID), which serves as our point of comparison.
SSAID is a device identifier available in Android 8.0 and later. Its main feature is that the same ID can be retrieved even after reinstalling an app. It doesn't require user consent, and different IDs are generated for each app and signing key. The ID persists unless the device is reset or the signing key changes.
This characteristic of "no user consent required" and "same ID after reinstallation" doesn't exist in iOS.
List of Available Identifiers in iOS
Here's a table summarizing the main identifiers available in iOS.
| Identifier | Scope | User Permission | After Reinstallation | Main Use |
|---|---|---|---|---|
| UDID | Entire device | Not required | - | Deprecated |
| IDFA | Entire device | ATT permission required[1] | Can be changed | Ad tracking |
| IDFV | Per vendor | Not required | Changes[2] | Analytics/Authentication |
| DeviceCheck | Entire device | Not required | Persistent (2 bits) | Fraud detection |
| App Attest | Per app | Not required | Persistent | Integrity verification |
| Firebase FID | Per app | Not required | Changes | Internal Firebase use |
| APNs token | Per app | Not required | May change | Push notifications |
| Keychain UUID | Configurable | Not required | Persistent (unofficial) | Custom uses |
1. UDID (Deprecated)
UDID (Unique Device Identifier) was a device-specific identifier that once existed. It became deprecated in iOS 5 (2011), was banned from the App Store in May 2013, and its API was completely removed in iOS 7.
NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];
It was discontinued due to abuse by ad networks for cross-app tracking, invasion of user privacy, and the lack of a way for users to reset their IDs. Currently, apps using UDID are immediately rejected in App Store reviews. The discontinuation was announced in Apple Developer News.
After UDID was deprecated, using MAC addresses was temporarily a workaround, but since iOS 7, it returns a fixed value, making it unusable as of 2025.
2. IDFV (Identifier for Vendor)
IDFV is currently the most commonly used identifier, available without user consent or ATT permission. It's shared among apps from the same vendor (developer).
let idfv = UIDevice.current.identifierForVendor?.uuidString
// Example: 95290AB7-FC58-4CC9-8B86-F8F38505B512
If a user deletes all apps from the same vendor, the IDFV resets. This means it doesn't have the complete persistence of Android's SSAID. If a vendor has only one app released, the IDFV changes after reinstallation.
IDFV uniqueness is determined by the first two components of the Bundle Identifier (e.g., com.example). For detailed specifications and timing of changes, please refer to Apple's official documentation.
3. IDFA (Identifier for Advertisers)
IDFA is an advertising identifier, but since iOS 14.5, App Tracking Transparency (ATT) permission is mandatory. You need to set NSUserTrackingUsageDescription in Info.plist.
import AdSupport
import AppTrackingTransparency
ATTrackingManager.requestTrackingAuthorization { status in
if status == .authorized {
let idfa = ASIdentifierManager.shared().advertisingIdentifier
print("IDFA: \(idfa.uuidString)")
}
}
If the user doesn't allow tracking, a zero value (00000000-0000-0000-0000-000000000000) is returned. The ATT consent dialog is displayed only once per app, and according to Flurry's research, the overall permission rate is about 25-35%. You should assume you can't obtain it from all users.
Since IDFA can be reset by users at any time, Apple's documentation recommends accessing it for each use rather than storing it. For details, refer to Apple's official documentation.
4. DeviceCheck
DeviceCheck is a framework that allows developers (vendors) to store 2 bits (4 states) of data on Apple's servers per device. Note that these 2 bits are shared across multiple apps from the same developer. Data persists even after app deletion, but this is an API for state storage, not an identifier.
import DeviceCheck
let tokenData = try await DCDevice.current.generateToken()
let token = tokenData.base64EncodedString()
// Send this token to your server, which interacts with the Apple API
The generated token is temporary, with a different value returned each time. Since it requires server-side interaction with Apple's API to read and write the 2 bits, it can't be used to uniquely identify a device. Its main uses are fraud detection and one-time benefit management. For details, see Apple's official documentation.
5. App Attest
App Attest is a framework for verifying app integrity (iOS 14+). It generates cryptographic keys in the Secure Enclave and allows Apple to certify that an app instance is legitimate.
import DeviceCheck
let service = DCAppAttestService.shared
guard service.isSupported else { return }
let keyId = try await service.generateKey()
let attestation = try await service.attestKey(keyId, clientDataHash: serverChallenge)
// Verify attestation on the server
Like DeviceCheck, server-side verification is mandatory, and it doesn't work in simulators. Its main uses are API protection and preventing unauthorized access from tampered apps. It's not designed to be used as an identifier.
The difference from DeviceCheck is that DeviceCheck "stores device state in 2 bits," while App Attest "proves that an app hasn't been tampered with." They're often used complementarily. For details, see Apple's official documentation.
6. Firebase Installation ID (FID)
This is an automatically generated identifier when using Firebase.
import FirebaseInstallations
let id = try await Installations.installations().installationID()
print("Firebase Installation ID: \(id)")
FID changes when the app is reinstalled or cache is cleared, so it's not a substitute for SSAID. Also, as stated in the Firebase documentation, it's deleted on the backend if inactive for 270 days. It's an identifier used internally by Firebase and is not suitable for persistent device identification.
7. APNs Device Token
This is a token for push notifications. It's prohibited to use it for tracking purposes.
// AppDelegate.swift
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("APNs Token: \(token)")
}
Apple's official documentation recommends "not caching the device token locally, but obtaining it from the system when needed" because the token changes during OS updates or device restoration.
8. Keychain UUID
This method involves generating your own UUID and storing it in the Keychain. While technically possible, it's not an official method, so I'll omit the implementation details.
There are several issues with this approach. First, it's not an official API and may stop working in the future due to Apple's specification changes. Also, there's a risk of App Store rejection if it's deemed to be for tracking purposes. Furthermore, depending on the kSecAttrAccessible setting, it might be carried over in device backups.
In iOS 10.3 Beta, Apple once attempted a specification change to "delete Keychain data when the app is deleted." The Apple Developer Forums stated: "This is an intentional change in iOS 10.3 to protect user privacy. Information that can identify a user should not be left on the device after the app that created that information is deleted." However, this change was withdrawn in Beta 7, and the original behavior (Keychain data is not deleted) was restored.
As of December 2025 (iOS 26.1), this behavior continues, but Apple has stated in another thread that "the Keychain documentation has never specified what happens in this case" and "the persistence of Keychain items after app deletion was never part of the API contract, but always an implementation detail." In other words, "not being deleted after reinstallation" is not a specification, but just how it has behaved historically. If you depend on this behavior, you need to design your app considering that it may change in the future.
Why Doesn't iOS Have an SSAID Equivalent?
Reading Apple's privacy policy and App Store review guidelines, this appears to be intentional design.
Deleting an app is a clear expression of the user's intention: "I want to cut ties with this app." An identifier that can track users after reinstallation goes against this intention. Also, persistent IDs can be abused by ad networks for cross-app tracking. IDFA exists, but since iOS 14.5, it requires ATT permission and can be reset at any time, ensuring user choice.
Apple prioritizes user control, with a design philosophy that respects the ability to reset ad IDs from the settings app, the right to completely delete data by deleting the app, the so-called "right to be forgotten."
What if You Absolutely Need a Persistent ID?
The most appropriate approach is to encourage users to create accounts. The login method should be as simple as possible, so using Sign in with Apple or email/phone number authentication is recommended. While generating your own ID and storing it in the Keychain is another option, as mentioned earlier, it works in the short term but carries long-term risks.
Don't Forget to Address Privacy Manifests
Throughout this article, I've touched on Apple's privacy-first design philosophy. When developing iOS apps, it's essential not to forget about "Privacy Manifests." You must clearly disclose to users what permissions your app needs and for what purposes it uses various data.
Since iOS 17, all apps and SDKs need to declare their use of identifiers in the PrivacyInfo.xcprivacy file. For details, please refer to the article I wrote a while back:
However, as of December 2025, while apps incorporating PrivacyInfo.xcprivacy are strictly checked, apps without it still pass review. I don't think the privacy manifest system will be abolished. To avoid sudden rejection of app reviews, it's best to address this for any non-compliant apps.
Summary
There is no SSAID equivalent in iOS. This is a result of Apple's privacy-first design and is intentionally not provided.
When porting Android designs that depend on SSAID to iOS, implementing a user account system is the most reliable approach. As mentioned earlier, Keychain UUID works in the short term but carries long-term risks.
Here's a summary of common use cases and which identifiers to use:
| Use Case | Recommended Identifier |
|---|---|
| Persistence after reinstallation | ❌ Doesn't officially exist → User account recommended |
| In-app analytics | ✅ IDFV |
| Ad tracking | ✅ IDFA (ATT permission required) |
| Fraud detection | ✅ DeviceCheck |
| App integrity verification | ✅ App Attest |
iOS's privacy model is fundamentally different from Android's. Rather than saying "it's inconvenient that there's no SSAID equivalent in iOS," a shift in thinking to "design according to iOS's privacy model" is necessary.
Since this article primarily deals with iOS, I haven't gone into detail, but even on Android, Advertising ID is recommended for advertising purposes, App Set ID for app analytics, and FID or GUID for non-advertising purposes, suggesting a move away from persistent identifiers.
Designs that respect user privacy will gain user trust in the long run and lead to app success. Please choose the appropriate identifier for your purpose.
References
Job Information: Classmethod is Recruiting iOS Engineers
Starbucks Digital Technology Department is looking for engineers who can develop iOS applications. We're waiting for applications from people who want to work together while sharing new iOS support on misc-ios and more!
Additionally, we're recruiting iOS/Android lead engineers in the manufacturing sector. Let's talk about mobile app development together!


