This guide shows how to migrate your code from FingerprintJS version 2 to version 4.
Please note that our licensing terms for v4 has changed. The table below indicates the different use-cases that shall require a commercial license to be purchased.
Before license change (versions 3.x and lower) | After license change (versions 4.x and higher) | |
---|---|---|
License | MIT | BSL 1.1 |
Use FingerprintJS for research, explorative and all other non-commercial purposes | ✅ | ✅ |
Fork FingerprintJS repository for production | ✅ | ❌ (requires a commercial license to be purchased) |
Use FingerprintJS in production | ✅ | ❌ (requires a commercial license to be purchased) |
To purchase a license for uses not authorized by BSL, please contact us at [email protected].
The support of Internet Explorer and some other browsers has been dropped. See the list of supported browsers in the browser support guide.
The migration process depends on the way you install the library.
Use the new URL: https://openfpcdn.io/fingerprintjs/v4/iife.min.js
Bower support is dropped, choose another installation method.
Update the package version:
npm install @fingerprintjs/fingerprintjs
# or
yarn add @fingerprintjs/fingerprintjs
The new version sends HTTP requests to collect usage statistics, they can be disabled. See this page for more details.
Remove the type declaration package. You don't need it because the type declaration is embedded into the main package in v4:
npm remove @types/fingerprintjs__fingerprintjs
# or
yarn remove @types/fingerprintjs__fingerprintjs
Version 4 doesn't require you to call requestIdleCallback
or setTimeout
manually.
Instead, you must call FingerprintJS.load()
.
This function returns a promise that resolves with an agent object.
The agent has a get
method that you will use instead of calling Fingerprint2.get
directly:
- requestIdleCallback(() => {
- Fingerprint2.get(result => {
+ const fpPromise = FingerprintJS.load()
+ fpPromise
+ .then(fp => fp.get()){
+ .then(result => {
// Handle the result
})
- })
Version 4 emits a complete visitor identifier, you don't need to derive it from the components by yourself:
fp.get().then(result => {
- const values = result.map(function (component) { return component.value })
- const visitorId = Fingerprint2.x64hash128(values.join(''), 31)
+ const visitorId = result.visitorId
})
If you need to get the raw components, you can, but the format is different:
const result = await fp.get()
console.log(result)
- [
- { key: 'ordinaryComponent', value: 'Some value' },
- { key: 'componentWithError', value: 'error' },
- { key: 'notAvailableComponent', value: 'not available' },
- { key: 'excludedComponent', value: 'excluded' },
- ],
+ {
+ visitorId: 'aStringWithAnIdentifier',
+ components: {
+ ordinaryComponent: { value: 'some value', duration: 4 },
+ componentWithError: { error: { message: 'This is the error object' }, duration: 2 },
+ notAvailableComponent: { value: undefined, duration: 1 },
+ excludedComponent: { value: 'Exclusion is not supported', duration: 10 },
+ }
+ }
Version 4 has no options for customization, it provides a good built-in setup. Nevertheless, you can exclude built-in entropy components and add custom entropy components manually. See the extending guide to learn more.
The identifiers produced by version 4 don't match the identifiers produced by version 2. If this is an issue for you, you can implement the following strategy.
Install version 4 together with version 2:
<script src="https://cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@2/dist/fingerprint2.min.js"></script>
<script src="https://openfpcdn.io/fingerprintjs/v4/iife.min.js"></script>
(if you prefer NPM or Yarn, see this note)
When you need the visitor identifier, get identifiers from both versions:
Promise.all([
new Promise(resolve => {
requestIdleCallback(() => {
Fingerprint2.get(resolve)
})
}),
FingerprintJS.load().then(fp => fp.get())
]).then(([v2Result, v4Result]) => {
// Handle both the results. For example, send to your server.
const v2VisitorId = Fingerprint2.x64hash128(
v2Result.map(component => component.value).join(''),
31
)
const v4VisitorId = v4Result.visitorId
return fetch(
'/visitor'
+ `?fingerprintV2=${encodeURIComponent(v2VisitorId)}`
+ `&fingerprintV4=${encodeURIComponent(v4VisitorId)}`
)
})
Make your server search using both the identifiers. Save the version 4 identifier:
-- Getting the visitor
SELECT * FROM visitors
WHERE
fingerprintV2 = :fingerprintV2 OR
fingerprintV4 = :fingerprintV4;
-- Update the visitor identifier
-- to switch to the fingerprint version 4
UPDATE visitors
SET fingerprintV4 = :fingerprintV4
WHERE fingerprintV2 = :fingerprintV2;
-- Saving a new visitor
INSERT INTO visitors (..., fingerprintV4)
VALUES (..., :fingerprintV4);
Later, when you get many enough identifiers of the version 4, remove the version 2 library and its identifiers.
The version 4 fingerprints may change after updating to a new major version, so you should extend this strategy to minor sub-versions of version 4 too.