> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fingerprint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Smart Signals reference

> Fingerprint is not just an identity platform; it also helps fight fraud by providing actionable device intelligence called Smart Signals. This page contains the reference information for individual Smart Signal components and their applications.

export const Availability = ({platforms = [], plans = []}) => {
  const platformConfig = {
    ios: {
      label: "iOS",
      backgroundColor: "rgb(107, 114, 128)"
    },
    android: {
      label: "Android",
      backgroundColor: "rgb(55, 160, 76)"
    },
    browser: {
      label: "Browser",
      backgroundColor: "rgb(47, 148, 215)"
    }
  };
  const planLabels = {
    free: "Free",
    "pro-plus": "Pro Plus",
    enterprise: "Enterprise"
  };
  const planClass = "text-white px-2 py-1 rounded-md";
  const planBackgroundColor = "rgb(255, 94, 36)";
  return <div className="flex flex-wrap items-center gap-2">
      {platforms.map(platform => {
    const normalized = String(platform).toLowerCase();
    const config = platformConfig[normalized];
    return <span key={`platform-${normalized}`} className="text-white px-2 py-1 rounded-md" style={config ? {
      backgroundColor: config.backgroundColor
    } : undefined}>
            {config?.label ?? platform}
          </span>;
  })}
      {plans.map((plan, index) => {
    const normalized = String(plan).toLowerCase();
    return <span key={`plan-${normalized}`} className={`${planClass}${index === 0 ? " ml-4" : ""}`} style={{
      backgroundColor: planBackgroundColor
    }}>
            {planLabels[normalized] ?? plan}
          </span>;
  })}
    </div>;
};

Smart Signals are actionable device intelligence insights you can use to improve your fraud prevention logic. For general information about Smart Signals availability and usage, see [Smart Signals Introduction](/docs/smart-signals-introduction).

