Deeplinkly
All articles
Device IdentityMobile Development

How to Find a Device ID on iOS and Android

Published May 3, 2026·Updated August 5, 2026·10 min read·By Sahil Asopa
Mobile apps using identifiers with different scopes and reset rules

There is no single universal “device ID” that every mobile app can read. iOS and Android provide several identifiers, each designed for a particular purpose and scope. The correct answer depends on whether you need an app-install ID, an identifier shared across your own apps, an advertising ID, or a support value visible to a user.

The safest rule is simple: choose the narrowest resettable identifier that solves the stated use case. Do not collect IMEI, serial number, MAC address, or another hardware identifier for ordinary analytics or attribution.

Quick answer: which identifier should you use?

Use caseiOS choiceAndroid choiceImportant limit
Identify one app installationApp-generated UUIDApp-generated UUID or Firebase Installation IDResets when app data is removed or the app is reinstalled, depending on storage
Analytics across your own appsIDFVApp Set IDMust stay inside the permitted first-party scope
Advertising and cross-company measurementIDFA after ATT authorizationGoogle Advertising ID when availableRespect user choice, platform policy, disclosures, and applicable law
Diagnose a support caseApp-generated support IDApp-generated support IDPrefer a value that reveals no platform advertising identifier
Verify app authenticity or abuseApp Attest or DeviceCheck where appropriatePlay Integrity APIThese are attestation signals, not general-purpose tracking IDs

If the purpose is “count active installations,” an app-instance ID is usually enough. If the purpose is “connect activity after sign-in,” use your own account ID after authentication. If the purpose is advertising, use the platform advertising framework and handle unavailable states without bypassing the user’s choice.

What a device identifier actually identifies

Before retrieving any ID, document four properties:

An identifier is not necessarily a person. One person may use several devices, several profiles on one device, or reinstall an app. A family may share one device. An advertising ID can reset. Treating any device-scoped value as a permanent customer key creates duplicate and merged profiles.

iOS identifiers

IDFV: Identifier for Vendor

Apple’s identifierForVendor returns a UUID that identifies a device to the app’s vendor. Apps from the same vendor on the same device normally receive the same value. Apple says the value can change after the user removes all apps from that vendor and later reinstalls one; it can also differ for some development or ad-hoc installations. Immediately after a restart, the value may be nil until the user unlocks the device.

Retrieve it in Swift:

swift
import UIKit

func currentVendorIdentifier() -> String? {
    UIDevice.current.identifierForVendor?.uuidString
}

Use IDFV for permitted first-party analytics across your own apps. Apple states that ATT is not required merely for this first-party analytics use, but IDFV must not be combined with other data to track someone across apps or websites owned by other companies.

Do not make IDFV your database primary key. Store it as a changeable signal and use an authenticated account ID for account continuity.

IDFA: Identifier for Advertisers

IDFA is available through AdSupport for advertising-related use. On iOS 14.5 and later, an app must use AppTrackingTransparency when its activity meets Apple’s definition of tracking or it wants access to the advertising identifier. Without authorization, the advertising identifier is all zeros and the app may not substitute another identifier to continue the prohibited tracking.

Check the authorization state before reading the value:

swift
import AdSupport
import AppTrackingTransparency

func authorizedAdvertisingIdentifier() -> String? {
    guard ATTrackingManager.trackingAuthorizationStatus == .authorized else {
        return nil
    }

    let value = ASIdentifierManager.shared().advertisingIdentifier
    let zero = "00000000-0000-0000-0000-000000000000"
    return value.uuidString == zero ? nil : value.uuidString
}

Request ATT only at a moment where the purpose is clear. Add NSUserTrackingUsageDescription, explain the use accurately, and ensure no tracking starts before authorization. Do not gate unrelated app functionality or reward a user for accepting the system prompt.

App-generated installation ID

For installation-scoped analytics or support, generate a random UUID and store it in normal app storage:

swift
import Foundation

let installationID = UUID().uuidString

Persist it in UserDefaults or an app database when reset-on-reinstall behavior is desired. Keychain persistence can survive reinstall in some circumstances and changes the privacy and lifecycle expectation, so do not use Keychain merely to rebuild a deleted identity.

Android identifiers

App-generated UUID or Firebase Installation ID

Google recommends a Firebase Installation ID or a privately stored GUID for most non-advertising use cases. A local GUID can be created in Kotlin:

kotlin
import java.util.UUID

val installationId = UUID.randomUUID().toString()

Generate it once, persist it in app-private storage, and rotate it when the user invokes a reset or deletion control. Clearing app data or reinstalling should create a new installation identity unless your clearly documented product requirement says otherwise.

App Set ID

