> ## 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.

# Migrating the Fingerprint React Native SDK from v3 to v4

> This guide covers all breaking changes introduced in version `4.0.0` of the Fingerprint React Native SDK and outlines the steps required to migrate an existing v3 integration.

Fingerprint React Native SDK `4.0.0` introduces breaking changes that require manual migration. The new SDK aligns with the v4 event format and requires the New Architecture, renames provider and client APIs, flattens the response format, and uses a single identification error type. These structural API changes do not affect identification or Smart Signals accuracy.

<Warning>
  * Native mobile SDKs v3.x will continue to work after v4.0.0 is released - you won't be forced to upgrade right away.
  * During this period, critical client-side hotfixes will still be issued for v3.x if needed, and backend-side improvements (including Smart Signals detection logic) can continue to benefit v3.x integrations, as long as the required signals are already collected by that SDK version.
  * However, React Native SDK v3.x support is tied to our overall API v3 deprecation timeline: once the [one-year deprecation period](/reference/migrating-from-v3-to-v4#client-sdk-compatibility-for-javascript-agent-v4) begins (which starts only after the full ecosystem supports API v4), the React Native SDK v3.x will no longer receive client-side hotfixes once that period ends. Backend-side improvements will still apply to v3.x wherever the SDK already collects the necessary signals.
</Warning>

# What's new

* The package is renamed from `@fingerprintjs/fingerprintjs-pro-react-native` to `@fingerprint/react-native`, and the GitHub repository moved from `fingerprintjs/fingerprintjs-pro-react-native` to `fingerprintjs/react-native`.
* The SDK now requires the [New Architecture](https://reactnative.dev/architecture/landing-page); the Old Architecture is no longer supported.
* The minimum supported versions are React Native 0.80 and Expo SDK 54, driven by the SDK's move to React Native's [Strict TypeScript API](https://reactnative.dev/docs/strict-typescript-api).
* The API aligns with Server API v4: responses are flat and snake\_case.
* `FingerprintJsProProvider` is renamed to `FingerprintProvider`, and `FingerprintJsProAgent` is replaced by a `start()` function plus a `useFingerprint()` hook.
* `useVisitorData` returns a discriminated union, `getData` always throws on error, and a new `immediate` option (default `false`) enables immediate data fetching on mount.
* Options are grouped by platform (`android`, `ios`, `web`), and `endpointUrl`/`fallbackEndpointUrls` are consolidated into a single `endpoints` option.
* All \~28 error classes collapse into one `FingerprintError`, discriminated with `error.code` and an `isFingerprintError` type guard.
* The web target's peer dependency changes from `@fingerprintjs/fingerprintjs-pro-spa` to `@fingerprint/agent`.
* Experimental Swift Package Manager support is available for iOS linking, alongside CocoaPods.
* iOS 13 is no longer supported. Because the SDK requires React Native 0.80, the effective platform floors are iOS 15.1 and Android 7.0 (API level 24+).

# Migration steps

The following section outlines the necessary migration steps to complete the transition from v3 to v4.

## Upgrade the package and enable the New Architecture

The package is renamed from `@fingerprintjs/fingerprintjs-pro-react-native` to `@fingerprint/react-native`. Remove the old package and install the new one at `4.0.0`, and make sure your app runs React Native 0.80+ (or Expo SDK 54+) with the New Architecture enabled:

<CodeGroup>
  ```shell NPM theme={"theme":"github-dark-dimmed"}
  npm uninstall @fingerprintjs/fingerprintjs-pro-react-native
  npm install @fingerprint/react-native --save
  ```

  ```shell Yarn theme={"theme":"github-dark-dimmed"}
  yarn remove @fingerprintjs/fingerprintjs-pro-react-native
  yarn add @fingerprint/react-native
  ```
</CodeGroup>

If your app still runs the Old Architecture, follow React Native's [New Architecture migration guide](https://reactnative.dev/docs/new-architecture-intro) before upgrading.

## Platform minimum bumps

Raise your platform floors to match the v4 SDK. The floors below are the effective minimums: React Native 0.80 itself requires iOS 15.1 and Android API level 24, so your app cannot target lower versions even where the native SDKs allow it.

| Platform | v3 minimum | v4 minimum |
| - | - | - |
| iOS / tvOS | iOS 13 / tvOS 15 | iOS 15.1 / tvOS 15 |
| Android | 6.0 (API 23) | 7.0 (API 24) |
| Swift | 5.9 | 5.9 |

Update your `ios/Podfile` platform target and `android/build.gradle` `minSdkVersion` accordingly.

## `FingerprintJsProProvider` renamed to `FingerprintProvider`

<CodeGroup>
  ```jsx v3 theme={"theme":"github-dark-dimmed"}
  import { FingerprintJsProProvider } from '@fingerprintjs/fingerprintjs-pro-react-native'

  <FingerprintJsProProvider apiKey="PUBLIC_API_KEY" region="eu">
    <App />
  </FingerprintJsProProvider>
  ```

  ```jsx v4 theme={"theme":"github-dark-dimmed"}
  import { FingerprintProvider } from '@fingerprint/react-native'

  <FingerprintProvider apiKey="PUBLIC_API_KEY" region="eu">
    <App />
  </FingerprintProvider>
  ```
</CodeGroup>

## `FingerprintJsProAgent` replaced by `start()` and `useFingerprint()`

The class-based agent is replaced by a `start()` function that synchronously returns a client with a single, asynchronous `get()` method. `getVisitorId()` and `getVisitorData()` are removed. Inside a component tree wrapped in `FingerprintProvider`, use the new `useFingerprint()` hook instead of constructing a client directly.

<CodeGroup>
  ```javascript Outside a component theme={"theme":"github-dark-dimmed"}
  import { FingerprintJsProAgent } from '@fingerprintjs/fingerprintjs-pro-react-native' // [!code --]
  import { start } from '@fingerprint/react-native' // [!code ++]

  const agent = new FingerprintJsProAgent({ apiKey: 'PUBLIC_API_KEY', region: 'eu' }) // [!code --]
  const visitorId = await agent.getVisitorId() // [!code --]
  const legacyData = await agent.getVisitorData() // [!code --]

  const fp = start({ apiKey: 'PUBLIC_API_KEY', region: 'eu' }) // [!code ++]
  const data = await fp.get({ tags: { action: 'login' } }) // [!code ++]
  ```

  ```javascript Inside a component theme={"theme":"github-dark-dimmed"}
  import { useFingerprint } from '@fingerprint/react-native' // [!code ++]

  function LoginButton() {
    const fp = useFingerprint() // [!code ++]

    const handleLogin = async () => {
      const data = await fp.get({ tags: { action: 'login' } }) // [!code ++]
    }

    return <Button title="Log in" onPress={handleLogin} />
  }
  ```
</CodeGroup>

## `useVisitorData` behavior changes

`useVisitorData` now returns a discriminated union (`{ data, isLoading, isFetched, error, getData }`), `getData` always throws instead of accepting `throwOnError`, and a new `immediate` option (default `false`) was introduced. Set it to `true` to fetch the data immediately on mount.

<CodeGroup>
  ```javascript useVisitorData theme={"theme":"github-dark-dimmed"}
  const oldHook = useVisitorData({ throwOnError: true }) // [!code --]
  const { isLoading, isFetched, error, data, getData } = useVisitorData() // [!code ++]

  const visitorData = await getData() // getData always throws now, wrap it in try/catch // [!code ++]

  useVisitorData({ immediate: true }) // set `immediate` to `true` to fetch on mount // [!code ++]
  ```
</CodeGroup>

## Options grouping and endpoint consolidation

Platform-specific options are now grouped under `android`, `ios`, and `web` keys, and `endpointUrl`/`fallbackEndpointUrls` are consolidated into a single `endpoints` option. `extendedResponseFormat` is removed; v4 always returns the flat response.

| v3 option | v4 option |
| - | - |
| `locationTimeoutMillisAndroid` | `android.locationTimeoutMillis` |
| `allowUseOfLocationData` (Android) | `android.allowUseOfLocationData` |
| `allowUseOfLocationData` (iOS) | `ios.allowUseOfLocationData` |
| `storageKey` | `web.storageKeyPrefix` |
| `urlHashing` | `web.urlHashing` |
| `cacheLocation`, `cacheTimeInSeconds`, `cachePrefix`, `cache` | `web.cache: { storage, duration, cachePrefix }` |
| `remoteControlDetection` | removed |
| `endpointUrl` + `fallbackEndpointUrls` | `endpoints: string \| string[]` |
| `extendedResponseFormat` | removed; v4 always returns the flat format |

<CodeGroup>
  ```jsx v3 theme={"theme":"github-dark-dimmed"}
  <FingerprintJsProProvider
    apiKey="PUBLIC_API_KEY"
    region="eu"
    allowUseOfLocationData={true}
    locationTimeoutMillisAndroid={2000}
    endpointUrl="https://metrics.yourdomain.com"
    fallbackEndpointUrls={['https://fallback.yourdomain.com']}
    extendedResponseFormat={true}
  >
    <App />
  </FingerprintJsProProvider>
  ```

  ```jsx v4 theme={"theme":"github-dark-dimmed"}
  <FingerprintProvider
    apiKey="PUBLIC_API_KEY"
    region="eu"
    android={{ allowUseOfLocationData: true, locationTimeoutMillis: 2000 }}
    ios={{ allowUseOfLocationData: true }}
    endpoints={['https://metrics.yourdomain.com', 'https://fallback.yourdomain.com']}
  >
    <App />
  </FingerprintProvider>
  ```
</CodeGroup>

## Response fields

### Renamed

| React Native SDK v3 | React Native SDK v4 |
| - | - |
| `requestId` | `event_id` |
| `visitorId` | `visitor_id` |
| `sealedResult` | `sealed_result` |

### Added

| Field | Type | Notes |
| - | - | - |
| `event_id` | `string` | Replaces `requestId` |
| `suspect_score` | `number \| undefined` | New Smart Signals value, only present when Smart Signals are enabled. It is not a replacement for `confidence.score`: a higher `suspect_score` means more suspicion, not more confidence. |
| `cache_hit` | `boolean \| undefined` | Web only. `true` when the response came from the cache. Always `undefined` on native platforms. |

### Removed

The following fields, and the `extendedResponseFormat` flag that enabled them, are no longer part of the response:

| Removed field | Type |
| - | - |
| `confidence` | `object` |
| `ipLocation` | `object` |
| `firstSeenAt` | `object` |
| `lastSeenAt` | `object` |
| `osName` | `string` |
| `osVersion` | `string` |
| `os` | `string` |
| `ip` | `string` |
| `device` | `string` |
| `visitorFound` | `boolean` |

## Errors

All \~28 v3 error classes collapse into a single `FingerprintError` with `{ name, code, event_id }`, plus an `isFingerprintError(error)` type guard. Discriminate on `error.code`, a string union open to unknown values, instead of `instanceof` checks against specific error classes.

<CodeGroup>
  ```javascript Error handling theme={"theme":"github-dark-dimmed"}
  import { isFingerprintError } from '@fingerprint/react-native' // [!code ++]

  try {
    const data = await getData()
  } catch (error) {
    if (error instanceof RequestTimeoutError) handleTimeout() // [!code --]
    if (isFingerprintError(error) && error.code === 'request_read_timeout') handleTimeout() // [!code ++]
    if (isFingerprintError(error)) console.log(error.code, error.event_id) // [!code ++]
  }
  ```
</CodeGroup>

| Common v3 error class | v4 `error.code` |
| - | - |
| `RequestTimeoutError` | `request_read_timeout` |
| `ClientTimeoutError` | `client_timeout` |
| `NetworkError` | `network_error` |
| `ApiKeyNotFoundError` | `public_api_key_not_found` |
| `WrongRegionError` | `wrong_region` |

`error.code` values are lower snake\_case and are the same on iOS, Android, and web; they are grouped into server/API v4 codes and client-side codes. Handle the ones you care about and fall back to generic handling for the rest. For the full list of web codes, see [JavaScript agent error handling](/reference/js-agent-error-handling#error-codes).

## Web peer dependency

If your app also targets web, swap the peer dependency from `@fingerprintjs/fingerprintjs-pro-spa` to `@fingerprint/agent`:

<CodeGroup>
  ```shell Web peer dependency theme={"theme":"github-dark-dimmed"}
  npm uninstall @fingerprintjs/fingerprintjs-pro-spa
  npm install @fingerprint/agent@^4.1.3 --save
  ```
</CodeGroup>

## iOS linking

CocoaPods is still fully supported for iOS linking. On React Native 0.87 and higher, you can optionally use experimental Swift Package Manager support instead:

<CodeGroup>
  ```shell CocoaPods (unchanged) theme={"theme":"github-dark-dimmed"}
  cd ios && pod install
  ```

  ```shell SPM (experimental, RN 0.87+) theme={"theme":"github-dark-dimmed"}
  cd ios && npx react-native spm --deintegrate
  ```
</CodeGroup>

## Check out these related resources:

* [React Native SDK reference](/docs/react-native)
* [React Native quickstart](/docs/react-native-quickstart)
* [React Native SDK GitHub release notes](https://github.com/fingerprintjs/react-native/releases)
* [Migrating the JS agent from v3 to v4](/reference/migrating-from-v3-to-v4)
* [Migrating the Server API from v3 to v4](/reference/migrating-from-server-api-v3-to-v4)
