# Data collection

:::note[In short]

This page lists the data the SDK handles, so you can complete Apple's App Store privacy details and Google Play's Data safety form. The SDK uses no data for advertising or tracking. With `proofUploadUrl` unset (the default) and the default direct transport mode, the SDK sends no coordinates to Octet. Country and state lookups send coordinates to the operating system's geocoder or, in a gateway mode, to the gateway. See [Location lookups](#location-lookups).

:::

## What the SDK handles

| Data | Leaves the device | Purpose | Linked to identity | Tracking |
|---|---|---|---|---|
| Precise location | To Octet: only if you set `proofUploadUrl` or use a gateway mode. See [Uploaded proofs](#uploaded-proofs) and [Location lookups](#location-lookups). | App functionality (location proofs) | No¹ | No |
| Coarse location | To Octet: yes, as region codes in the usage counters, and in uploaded proofs if you set `proofUploadUrl`. See [Usage counters](#usage-counters). | App functionality (country-level proofs), Analytics (region codes in the usage reports) | No¹ | No |
| Device ID (device fingerprint) | Yes: license activation and usage reports, and bound into proofs | App functionality, anti-fraud | No¹ | No |
| Product interaction (usage counters) | Yes, unless `telemetryEnabled = false` | Analytics: usage counters and per-proof events, no coordinates | No | No |
| Product interaction (daily usage record) | Yes, always: one record per device per day | Billing (active-device count), no location | No | No |

¹ The device fingerprint is a pseudonymous one-way hash, not an account identity, and the SDK does not link this data to a user identity. On iOS the SDK keeps it in the Keychain, so it survives an app reinstall. On Android it changes when the app is reinstalled. If your app associates proofs with a user account, classify the data accordingly on your own form.

The daily usage record is new in 3.0 and cannot be turned off. See [Metrics and usage reporting](/docs/mobile/concepts/metrics/) for what each report contains.

## Uploaded proofs

With `proofUploadUrl` set, the SDK uploads each proof it generates.

A proof that carries a [content commitment](/docs/mobile/concepts/content-commitments/) lists each item's key, content type, size, digest and optional locator, so these travel wherever the proof is uploaded. Choose keys and locators that don't reveal personal data. The values and salts never enter the proof. If you have the SDK [upload content](/docs/mobile/concepts/content-commitments/#uploading-content-to-your-storage), it goes to your own storage, never to Octet. Whatever you send to a verifier yourself, such as the content or the manifest, is your app's own data and belongs on your own form.

## Uploads to your storage

If an app uploads committed items, they go only to the storage location the app supplies, never to Octet.

While an upload is pending, the SDK keeps the salt and small items encrypted on the device, for at most 7 days, and deletes them once the upload ends. Uploaded files are your app's own data sent to your own server, so Octet collects nothing from them. Declare them on your own form, as you would any other data your app sends to your server.

## Location lookups

To check a country or US state, the SDK turns the device's coordinates into a country or state code. Where that lookup runs depends on the transport mode (see [Gateway routing](/docs/mobile/concepts/gateway-routing/)).

- **Direct mode (the default).** The SDK calls the operating system's geocoder: `CLGeocoder` on iOS, `Geocoder` on Android. Apple or Google receives the coordinates. The SDK sends no coordinates to Octet.
- **Gateway modes.** The SDK sends the coordinates to `{gateway}/ext/geo/reverse` instead of the operating system's geocoder. With your own gateway (`integratorGateway` on iOS, `INTEGRATOR_GATEWAY` on Android), your gateway receives them and forwards the request to Octet. In `octetGateway` (`OCTET_GATEWAY`) mode, Octet's gateway receives them. The request carries the full-precision latitude and longitude and the SDK's activation credential, so the receiver can link the lookup to the activated device.

Two other requests carry no location:

- **IP-based country hint (iOS only).** In direct mode, the iOS SDK requests the device's country from `ipwho.is`. The service sees the device's IP address and the standard `User-Agent` header that iOS adds to every request, which names your app, its build number and the iOS version. In a gateway mode the request goes to `{gateway}/ext/ipgeo/` instead. Set `TransportPolicy.thirdParty = .disable` to skip the lookup. Octet can also switch the lookup off through remote configuration. The Android SDK makes no IP lookup.
- **Border-map updates.** The SDK downloads updated border maps from `/ext/geo/borders/` on the host it already uses. These requests carry no location and no device data.

## Usage counters

The usage counters carry no coordinates. Octet also turns on additional usage reporting through remote configuration, without an app release, and it is on for all licenses. The usage reports also include:

- The ISO 3166 country or subdivision code of each region your app checks (for example `US` or `US-NY`), with the verdict.
- The country or subdivision code the device was resolved to by a background proof, whether or not your app asked about that region.
- How the location was found, for example GPS or the cell network.
- The proof's confidence and the time it took to produce, each reported as a range.
- The app's location-permission state: granted, denied, not determined or restricted.
- The category of an internal SDK error and where in the SDK it occurred.
- Which remote-configuration variant the device received, with a pseudonymous device key.

None of these reports carries coordinates.

Set `telemetryEnabled = false` to stop all usage counters and the additional reporting. To keep the basic usage counters but not the additional reporting, set `flagsEnabled = false`, which stops the SDK from receiving remote configuration. These requests continue with `telemetryEnabled = false`:

- **License heartbeat.** Renews the SDK's activation in the background.
- **Remote-configuration fetch.** Sends the SDK version, platform, OS version, your app ID and a pseudonymous device key.
- **Daily usage record.** See [Metrics and usage reporting](/docs/mobile/concepts/metrics/#daily-usage-record).

## iOS: privacy manifest

The xcframework bundles a `PrivacyInfo.xcprivacy` privacy manifest. Xcode adds it to your app's privacy report at build time, so no action is needed beyond reviewing it alongside your own disclosures. It declares:

- **Collected data types.** Precise location, coarse location and device ID, each for App Functionality. Coarse location also for Analytics, because of the region codes in the usage reports. The manifest in SDK 3.0.0 left that out, so if you added it to your App Store privacy details yourself, keep it. Product interaction, for Analytics (the usage counters) and Other (the daily usage record, used for billing). Every type is declared as not linked to the user and not used for tracking.
- **Tracking.** None, and no tracking domains.
- **Required-reason APIs.** System boot time, for the SDK's anchored license clock, and `UserDefaults`, for a one-time device-ID migration.

When you upgrade, re-check your App Store privacy details: from 2.x, so they include product interaction for the Other purpose, and from 3.0, so they include coarse location for Analytics.

## Android: Data safety form

Android has no privacy manifest inside the library, so the table above is the statement to use for your app's Play Console Data safety form. The SDK's permissions merge into your manifest automatically. See [Prerequisites](/docs/mobile/getting-started/prerequisites/) for the permission list.

## Where to go next

- [Metrics and usage reporting](/docs/mobile/concepts/metrics/). What the counters and the daily record contain.
- [Gateway routing](/docs/mobile/concepts/gateway-routing/). Which hosts the SDK contacts, and how to route them through one domain.