App Set ID supports analytics or fraud-prevention use cases across apps owned by the same Google Play developer account. Play-installed apps normally receive developer scope; apps installed another way or on devices without suitable Google Play services may receive app scope.

The value can reset when the last app in the set is uninstalled, after 13 months without access by the app set, after a factory reset, or after some SDK scope changes. Google says to retrieve it when needed rather than rely on a permanently cached value.

kotlin
val client = AppSet.getClient(applicationContext)

client.appSetIdInfo.addOnSuccessListener { info ->
    val id = info.id
    val scope = info.scope
    // Send only if this use is covered by your documented purpose.
}

App Set ID is not an advertising identifier. Google’s guidance limits it to non-advertising purposes such as first-party analytics and fraud prevention.

ANDROID_ID

On Android 8.0 and later, Settings.Secure.ANDROID_ID is a 64-bit value represented as a hexadecimal string and scoped to the combination of app-signing key, user, and device. It can change after a factory reset or signing-key change. Multiple Android users on the same physical device receive different values.

kotlin
import android.provider.Settings

val androidId = Settings.Secure.getString(
    contentResolver,
    Settings.Secure.ANDROID_ID
)

ANDROID_ID is not the right substitute for an unavailable advertising ID. Use it only when its scope and lifetime fit a non-advertising purpose and your disclosures cover the use.

Google Advertising ID

Google’s advertising ID is user-resettable and user-deletable. Google Play policy requires apps to use it, when available, instead of other device identifiers for advertising purposes. When a user deletes it, attempts to access it return zeros. Apps targeting Android 13 or later must declare the com.google.android.gms.permission.AD_ID permission when they use the Google Play services advertising ID; otherwise the returned value is zeroed.

Retrieval is asynchronous and can fail when Google Play services is missing or unavailable. Do it off the main thread and treat every unavailable, deleted, zero, or limited state as normal:

kotlin
val info = AdvertisingIdClient.getAdvertisingIdInfo(applicationContext)
val advertisingId = info.id
val limited = info.isLimitAdTrackingEnabled

Do not bridge a reset by linking the new advertising ID to the old one through a persistent identifier or fingerprint without the explicit permission required by policy.

Identifier selection flow based on purpose, scope, and user choice

How users can find a support identifier

End users normally cannot see IDFV, App Set ID, or an app’s private installation UUID in system settings. If support needs a stable value, add an in-app screen such as Settings → Help → Diagnostic ID.

A good diagnostic ID should:

For Android’s advertising ID, the settings path varies by manufacturer and OS version. Google documents a common route under Settings → Privacy → Ads, where users can reset or delete the advertising ID. Do not instruct users to install an unknown “device ID” utility.

Identifier formats are not identity guarantees

Many values use UUID notation such as 38400000-8cf0-11bd-b23e-10b96e40000d; ANDROID_ID is typically a hexadecimal representation of a 64-bit number. Format validation only proves the string resembles an expected value. It does not prove:

Validate source, scope, permission state, and timestamps alongside syntax.

A safe identifier data model

Do not put every signal into a single device_id column. Use explicit fields:

FieldExample purpose
installation_idOne app installation
account_idSigned-in product identity
identifier_typeIDFV, App Set ID, advertising ID, or none
identifier_scopeInstall, vendor, developer, or advertising
authorization_stateAuthorized, denied, restricted, not determined, unavailable
observed_atWhen the app read the value
resettableWhether the platform/user can rotate it
source_platformiOS or Android

Store only what you need. Limit access, encrypt identifiers in transit and at rest, define retention, and propagate deletion requests to processors. Hashing an identifier does not automatically make it anonymous; a stable hash can still be linkable.

Common mistakes

That last one is worth checking in your measurement vendor, not just your own code. Deeplinkly attributes from deterministic signals — Play Install Referrer, Meta Install Referrer, and SKAdNetwork postbacks — and reports an install as unattributed when none is present, rather than fingerprinting the device to manufacture a match. If a vendor's attributed total is suspiciously close to your install total, ask which of the two it is doing.

Final decision checklist

  1. Write the exact purpose before selecting an identifier.
  2. Prefer account, installation, vendor, or developer scope over cross-app scope.
  3. Implement unavailable and reset states as normal paths.
  4. Do not bridge resets or denied permission with a hidden identifier.
  5. Keep advertising identifiers out of logs, crash messages, and support screens.
  6. Review every third-party SDK’s collection and disclosure behavior.
  7. Test reinstall, data clearing, account change, ATT denial, ad-ID deletion, and devices without Google Play services.

The right way to “know a device ID” is not to find the longest-lived value. It is to choose the smallest, most transparent identifier that performs one legitimate job and can change when the platform or user says it should.

Primary sources

Back to all articles© 2026 Deeplinkly

Related guides