Some signals are available on [all platforms](#smart-signals-common-for-browsers-and-mobile-devices), while others are specific only to [browsers](#browser-smart-signals) or [mobile devices](#smart-signals-for-mobile-devices).

## Smart Signals common for browsers and mobile devices

These Smart Signals are available on all platforms.

### Suspect Score

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

Suspect Score combines all Smart Signals into a weighted integer value based on their global probability. To read more about the weights and the mechanisms, see [Suspect score](/docs/suspect-score).

```json Suspect Score theme={"theme":"github-dark-dimmed"}
"suspect_score": 10
```

### Velocity Signals

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

Velocity Signals sum [key data points](https://fingerprint.com/blog/product-update-velocity-signals/) at three distinct intervals: 5 minutes, 1 hour, and 24 hours as follows:

[`Per visitorID`](https://fingerprint.com/blog/product-update-velocity-signals/#per-visitorid) :

* Number of distinct IP addresses linked to the `visitor_id`
* Number of distinct countries associated with a `visitor_id`
* Number of distinct `linked_id` associated with the `visitor_id`
* Number of events linked to the `visitor_id`

[`Per linkedID`](https://fingerprint.com/blog/product-update-velocity-signals/#per-linkedid) :

* Number of distinct IPs associated with the `linked_id`
* Number of distinct `visitor_id` associated with the `linked_id`

[`Per IP`](https://fingerprint.com/blog/product-update-velocity-signals/#per-ip) :

* Number of events linked to an IP address

<CodeGroup>
  ```json Distinct IPs per visitorID theme={"theme":"github-dark-dimmed"}
  "velocity": {
      "distinct_ip": {
        "5_minutes": 1,
        "1_hour": 1,
        "24_hours": 1 // For visitors exceeding 10,000 in 24 hours, we will omit 5_minutes and 1_hour, returning only 24h as 10,000.
      }
    }
  ```

  ```json Distinct countries per visitorID theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "distinct_country": {
        "5_minutes": 1,
        "1_hour": 2,
        "24_hours": 2 // For visitors exceeding 10,000 in 24 hours, we will omit 5_minutes and 1_hour, returning only 24h as 10,000.
      }
    }
  ```

  ```json Distinct linkedIDs per visitorID theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "distinct_linked_id": {
      "5_minutes": 1,
      "1_hour": 5,
      "24_hours": 5 // For visitors exceeding 10,000 in 24 hours, we will omit 5_minutes and 1_hour, returning only 10,000 for 24h.
    }
  }
  ```

  ```json Events per visitorID theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "events": {
      "5_minutes": 3,
      "1_hour": 5,
      "24_hours": 23 // For visitors exceeding 10,000 in 24 hours, we will omit 5_minutes and 1_hour, returning only 10,000 for 24h.
    }
  }
  ```

  ```json Distinct IPs per linkedID theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "distinct_ip_by_linked_id": {
      "5_minutes": 1,
      "1_hour": 5,
      "24_hours": 5 // For visitors exceeding 10,000 in 24 hours, we will omit 5_minutes and 1_hour, returning only 10,000 for 24h.
    }
  }
  ```

  ```json Distinct visitorIDs per linkedID theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "distinct_visitor_id_by_linked_id": {
      "5_minutes": 1,
      "1_hour": 5,
      "24_hours": 5 // For visitors exceeding 10,000 in 24 hours, we will omit 5_minutes and 1_hour, returning only 10,000 for 24h.
    }
  }
  ```

  ```json Events per IPv4 theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "ip_events": {
      "5_minutes": 1,
      "1_hour": 5,
      "24_hours": 5
    }
  }
  ```

  ```json No Relevant Data - example theme={"theme":"github-dark-dimmed"}
  "velocity": {
    "distinct_visitor_id_by_linked_id": { // This will be an empty object if there is no data to present
    }
  }
  ```
</CodeGroup>

For high-activity visitors generating over 10,000 unique distinct values to track within a 24-hour window, we will omit the aggregation of 5-minute and 1-hour results, returning an accurate count up to 10,000 for a 24 hour period. This limit does not apply to number of events by visitor ID or events by IP.

### IP Geolocation

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

The IP Geolocation signal provides an estimated physical location of the client, along with network metadata to support fraud detection and traffic analysis

**Location data**

The location is composed of latitude and longitude, along with an accuracy radius ranging from 5 to 1000 km. These coordinates define the center of a circle that can be mapped. The postal code has the weakest level of confidence and this mappable area would rarely fall within a single postal code.

Latitude and longitude values are mapped to the nearest public park or body of water to avoid implying a specific residential or business location.

**Network data**

IP Geolocation also includes network and ownership metadata, such as:

* ASN information
* Organization type (ISP, Hosting, Business, Education, Government)
* Datacenter indicator

This data can be used to group IP ranges, apply protection or allowlisting rules, and better understand the network context of incoming traffic

<CodeGroup>
  ```json IP Geolocation theme={"theme":"github-dark-dimmed"}
  "ip_info": {
    "v4": {
      "address": "94.142.239.124",
      "geolocation": {
        "accuracy_radius": 20,
        "latitude": 50.05,
        "longitude": 14.4,
        "postal_code": "150 00",
        "timezone": "Europe/Prague",
        "city_name": "Prague",
        "country_code": "CZ",
        "country_name": "Czechia",
        "continent_code": "EU",
        "continent_name": "Europe",
        "subdivisions": [
          {
            "iso_code": "10",
            "name": "Hlavni mesto Praha"
          }
        ]
      },
      "asn": "7922",
      "asn_name": "COMCAST-7922",
      "asn_network": "73.136.0.0/13",
      "asn_type": "isp",
      "datacenter_result": true,
      "datacenter_name": "DediPath"
    },
    "v6": {
      "address": "2001:db8:3333:4444:5555:6666:7777:8888",
      "geolocation": {
        "accuracy_radius": 5,
        "latitude": 49.982,
        "longitude": 36.2566,
        "postal_code": "10112",
        "timezone": "Europe/Berlin",
        "city_name": "Berlin",
        "country_code": "DE",
        "country_name": "Germany",
        "continent_code": "EU",
        "continent_name": "Europe",
        "subdivisions": [
          {
            "iso_code": "BE",
            "name": "Land Berlin"
          }
        ]
      },
      "asn": "6805",
      "asn_name": "Telefonica Germany",
      "asn_network": "2a02:3100::/24",
      "asn_type": "isp",
      "datacenter_result": false,
      "datacenter_name": ""
    }
  }
  ```
</CodeGroup>

### Proxy Detection

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

Detects whether the IP address is used by a **residential** or a **data center** proxy provider using a combination of internal and third-party data sources.

* Data center proxies are typically hosted in data centers and connect with HTTPS or SOCKS5 protocols
* Residential proxies route internet traffic through real user devices with legitimate ISP-issued IP addresses, making requests appear as if they originate from ordinary end-users. They are commonly used for fraudulent activity, such as account takeovers or illegal content scraping
* `proxy_confidence` is a field that comes with the detection result. If a proxy is **not detected**, `confidence` is `high`. If it's **detected**, can be `low`, `medium`, or `high`. Proxy IPs with high levels of recent activity will get a high confidence
* `proxy_details` is an object with additional information about proxy IPs that we return when we detect any proxy type. It always contains the `proxy_type` field that can be either `residential` or `data_center`. It may also have an optional `last_seen_at` timestamp field that contains a timestamp of when we last saw this IP show proxy-like behavior. The timestamp is in ISO 8601 format with an hourly resolution and is always in UTC.

<Warning>Proxy detection is currently in beta</Warning>

<CodeGroup>
  ```json Proxy not detected theme={"theme":"github-dark-dimmed"}
  "proxy": false,
  "proxy_confidence": "high"
  ```

  ```json Residential proxy detected theme={"theme":"github-dark-dimmed"}
  // will return true in case the device IP was recently used by a known residential proxy provider
  "proxy": true,
  // can also be "medium" for moderately active proxy IPs,
  // or "high" for recently active proxy IPs
  "proxy_confidence": "low",
  "proxy_details": {
    "proxy_type": "residential",
    "provider": "BrightData"
  }
  ```

  ```javascript Data center proxy detected theme={"theme":"github-dark-dimmed"}
  // will return true in case the device IP belongs to a known data center proxy
  "proxy": true,
  // can also be "medium" for moderately active proxy IPs,
  // or "high" for recently active proxy IPs
  "proxy_confidence": "low",
  "proxy_details": {
    "proxy_type": "data_center",
    "provider": "Massive",
    // this field is optional and is returned when the time of last proxy activity is known
    "last_seen_at": 1708102555327
  }
  ```
</CodeGroup>

### IP Blocklist Matching

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

The feature uses a combination of internal and 3rd-party IP databases to determine whether:

* `tor` payload : The IP address is a known Tor exit node. Do not utilize active Tor detection mechanisms.
* `ipBlocklist.details`payload : The IP address has been part of a network attack, email spam attack or if 75% or more of events from an IP are flagged as [replayed](/docs/protecting-from-payload-replay-attacks) within the last 7 days.

<CodeGroup>
  ```json Blocklist theme={"theme":"github-dark-dimmed"}
  "ip_blocklist": {
    "email_spam": false,
    "attack_source": false,
    "tor_node": false
  }
  ```
</CodeGroup>

### High-Activity Device

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

Detects if the device is among the top 2% of devices most frequently identified by your Fingerprint application.**High-Activity Device** searches for spikes in traffic connected to a single `visitorID`. It computes the amount of visits **in the past 24 hours** for each `visitorID` **every five minutes** and reports `high_activity_device` as `true` if the number of visits for the past 24 hours surpasses a threshold.

#### High-Activity Device Threshold

The threshold is calculated for each customer separately and is determined through **a normal traffic distribution**. If the returned `visitorID` does **more requests than 98% of other daily visitors**, the High-Activity Smart Signal returns a positive result. If the traffic doesn't pass the threshold, `high_activity_device` returns `false`.

<CodeGroup>
  ```json High Activity - Detected theme={"theme":"github-dark-dimmed"}
  "high_activity_device": true
  ```

  ```json Normal Activity theme={"theme":"github-dark-dimmed"}
  "high_activity_device": false
  ```
</CodeGroup>

### Raw Device Attributes

<Availability platforms={["browser", "ios", "android"]} plans={["enterprise"]} />

Raw Device Attributes expose low-level data points describing the browser, device, and rendering environment, collected by our JavaScript agent and native iOS/Android SDKs.

<Accordion title="JSON">
  ```json theme={"theme":"github-dark-dimmed"}
  "raw_device_attributes": {
    "font_preferences": {
      "default": 73.78125,
      "serif": 73.78125,
      "sans": 72.0078125,
      "mono": 66.53125,
      "apple": 73.78125,
      "min": 4.6171875,
      "system": 73.046875
    },
    "emoji": {
      "font": "Times",
      "width": 1280,
      "height": 18.5,
      "top": 9.5,
      "bottom": 28,
      "left": 8,
      "right": 1288,
      "x": 8,
      "y": 9.5
    },
    "fonts": [
      "Arial Unicode MS",
      "Gill Sans",
      "Helvetica Neue",
      "Menlo"
    ],
    "device_memory": 8,
    "timezone": "America/New_York",
    "canvas": {
      "winding": true,
      "geometry": "db3c1462576a399a03ae93d0ab9eb5c4",
      "text": "70c3d3f7eb4408dc37a6bf8af1c51029"
    },
    "languages": [
      [
        "en-US"
      ]
    ],
    "webgl_extensions": {
      "context_attributes": "6b1ed336830d2bc96442a9d76373252a",
      "parameters": "ea118c48e308bc4b0677118bbb3019ec",
      "shader_precisions": "f223dfbcd580cf142da156d93790eb83",
      "extensions": "57233d7b10f89fcd1ff95e3837ccd72d",
      "extension_parameters": "86a8abb36f0cb30b5946dec0c761d042",
      "unsupported_extensions": []
    },
    "webgl_basics": {
      "version": "WebGL 1.0 (OpenGL ES 2.0 Chromium)",
      "vendor": "WebKit",
      "vendor_unmasked": "Google Inc. (Apple)",
      "renderer": "WebKit WebGL",
      "renderer_unmasked": "ANGLE (Apple, ANGLE Metal Renderer: Apple M4, Unspecified Version)",
      "shading_language_version": "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)"
    },
    "screen_resolution": [
      1710,
      1107
    ],
    "touch_support": {
      "touch_event": false,
      "touch_start": false,
      "max_touch_points": 0
    },
    "architecture": 127,
    "cookies_enabled": true,
    "hardware_concurrency": 10,
    "date_time_locale": "en-US",
    "vendor": "Google Inc.",
    "color_depth": 30,
    "platform": "MacIntel",
    "session_storage": true,
    "local_storage": true,
    "audio": 124.04347745512496,
    "plugins": [
      {
        "name": "PDF Viewer",
        "description": "Portable Document Format",
        "mimeTypes": [
          {
            "type": "application/pdf",
            "suffixes": "pdf"
          },
          {
            "type": "text/pdf",
            "suffixes": "pdf"
          }
        ]
      },
      {
        "name": "Chrome PDF Viewer",
        "description": "Portable Document Format",
        "mimeTypes": [
          {
            "type": "application/pdf",
            "suffixes": "pdf"
          },
          {
            "type": "text/pdf",
            "suffixes": "pdf"
          }
        ]
      },
      {
        "name": "Chromium PDF Viewer",
        "description": "Portable Document Format",
        "mimeTypes": [
          {
            "type": "application/pdf",
            "suffixes": "pdf"
          },
          {
            "type": "text/pdf",
            "suffixes": "pdf"
          }
        ]
      },
      {
        "name": "Microsoft Edge PDF Viewer",
        "description": "Portable Document Format",
        "mimeTypes": [
          {
            "type": "application/pdf",
            "suffixes": "pdf"
          },
          {
            "type": "text/pdf",
            "suffixes": "pdf"
          }
        ]
      },
      {
        "name": "WebKit built-in PDF",
        "description": "Portable Document Format",
        "mimeTypes": [
          {
            "type": "application/pdf",
            "suffixes": "pdf"
          },
          {
            "type": "text/pdf",
            "suffixes": "pdf"
          }
        ]
      }
    ],
    "indexed_db": true,
    "math": "5f030fa7d2e5f9f757bfaf81642eb1a6"
  }
  ```
</Accordion>

<Accordion title="Web Attribute descriptions">
  <Accordion title="font_preferences">
    Measures the rendered size of different font families to capture subtle differences in font
    rendering behavior across platforms and configurations.
  </Accordion>

  <Accordion title="emoji">
    Captures how emoji glyphs are rendered and positioned in the browser, which can vary by OS,
    browser, and font stack.
  </Accordion>

  <Accordion title="fonts">
    Lists detectable system fonts available in the browser environment.
  </Accordion>

  <Accordion title="device_memory">
    Reflects the approximate device RAM in GB as reported by the browser.
  </Accordion>

  <Accordion title="timezone">
    Represents the browser’s configured IANA time zone identifier.
  </Accordion>

  <Accordion title="canvas">
    Contains hashed results of canvas rendering tests that detect differences in graphics rendering
    behavior.
  </Accordion>

  <Accordion title="languages">Reflects the device's preferred language as reported by the platforms.</Accordion>

  <Accordion title="webgl_extensions">
    Includes hashed representations of supported WebGL extensions, parameters, and shader
    capabilities.
  </Accordion>

  <Accordion title="webgl_basics">
    Provides core WebGL metadata such as version, vendor, renderer, and shading language
    information.
  </Accordion>

  <Accordion title="screen_resolution">
    Reports the available screen width and height in pixels.
  </Accordion>

  <Accordion title="touch_support">
    Indicates whether touch events are supported and the maximum number of simultaneous touch
    points.
  </Accordion>

  <Accordion title="architecture">
    Represents a numeric value describing the browser-reported CPU architecture characteristics.
  </Accordion>

  <Accordion title="cookies_enabled">
    Indicates whether cookies are enabled and accessible in the browser.
  </Accordion>

  <Accordion title="hardware_concurrency">
    Reports the number of logical CPU cores available to the browser.
  </Accordion>

  <Accordion title="date_time_locale">
    Represents the locale used for date and time formatting in the browser.
  </Accordion>

  <Accordion title="vendor">
    Identifies the browser vendor string as reported by the user agent.
  </Accordion>

  <Accordion title="color_depth">
    Indicates the color depth of the display in bits per pixel.
  </Accordion>

  <Accordion title="platform">
    Describes the platform on which the browser is running (e.g., MacIntel, Win32).
  </Accordion>

  <Accordion title="session_storage">
    Indicates whether the browser supports and allows access to session storage.
  </Accordion>

  <Accordion title="local_storage">
    Indicates whether the browser supports and allows access to local storage.
  </Accordion>

  <Accordion title="audio">
    Represents a numeric fingerprint derived from audio signal processing behavior in the browser.
  </Accordion>

  <Accordion title="plugins">
    Lists browser-detected plugins and their supported MIME types.
  </Accordion>

  <Accordion title="indexed_db">
    Indicates whether IndexedDB is available and accessible in the browser.
  </Accordion>

  <Accordion title="math">A hashed fingerprint.</Accordion>
</Accordion>

<Accordion title="Mobile Attribute descriptions">
  <Accordion title="device_manufacturer">
    Android and iOS only. Reflects the manufacturer of the device as reported by the platform (e.g., Apple, Samsung, Google).

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { device_manufacturer": "samsung" } }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="device_model">
    Android and iOS only. Reflects the model name of the device as reported by the platform.

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { device_model": "SM-A336B" } }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="device_memory">
    Reflects the approximate device RAM in GB as reported by the platform. Android only.
    <Note>iOS support coming soon.</Note>

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { "device_memory": 8 } }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="languages">
    Reflects the device's preferred language as reported by the platforms.

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { "languages": [["en-US"]] } }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="screen_resolution">
    Reports the available screen width and height in pixels. Supported for iOS devices.
    <Note>Android support coming soon.</Note>

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { "screen_resolution": [390, 844] } }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="battery_level">
    Android and iOS only. Reports the device's current battery level in percentage.

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { "battery_level": true } }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="battery_low_power_mode">
    Android and iOS only. Indicates whether low power mode (battery saver) is active on the device.

    <CodeGroup>
      ```json JSON theme={"theme":"github-dark-dimmed"}
      { "raw_device_attributes": { "battery_low_power_mode": true } }
      ```
    </CodeGroup>
  </Accordion>
</Accordion>

**Notes**

* Many values are hashed to reduce payload size and prevent direct reconstruction of raw rendering data.
* Individual attributes are not inherently malicious, they are evaluated in combination to detect anomalous or manipulated environments.

### Proximity Detection

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

Proximity detection is a complementary, location-based signal. Unlike the visitor ID, the proximity ID does not identify a unique device or browser but instead represents a fixed geographical zone within which the device is observed. This provides an additional layer of context, making it possible to identify groups of devices in the same physical area or a single device that may have changed its identity while remaining in the same zone.

**How to use this signal on each platform**

**Web:**

* Make sure your website uses JavaScript Agent version 3.12.9 or higher.
* Ensure that location permission is enabled and granted in the browser. The signal relies on the browser’s Geolocation API, so proximity data can only be collected when the user allows location access.

**Android:**

* To use this feature, make sure to update your app to use [Android SDK v2.10.0](/docs/changelog-android-sdk#v2-10-0) or higher.
* Ensure your app declares the required [location permissions](/docs/android-sdk#location-permissions). For integration details, please follow the instructions on the [Android SDK configuration](/docs/android-sdk#using-location-data-for-proximity-detection) page.
* Proximity IDs and related data (e.g., confidence level, precision radius) will be exposed only via the [Server API](/reference/server-api-v4), [webhooks](/docs/webhooks), or when [Sealed Client Results](/docs/sealed-client-results) are enabled.

**iOS:**

* To use this feature, make sure to update your app to use [iOS SDK v2.10.0+](/docs/changelog-ios-sdk#v2-10-0) or higher.
* Ensure your app declares the required [location permissions](/docs/ios-sdk#handling-location-permissions). For integration details, please follow the instructions on the [iOS SDK configuration](/docs/ios-sdk#using-location-data-for-proximity-detection) page.
* Same as for Android, proximity IDs and related data (e.g., confidence level, precision radius) will be exposed only via the [Server API](/reference/server-api-v4), [webhooks](/docs/webhooks), or when [Sealed Client Results](/docs/sealed-client-results) are enabled.

We use a [discrete global grid system](https://en.wikipedia.org/wiki/Discrete_global_grid) to generate proximity data in a consistent and privacy-conscious way. This approach allows us to represent user locations as coarse, non-identifiable spatial zones (proximity IDs), enabling scalable proximity detection and fraud analysis while protecting user privacy. For a closer look at how we apply this approach in practice, see our [technical deep-dive](https://fingerprint.com/blog/proximity-detection-deep-dive/).

The response will include proximity results in the following structure:

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  {
    "proximity": {
      "id": "w1aTfd4MCvl",
      "precision_radius": 10,
      "confidence": 0.95
    }
  }
  ```
</CodeGroup>

Note: In API v4, the `proximity` attribute is omitted from the response payload if the underlying geolocation data is not available, rather than being returned as an empty object.

`id`

The `id` field is a stable identifier for a given proximity zone. Devices observed within the same zone will share the same `id`. It can be used for detecting behaviors like:

* Devices frequently appearing together (co-location patterns).
* Repeated activity from the same physical area.
* Potential device farms or shared access points. `id` cannot be reverse-mapped to a specific geolocation, enabling privacy-preserving location-based analysis without compromising user identity or precision.

`precisionRadius`

The `precisionRadius` field indicates the precision level of the proximity zone, expressed in meters. For example, `"precisionRadius": 10` means the device's location was mapped to a zone covering an area approximately 10 meters across.

* Smaller values correspond to finer-grained zones and higher precision.
* Proximity precision levels are hierarchical: each proximity ID is contained within a parent proximity ID at a coarser level (larger `precisionRadius`).
  * Devices with identical coordinates can map to different proximity IDs if their reported location accuracies differ significantly.
  * For example, identical coordinates with `5` m and `10` m location accuracy would map to the same proximity ID, while `50` m accuracy would map to a different, coarser proximity ID.
* By default, we return the most precise proximity ID based on the location signals, but you can also retrieve proximity data at a specific (default or larger) `precisionRadius` using [/events/search](/reference/server-api-v4-search-events). We recommend leveraging this search filter to get the most value from proximity data. This feature allows you to search across coarser radius levels, helping identify all devices within a larger area - even if they were originally mapped to more granular zones.

<Info>
  **Useful tip: Keep in mind that adjacent** physical areas may generate different Proximity IDs.
  Using the filter by `precisionRadius` through
  [/events/search](/reference/server-api-v4-search-events) ensures your logic can accommodate these
  natural boundaries by grouping related IDs under a broader zone.
</Info>

**How to interpret precisionRadius**

| **Precision radius range** | **What it means**                                       | **Typical use cases**                                                                                                                                   |
| -------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **0-10 m**                 | Very precise location (room-level or same building).    | Detecting co-located devices, potential device farms, or flagging a single device that may have changed its identity but remained in the same location. |
| **10-75 m**                | Street-level accuracy. Same street or nearby building.  | Retail/store fraud detection, delivery validation, nearby device matching.                                                                              |
| **75-200 m**               | Neighborhood/block-level accuracy.                      | Good for geo-marketing and less strict fraud checks; however, it can flag potential clusters of spoofed locations or reused identities.                 |
| **200 m-1 km**             | City-level accuracy. Same area, but not the exact spot. | Audience analytics, compliance checks, potential clusters of spoofed locations or reused identities.                                                    |
| **1 km+**                  | Rough location.                                         | Country/city validation, coarse geolocation, potential clusters of spoofed locations or reused identities.                                              |

`confidence`

The `confidence` field ranges from `0` to `1` and reflects the likelihood that the true device location lies within the mapped proximity zone rather than an adjacent one. It is calculated by evaluating multiple factors that determine how well the device location coordinates and accuracy radius fit within the proximity zone.

* Scores closer to `1` indicate high confidence that the true device location is inside the mapped proximity zone, as the device location area fits cleanly within its bounds.
* Scores closer to `0` indicate low confidence, as the device location area is only partially contained within the proximity zone bounds, suggesting the true location point may lie within an adjacent zone. Even with a score of `0`, the true location will always be either within the mapped proximity zone or an immediately adjacent one. Retrieving proximity IDs from [/events/search](/reference/server-api-v4-search-events) at coarser precision levels (filtering by larger `precisionRadius` values) typically yields higher confidence scores.

## Browser Smart Signals

The Smart Signals listed below apply only to browsers.

### Browser Bot Detection

<Availability platforms={["browser"]} plans={["pro-plus", "enterprise"]} />

[**Javascript agent v3.7.0+**](/docs/changelog-javascript-agent#v3-7-0)

Get information about good and bad bots, allowing you to block or filter them from your regular traffic and stop automated abuse attempts.

The `bot` field contains one of `not_detected`, `bad` or `good` values where

* `not_detected` means that we haven't detected a bot and the payload should belong to a regular visitor
* `good` indicates that the bot is a well-known web crawler or other search engine bot
* `bad` is an automated tool that doesn't have legitimate uses and assumes fraudulent activity

<CodeGroup>
  ```json Bad Bot - Detected theme={"theme":"github-dark-dimmed"}
  "bot": "bad",
  "bot_type": "selenium"
  ```

  ```json Legitimate Visitor theme={"theme":"github-dark-dimmed"}
  "bot": "not_detected"
  ```
</CodeGroup>

### Browser Incognito Detection

<Availability platforms={["browser"]} plans={["pro-plus", "enterprise"]} />

**Incognito** flag detects whether incognito or private modes are being used by the visitor to access the customer's website.

Most browsers have an option called Incognito mode ([Chrome](https://support.google.com/chrome/answer/95464?hl=en\&co=GENIE.Platform%3DDesktop)) or Private mode ([Safari](https://support.apple.com/en-gb/guide/safari/ibrw1069/mac), [Firefox](https://support.mozilla.org/en-US/kb/private-browsing-use-firefox-without-history)) that disables some functionality and makes the general browser storage more ephemeral. Normal browser tabs save additional information like cookies and local storage content in a way that ensures that the information is available to the website even after the browser window is closed and re-opened. Incognito mode makes sure that there are no such traces once a window gets closed.

Since the most basic fingerprinting technique could be storing a cookie in the visitor's browser, the incognito mode can be used to circumvent this simple mechanism, making sure that the returning visitor is not correctly re-identified through cookies and other information stored in the browser. This might be interpreted as an attempt to pose as a completely new identity. It might also be considered to be the most basic mechanism of browser tampering.

The flag is an interesting data point in fraud scenarios, especially in use cases where applying promotional coupons, redeeming bonuses or voting should be limited to once per user.

<CodeGroup>
  ```json Incognito Mode - Detected theme={"theme":"github-dark-dimmed"}
  "incognito": true
  ```

  ```json Normal Mode theme={"theme":"github-dark-dimmed"}
  "incognito": false
  ```
</CodeGroup>

These browsers are supported:

* Safari (macOS / iOS)
* Chrome (Windows / macOS / iOS / Android / Linux)
* Samsung Browser (Android)
* Firefox (Windows / macOS / iOS / Android / Linux)
* Edge (Windows / macOS / iOS / Android)
* Brave (Windows / macOS / iOS / Android / Linux)

<Warning>
  **HTML iframes limitation**

  Incognito detection can give a false result when JavaScript agent runs in an iframe. Make sure JavaScript agent runs outside iframes to get the accurate result.
</Warning>

### VPN Detection for browsers

<Availability platforms={["browser"]} plans={["free", "pro-plus", "enterprise"]} />

Fingerprint's [VPN detection](https://fingerprint.com/blog/vpn-detection-how-it-works/) is capable of detecting whether the user is in a different timezone compared to their originating IP address indicated by the `timezone_mismatch` flag. It can also provide information about whether an IP address is associated with one of the public VPN providers, indicated by the `publicVPN` flag, or anonymizing services, indicated by the `relay` flag . On top of that, we detect whether the OS of the client matches the OS of the network traffic we see, represented in the `os_mismatch` flag.

If either of those `vpn_methods` return positive results, we return the final `result` as `true`.

<CodeGroup>
  ```json VPN Detected theme={"theme":"github-dark-dimmed"}
  "vpn": true,
  "vpn_confidence": "high",
  "vpn_origin_timezone": "Europe/Berlin",
  "vpn_origin_country": "unknown", // Not yet supported for browsers
  "vpn_methods": {
      "timezone_mismatch": true,
      "public_vpn": true,
      "auxiliary_mobile": false, 
      "os_mismatch": false,
      "relay": false
  }
  ```

  ```json No VPN Detected theme={"theme":"github-dark-dimmed"}
  "vpn": false,
  "vpn_confidence": "high",
  "vpn_origin_timezone": "Europe/Berlin",
  "vpn_origin_country": "unknown", // Not yet supported for browsers
  "vpn_methods": {
      "timezone_mismatch": false,
      "public_vpn": false,
      "auxiliary_mobile": false,
      "os_mismatch": false,
      "relay": false
  }
  ```
</CodeGroup>

#### `vpn`

* `true` if we detect a VPN through `timezoneMismatch`, `publicVPN`, `relay`or `osMismatch` methods. The field can be used as a standalone flag for VPN detection. Alternatively, fields in the `methods` section (documented below) can be used in specific use-cases to improve the granularity of the detection
* `false` if none of the `methods` below returned a positive result

#### `vpn_confidence`

The confidence level indicates how certain Fingerprint is that the current request is originating from a VPN. It is conveyed as a string with three possible values: **high**, **medium**, or **low**.

This confidence level is determined by evaluating multiple factors, such as **public\_vpn**, **timezone\_mismatch**, **os\_mismatch**, and other relevant `vpn_methods`.

In case of `vpn: true`

* **High confidence**: Clear, strong signals suggest the user is connected via a VPN.
* **Medium confidence**: Some signals point to possible VPN usage, including cases where a significant difference between the device's original timezone and the IP timezone is detected. The evidence is not definitive.
* **Low confidence**: Mainly due to a minor difference between the device's original timezone and the IP timezone. This could suggest scenarios other than VPN usage, such as when the network provider is registered in a different timezone or routes traffic through servers in another location.

In case of `vpn: false`

* **High confidence**: Strong signals suggest the user is not using a VPN.
* **Medium confidence**: Partial signals have been captured, but the evidence is not definitive.

#### `vpn_origin_timezone`

This field exposes the [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) that is available through the system settings. Since the presence of a VPN does not affect the value of this field, it can be used as a true timezone of origin (physical location) of the user.

* **Example:** `originTimezone: "Europe/Prague"`

#### `vpn_origin_country`

This field is populated only when the request comes from our iOS and Android native SDKs and is always set to `"unknown"` for browsers. See the detailed description in [VPN Detection for mobile devices](/docs/smart-signals-reference#vpn-detection-for-mobile-devices) .

#### `vpn_methods`

More granular VPN detection methods that contribute to the final VPN detection `result`.

##### `timezone_mismatch`

* `true`
  * When the geolocated IP address of the device does not match the originTimezone from the system settings or
  * When at least 50% of requests from the same IP in the last 7 days show a mismatch between the device’s originTimezone and the IP address location
* `false` when `originTimezone` matches the location of the IP address from which we receive the traffic

The `originTimezone` includes a country-specific reference like `"Europe/Prague"`. The `timezoneMismatch` will be `true` even if a visitor in Prague uses a Berlin VPN server, despite both countries being in the same *GMT+2* UTC offset. For most use cases, `timezoneMismatch` functions well as an indicator of country mismatch between the browser and the IP address.

##### `public_vpn`

Detects whether the IP address of the event matches any publicly known VPN providers like [NordVPN](https://nordvpn.com/), [Surfshark](https://surfshark.com/), [ExpressVPN](https://www.expressvpn.com/), [ProtonVPN](https://protonvpn.com/) and others.

* `true` when our database of public VPN provider IP addresses contains the IP address of the event
* `false` if we did not find a match in our public VPN provider database

##### `os_mismatch`

Compares the network signature of the request we have received through our proprietary algorithm and searches our internal database to determine whether the signature matches the OS (operating system) of the client.

* `true`
  * If the network signature of the request we receive **does not match** the signature of the OS of the client or
  * When at least 10% of requests from the same IP in the last 7 days show this mismatch
* `false`
  * if the network signature of the request we receive matches the signature of the OS of the client
  * if we fail to capture the OS information through our detection algorithm (happens in 10-15% cases)

The method is currently very accurate for **Windows** devices but might be less accurate for other OS combinations. We recommend using this flag to lower the false positive rate of the `timezoneMismatch` method.

##### `relay`

Detects whether the IP address of the event matches anonymizing services, such as iCloud Private Relay.

##### `auxiliary_mobile`

* This field is primarily set for requests from our iOS and Android native SDKs.
* For browsers, it is normally false, but will be true if at least 10% of requests from the same IP in the last 7 days meet the auxiliary mobile detection criteria.
* See the detailed description in [VPN Detection for mobile devices](/docs/smart-signals-reference#vpn-detection-for-mobile-devices)

### Browser Tamper Detection

<Availability platforms={["browser"]} plans={["free", "pro-plus", "enterprise"]} />

There are very simple techniques to confuse less sophisticated fingerprinting algorithms through User Agent [spoofing](https://fingerprint.com/blog/what-is-browser-spoofing/) or by changing the output of selected signals collected from the browser, including the use of anti-detect browsers.

While our `visitor_id` remains stable in those cases, tampering detection helps detect this behavior.

We do this using two complementary detection approaches:

* Statistical anomaly detection, which identifies browser signatures that are unusually rare compared to the overall population
* Anti-detect browser detection, which combines heuristic (rule-based) methods with a machine learning model to identify known anti-detect browsers

<CodeGroup>
  ```json Tampering Detected - Anti-detect browser theme={"theme":"github-dark-dimmed"}
  "tampering": true,
  "tampering_confidence": "high",
  "tampering_ml_score": 0.9721,
  "tampering_details": {
      "anomaly_score": 0,
      "anti_detect_browser": true 
    } 
  ```

  ```json Tampering Detected - High anomaly score theme={"theme":"github-dark-dimmed"}
  "tampering": true,
  "tampering_confidence": "medium",
  "tampering_ml_score": 0,
  "tampering_details": {
      "anomaly_score": 0.9721,
          "anti_detect_browser": false
  }
  ```

  ```json Standard Browser theme={"theme":"github-dark-dimmed"}
  "tampering": false,
  "tampering_confidence": "high",
  "tampering_ml_score": 0,
  "tampering_details": {
      "anomaly_score": 0,
      "anti_detect_browser": false
  }

  ```
</CodeGroup>

#### `tampering`

* `true` if tampering is detected through an anomalous browser signature, anti-detect browser detection, or other tampering-related methods
* `false` if none of the tampering checks return a positive result

The field can be used as a standalone flag for tampering detection. Alternatively, the more granular fields documented below can be used for workflows that require more context.

#### `tampering_confidence`

The confidence level indicates how certain Fingerprint is that the current request involves browser tampering. This confidence level is determined by evaluating multiple factors, such as heuristic rules, probabilistic anomaly detection, an anti detect browser ml model, and other relevant methods.
It is conveyed as a string with possible values such as high, medium, or low

In case of tampering: `true`

* **High confidence**: heuristic anti detect browser signals and the ml model are triggered, or all of the methods are triggered.
* **Medium confidence**: either the ml model triggers alone, the anomaly score triggers alone with or without the heuristic anti detect browser methods trigger.
* **Low confidence**: only the heuristic anti detect methods are triggered.

In case of tampering: `false`

* **High confidence**: Strong signals suggest the user is not tampering with their request.

#### `tampering_ml_score`

The output of this model is captured as `tampering_ml_score`, a number indicating how likely an event is coming from an anti detect browser. Values close to 1 signify higher confidence and we consider anything above the threshold of 0.8 to be actionable (the result and anti\_detect\_browser fields conveniently captures that fact)

#### `tampering_details`

Provides more granular tampering-related signals that contribute to the final tampering result.

#### `anomaly_score`

The output of this model is captured as `anomaly_score`, a statistical score indicating how rare the visitor’s browser signature is compared to the overall population. Values close to `1` signify highly anomalous browsers and we consider anything above the threshold of `0.5` to be actionable (the `result` field conveniently captures that fact).

#### `anti_detect_browser`

Detects whether the request shows evidence of anti-detect browser usage.

This field may be triggered by:

* heuristic detection of known anti-detect browser behavior
* machine learning detection of anti-detect browser patterns

Examples of anti-detect browsers include tools such as AdsPower, DolphinAnty, OctoBrowser, and GoLogin.

### Virtual Machine Detection

<Availability platforms={["browser"]} plans={["pro-plus", "enterprise"]} />

Detects if the browser is running inside a [virtualization software](https://fingerprint.com/blog/virtual-machine-fraud-detection/) like VirtualBox by examining the browser configuration.

<CodeGroup>
  ```json Browser Launched from a VM theme={"theme":"github-dark-dimmed"}
  "virtual_machine": true
  ```

  ```json Legitimate Browser theme={"theme":"github-dark-dimmed"}
  "virtual_machine": false
  ```
</CodeGroup>

### Privacy-Focused Settings

<Availability platforms={["browser"]} plans={["pro-plus", "enterprise"]} />

Firefox, Brave, and other privacy-focused browsers actively [fight fingerprinting](https://fingerprint.com/blog/privacy-settings-detection/) and expose user settings that have the ability to randomize and obfuscate signal output. The Privacy-Focused Settings Smart Signal detects if those settings are enabled and reports it.

<CodeGroup>
  ```json Privacy Settings - Detected theme={"theme":"github-dark-dimmed"}
  "privacy_settings": true
  ```

  ```json No Privacy Settings theme={"theme":"github-dark-dimmed"}
  "privacy_settings": false
  ```
</CodeGroup>

### Developer Tools Detection

<Availability platforms={["browser"]} plans={["pro-plus", "enterprise"]} />

Detect whether browser developer tools are manually opened in Chrome or Firefox, or whether a Chrome instance is being controlled via an active Chrome DevTools Protocol session. This enables detection of various automation frameworks and libraries.

> Note: Data required for Developer Tools detection are collected when the JavaScript agent [loads](/reference/js-agent-v4-start-function), not when the user is [identified](/reference/js-agent-v4-get-function). This can result in false negatives if the visitor opens Developer Tools only after loading the page.

<CodeGroup>
  ```json Developer Tool Detected theme={"theme":"github-dark-dimmed"}
  "developer_tools": true
  ```

  ```json No Developer Tool Detected theme={"theme":"github-dark-dimmed"}
  "developer_tools": false
  ```
</CodeGroup>

## Smart Signals for mobile devices

The Smart Signals listed in this section apply only to mobile devices and provide valuable intelligence about the integrity of the device and the app. Smart Signals for Android devices are now included on our [Free plan](https://fingerprint.com/pricing/), making it easier to get started. Full access to all mobile Smart Signals is included with our [Pro Plus and Enterprise plans](https://fingerprint.com/pricing/). If you are interested in one or more of these signals, then please [contact our support team](https://fingerprint.com/support/) to enable them for you.

When your app is integrated with Fingerprint (using either our native mobile SDKs or our multi-platform SDKs), you will receive these signals as part of our Server API and/or Webhooks responses.

### Android Emulator Detection

<Availability platforms={["android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.0+**](/docs/changelog-android-sdk#v2-3-0)

Prevent spam and protect against nefarious Android emulator farms by ensuring the request is coming from a physical device. To [detect emulators](https://fingerprint.com/blog/android-emulator-tamper-fraud-detection/), several additional device attributes have to be collected and this increases the time to get a `visitorId`. The latency can be anywhere between 300 and 1500ms.

```json theme={"theme":"github-dark-dimmed"}
"emulator": false
```

### iOS Simulator Detection

<Availability platforms={["iOS"]} plans={["pro-plus", "enterprise"]} />

[**iOS SDK v2.12.0+**](/docs/changelog-ios-sdk#december-2025)

Detect whether your app is running on an iOS simulator rather than a physical device. In production environments, simulators are rarely used by legitimate users - they are commonly leveraged by fraudsters to run automated attacks at scale, including account farming, bonus abuse, and promo exploitation. Use this signal to flag non-genuine iOS environments and strengthen your fraud detection stack alongside other signals such as [jailbreak detection](/docs/smart-signals-reference#jailbroken-device-detection), [VPN](http://localhost:3001/docs/smart-signals-reference#vpn-detection-for-mobile-devices) and [proxy](/docs/smart-signals-reference#proxy-detection) usage.

```json theme={"theme":"github-dark-dimmed"}
"simulator": false
```

### Cloned App Detection

<Availability platforms={["android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.0+**](/docs/changelog-android-sdk#v2-3-0)

Identify if a request is coming from a cloned application. Making multiple [clones of an app](https://fingerprint.com/blog/navigating-risks-user-initiated-app-cloning/) on the same device can be used to abuse promotions and get around app restrictions. (Android only)

```json theme={"theme":"github-dark-dimmed"}
"cloned_app": false
```

### Factory Reset Detection

<Availability platforms={["ios", "android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.0+**](/docs/changelog-android-sdk#v2-3-0)\
[**iOS SDK v2.3.0+**](/docs/changelog-ios-sdk#v2-3-0)

Resetting a **mobile device** to default factory settings has been a common technique that fraudsters use to [evade fraud detection mechanisms](https://fingerprint.com/blog/detecting-suspicious-activity-factory-reset/). When a factory reset is performed, it can

* Disguise the identity of the mobile device
* Be used to abuse promotional offers
* Prevent the mobile device from being blocked for fraudulent activity

The Factory Reset Smart Signal will indicate when the mobile device was most recently factory reset. You can use this information in your fraud detection mechanisms to flag a mobile device as suspicious.

As an example, for a mobile device that was factory reset on July 19, 2023, at 6 AM EST, the response will be:

```json theme={"theme":"github-dark-dimmed"}
"factory_reset_timestamp": 1689756000
```

**What is the response for devices that were never factory reset?**

**iOS SDK v2.3.0 or higher**

* For iOS devices that were never factory reset, the `time` and `timestamp` fields will correspond to [epoch](https://en.wikipedia.org/wiki/Epoch_\(computing\)):

  ```json theme={"theme":"github-dark-dimmed"}
     "factory_reset_timestamp": 0
  ```

**In what other iOS scenarios can a timestamp reset to epoch?**

* The **iOS device** that initiated the request is not a physical device but an iOS simulator. (Conversely, a factory reset can be detected for Android emulators).
* Your **iOS app** does not use Fingerprint Identification SDK **v2.3.0 or higher**. The ability to detect factory reset was introduced only in v2.3.0.

**Android SDK v2.3.0 to 2.9.0**

* For Android devices that were never factory reset, the `time` and `timestamp` fields in the response will correspond to when the device was activated or in some scenarios, the `time` and `timestamp` fields will correspond to [epoch](https://en.wikipedia.org/wiki/Epoch_\(computing\)):

  <CodeGroup>
    ```json JSON theme={"theme":"github-dark-dimmed"}
     "factoryReset": {
       "data": {
         "time": "1970-01-01T00:00:00Z",
         "timestamp": 0
     }
    }
    ```
  </CodeGroup>

**Android SDK v2.10.0 and higher**

Starting from Android SDK **v2.10.0** the factory reset detection algorithm has been improved for Android devices to reduce false positives and better distinguish real resets from routine system updates, Google system changes, or vendor-specific behavior.

* For Android devices that were never factory reset, the `time` and `timestamp` fields will correspond to [epoch](https://en.wikipedia.org/wiki/Epoch_\(computing\)):

  <CodeGroup>
    ```json JSON theme={"theme":"github-dark-dimmed"}
     "factoryReset": {
       "data": {
         "time": "1970-01-01T00:00:00Z",
         "timestamp": 0
     }
    }
    ```
  </CodeGroup>

* If an Android device previously showed a factory reset timestamp but now returns the [epoch](https://en.wikipedia.org/wiki/Epoch_\(computing\)) value after updating to SDK v2.10.0 or higher, it simply means that no real factory reset occurred. Starting with SDK v2.10.0, affected devices have their factory reset timestamps recalculated to ensure accuracy. In these cases, the earlier timestamp was most likely triggered by a system update or silent Google update that behaved similarly to a reset.

**In what other Android scenarios can a timestamp reset to epoch?**

* Your **Android app** uses an incompatible version of Fingerprint Identification SDK
  * **\v2.3.0:** The ability to detect factory reset was introduced only in v2.3.0.
  * **v2.3.0 ≥ SDK \< v2.3.4:** Due to *lazy* signal collection, more than one request must be initiated from the same device for a factory reset to be detected. If you would like to use one of these versions in your app, you first need to [contact our support team](https://fingerprint.com/support/) to enable factory reset detection for your account. (Since the first request from a fraudulent device is the most critical request to detect fraud, we made improvements in v2.3.4 that allowed us to detect a factory reset during the first request itself.)
* **SDK v2.10.0+** As mentioned above, if an Android device previously showed a factory reset due to a system update or silent Google system update before upgrading to SDK v2.10.0, its factory reset timestamp will be recalculated after the upgrade. If no actual user-initiated reset occurred, the timestamp will be updated to the epoch value.

### Frida Detection

<Availability platforms={["ios", "android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.3+**](/docs/changelog-android-sdk#v2-3-3)\
[**iOS SDK v2.2.0+**](/docs/changelog-ios-sdk#v2-2-0)

In simple terms, [app hooking](https://en.wikipedia.org/wiki/Hooking) is a process where the behavior of a mobile app is changed by intercepting the app at runtime. [Frida](https://frida.re/) is a dynamic instrumentation toolkit that tech-savvy fraudsters can use to spoof an app at runtime and change its behavior. With this Smart Signal, you will know if [Frida](https://fingerprint.com/blog/exploring-frida-dynamic-instrumentation-tool-kit/) is being used to dynamically instrument the app.

<CodeGroup>
  ```json theme={"theme":"github-dark-dimmed"}
  "frida": false
  ```
</CodeGroup>

### Geolocation Spoofing Detection

<Availability platforms={["ios", "android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.4+**](/docs/changelog-android-sdk#v2-3-4)\
[**iOS SDK v2.3.1+**](/docs/changelog-ios-sdk#v2-3-1)

Fraudsters spoof the location of their mobile devices to fool fraud detection systems. With this Smart Signal, you will know if the location of the mobile device has been spoofed or not. We also recommend using this Smart Signal in combination with [Proximity Detection](/docs/smart-signals-reference#proximity-detection) results.

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  "location_spoofing": false
  ```
</CodeGroup>

Note: The SDK itself does not request any location permissions. The SDK performs a non-intrusive check to determine whether the host app has already been granted the necessary location permissions. Based on that check, it either collects the geolocation spoofing signal or skips it. In short, this geolocation spoofing detection is only applicable to location-enabled apps for now. For more info about working with location permissions on app side, please refer to the resources:

* [Location Permission for iOS](https://developer.apple.com/documentation/corelocation/requesting_authorization_to_use_location_services).
* [Location Permission for Android](https://developer.android.com/training/permissions/requesting).

### Jailbroken Device Detection

<Availability platforms={["ios"]} plans={["pro-plus", "enterprise"]} />

[**iOS SDK v2.2.0+**](/docs/changelog-ios-sdk#v2-2-0)

An iPhone or an iPad is labeled *jailbroken* when unauthorized modifications are made to the underlying operating system (iOS). Jailbreaking weakens a device’s built-in security features and makes it easy to steal sensitive information stored on the device. See [Unauthorized modification of iOS](https://support.apple.com/guide/iphone/unauthorized-modification-of-ios-iph9385bb26a/ios) for more information.

Fraudsters employ [phishing](https://en.wikipedia.org/wiki/Phishing) mechanisms to trick users into installing *jailbreak* software on their devices and then take control of their devices. Your app (e.g. banking, e-commerce, etc) will not be able to distinguish the transactions made using [jailbroken devices](https://fingerprint.com/blog/prevent-mobile-fraud-jailbroken-device-detection/) from those made using genuine devices. Honoring these fraudulent transactions will lead to financial losses (caused by chargeback expenses, account takeover, etc) and loss of trust among your customers.

The Jailbroken Smart Signal will help you detect if your app is being used from an iPhone/iPad that has been jailbroken and enable you to proactively act upon it.

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  "jailbroken": false
  ```
</CodeGroup>

### MitM Attack Detection

<Availability platforms={["ios", "android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.8.0+**](/docs/changelog-android-sdk#v2-8-0)\
[**iOS SDK v2.8.2+**](/docs/changelog-ios-sdk#v2-8-2)

Man-in-the-Middle (MitM) attacks occur when a fraudster intercepts the communication between two parties with the intention of

* Gaining access to sensitive information.
* Modifying the information to their advantage.
* Block the requests to/from the intended parties.

These attacks can result in service disruptions for an organization, diminishing customer trust, damaging reputation, and causing financial losses.

The MitM Attacks Smart Signal will help you detect if requests made to Fingerprint servers are intercepted and potentially modified. You can use this information to identify spoofed requests/responses and take additional precautionary steps.

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  "mitm_attack": false
  ```
</CodeGroup>

### Rooted Device Detection

<Availability platforms={["android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.0+**](/docs/changelog-android-sdk#v2-3-0)

Ensure a safe Android mobile app environment by detecting [rooted devices](https://fingerprint.com/blog/android-emulator-tamper-fraud-detection/).

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  "root_apps": false
  ```
</CodeGroup>

### Tampered Request Detection for mobile apps

<Availability platforms={["ios", "android"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.0+**](/docs/changelog-android-sdk#v2-3-0)\
[**iOS SDK v2.2.0+**](/docs/changelog-ios-sdk#v2-2-0)

Promotional offers are often exploited by creating multiple accounts. Device identification enables businesses to determine if the same mobile device was used to create multiple accounts. One technique fraudsters employ to trick device identification is to modify the request sent to our servers.

When your app requests a visitor ID for the device, Fingerprint collects several properties from the device and sends it to our servers. The properties collected from the device are used to generate the visitor ID and deduce other Smart Signals. However, if the properties within the request are modified beyond recognition, then

* A new visitor ID could be generated for an already-seen device
* All the intended Smart Signals may not be flagged.

The Tampered Request Detection Smart Signal detects anomalies in the properties received with the request. Thus, it enables you to identify tampered requests and take corresponding mitigation measures.

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  "tampering": true
  "tampering_details" {
    "anomaly_score": 1
  }
  ```
</CodeGroup>

#### `tampering`

Indicates if an identification request from an Android SDK has been tampered with.

* `true` - If the request contains anomalous device attributes that could not have been legitimately produced by Fingerprint's Android or iOS SDK (see `anomaly_score`).
* `false` - If the request is considered genuine.

#### `tampering_details.anomaly_score`

When the request contains anomalous device attributes, this value is 1. Otherwise, it is 0.

### VPN Detection for mobile devices

<Availability platforms={["ios", "android", "browser"]} plans={["free", "pro-plus", "enterprise"]} />

[**Android SDK v2.3.3+**](/docs/changelog-android-sdk#v2-3-3)\
[**iOS SDK v2.3.0+**](/docs/changelog-ios-sdk#v2-3-0)

VPN apps for mobile devices are popular with both legit users and fraudsters. These VPN apps

* Protect their users’ privacy by encrypting all their traffic
* Allow their users to remain anonymous by giving them the ability to hide their real location

The VPN Detection Smart Signal for mobile devices will help you [detect](https://fingerprint.com/blog/vpn-detection-location-spoofing-fraud-prevention/) if your app is being used by a mobile device with an active VPN connection.

<CodeGroup>
  ```json JSON theme={"theme":"github-dark-dimmed"}
  "vpn": true,
  "vpn_confidence": "high",
  "vpn_origin_timezone": "Europe/Berlin",
  "vpn_origin_country": "DE", // country code string in the ISO 3166 format
  "vpn_methods": {
      "timezone_mismatch": true,
      "public_vpn": true,
      "auxiliary_mobile": true,
      "os_mismatch": false, // always false, irrelevant for native SDKs
      "relay": false
  }
  ```
</CodeGroup>

#### `vpn`

For mobile devices, `vpn` is true when either of the four listed methods is true:

* `timezone_mismatch` - `true` when the device is in a different timezone compared to the timezone of the originating IP address.
* `public_vpn` - `true` when the IP address matches one of the known IP addresses that belong to public VPN providers.
* `auxiliary_mobile` - `true` when other proprietary detection methods indicate the presence of a VPN.
* `relay`- `true` then the IP address of the event matches anonymizing services, such as iCloud Private Relay.

Note: `os_mismatch` is web-specific, always `false` when using mobile SDKs.

#### `vpn_confidence`

The confidence level indicates how certain Fingerprint is that the current request is originating from a VPN. This confidence level is determined by evaluating multiple factors, such as `public_vpn`, `timezone_mismatch`, `auxiliary_mobile`, and other relevant methods.

To learn more about the possible values and how they are determined, see [confidence](/docs/smart-signals-reference#vpn_confidence).

#### `vpn_origin_timezone`

This field indicates the [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) that is currently set for the mobile device. In situations where a VPN is enabled, this timezone can be different from the timezone associated with the IP address.

The `vpn_origin_timezone` usually includes a country-specific reference like `"Europe/Prague"`. The `timezone_mismatch` will be `true` even if a mobile user in Prague uses a Berlin VPN server, despite both countries being in the same *GMT+2* UTC offset. For most use cases, `timezone_mismatch` functions well as an indicator of country mismatch between the mobile device and the IP address.

This field is supported for both Android and iOS devices.

#### `vpn_origin_country`

This field indicates the country in which the mobile device is physically located at the time of request. The country is represented in [ISO 3166](https://www.iso.org/iso-3166-country-codes.html) format. It does not require Location Permissions to be enabled for your app.

This field can be very useful in situations where an active VPN can mask the true location of the device.

**Android devices**

* This field is supported only in Android SDK [v2.4.0](https://github.com/fingerprintjs/fingerprintjs-pro-android-demo/releases/tag/v2.4.0) and higher. For lower versions of the Android SDK, the value is set to `unknown`.
* If the request is from an emulator, irrespective of the SDK version used, the value is set to `unknown`.

**iOS devices**

* This field is supported only in iOS SDK [**v2.9.0**](https://docs.fingerprint.com/docs/changelog-ios-sdk#v2-9-0) and higher. For lower versions of the iOS SDK, the value is set to `unknown`.

### Developer Tools Detection for mobile devices

<Availability platforms={["ios", "android"]} plans={["pro-plus", "enterprise"]} />

[**Android SDK v2.13.1+**](https://docs.fingerprint.com/docs/changelog-android-sdk#february-2026)\
[**iOS SDK v2.12.0+**](https://docs.fingerprint.com/docs/changelog-ios-sdk#december-2025)

This mobile smart signal detects whether developer tools are active on a mobile device.
Developer tools are standard in development and testing workflows, especially on Android, but their presence on a production device can indicate exposure to reverse engineering, dynamic instrumentation, or automated abuse.
The signal is most meaningful when combined with others such as [Frida detection](https://docs.fingerprint.com/docs/smart-signals-reference#frida-detection), [Android emulator](https://docs.fingerprint.com/docs/smart-signals-reference#android-emulator-detection) and [iOS simulator](https://docs.fingerprint.com/docs/smart-signals-reference#ios-simulator-detection) detection.

**What is detected per platform:**

* **iOS** detects developer activity across three complementary layers: whether developer mode is explicitly enabled on the device, whether the app was signed with a development profile rather than distributed through the App Store, and whether the app is actively being run from Xcode. The signal returns `true` if any of these indicators is detected.

As mentioned, Developer Tools detection is available from [iOS SDK 2.12.0+](https://docs.fingerprint.com/docs/changelog-ios-sdk#december-2025). For improved detection accuracy, we recommend upgrading to [iOS SDK 2.13.0](https://docs.fingerprint.com/docs/changelog-ios-sdk#february-2026) or higher.

* **Android** detects developer activity at the device level by checking whether developer options are enabled, whether ADB (Android Debug Bridge) is active, and whether USB debugging or Wireless debugging is enabled. The signal returns `true` if any of these indicators are detected.

<CodeGroup>
  ```json Developer Tool Detected theme={"theme":"github-dark-dimmed"}
  "developer_tools": true
  ```

  ```json No Developer Tool Detected theme={"theme":"github-dark-dimmed"}
  "developer_tools": false
  ```
</CodeGroup>
