JavaScript agent
FingerprintJS Pro JavaScript API. Not supported in Node.js, requires web browser to work.
The client-side agent is a high-performance JavaScript agent that collects multiple device and browser signals and sends them to the FingerprintJS Pro API for processing and identification.
Installing the agent
There are various ways to install the agent. No matter what you choose, the API will be the same.
CDN
This is the easiest way to start. It's also known as global variable. Add the following HTML code to your pages:
<script>
// Initialize the agent at application startup.
const fpPromise = import('https://fpcdn.io/v3/<<browserToken>>')
.then(FingerprintJS => FingerprintJS.load())
// Get the visitor identifier when you need it.
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
</script>
Put your public API key to the URL (right after /v3/
). You can get an API key at dashboard.fingerprintjs.com. An example script URL where the key is qwerty
: https://fpcdn.io/v3/qwerty
.
Alternatively, you can use a synchronous code that pauses the other scripts during loading and therefore is not recommended:
<script src="https://fpcdn.io/v3/<<browserToken>>/iife.min.js"></script>
<script>
// Initialize the agent at application startup.
var fpPromise = FingerprintJS.load()
// Get the visitor identifier when you need it.
fpPromise
.then(function (fp) { return fp.get() })
.then(function (result) { console.log(result.visitorId) })
</script>
UMD installation method designed for module loaders like RequireJS is also available:
require(
['https://fpcdn.io/v3/<<browserToken>>/umd.min.js'],
FingerprintJS => {
// Initialize an agent.
const fpPromise = FingerprintJS.load()
// Get the visitor identifier when you need it.
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
}
)
NPM
First install the agent NPM package:
npm install @fingerprintjs/fingerprintjs-pro
yarn add @fingerprintjs/fingerprintjs-pro
Then import the package into your code:
import * as FingerprintJS from '@fingerprintjs/fingerprintjs-pro'
// Initialize an agent at application startup.
const fpPromise = FingerprintJS.load({ apiKey: '<<browserToken>>' })
// Get the visitor identifier when you need it.
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
If you want to exclude the unused code from your application by tree-shaking, type import * as FingerprintJS from
instead of import FingerprintJS from
.
The NPM package comes with a TypeScript declaration for superior development experience. The package can be used with various module bundlers such as Webpack, Rollup.js or Browserify. If you face a TypeScript error that occurs in a FingerprintJS file, see the TypeScript support section.
Alternatively, you can use the legacy CommonJS standard:
const FingerprintJS = require('@fingerprintjs/fingerprintjs-pro')
// Initialize an agent at application startup.
const fpPromise = FingerprintJS.load({ apiKey: '<<browserToken>>' })
// Get the visitor identifier when you need it.
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
Agent initialization
You should create an agent when your page or application starts:
const fpPromise = FingerprintJS.load({ /* ... */ })
// fpPromise will resolve with `fp` object that you can use to call `fp.get()`
To configure the agent, pass parameters into the βloadβ function. The table below summarizes the parameters available. Below the table are detailed descriptions of each parameter
Parameter | Description |
---|---|
| Your public API key that authenticates the agent with the API. |
| Which region to use. |
| Server API URL. Should be only used with Subdomain integration. |
| Custom TLS endpoint. |
| Disables the extra TLS request. |
| Name of key to store data in visitor browsers. |
| Pattern of the JS agent script URL. |
Full list of parameters:
apiKey
default: no, required: yes for NPM installation
Public API key to authenticate the agent with the server API. You can get one at dashboard.fingerprintjs.com. If you login into this documentation portal via dashboard, you will be able to see your personal API key in the example below.
Example usage:
const fpPromise = FingerprintJS.load({ apiKey: "<<browserToken>>" })
The parameter is required for the NPM installation method and optional for the CDN (where the key is a part of the URL).
region
default: (depends on the API key), required: false
Available values: us
, eu
and ap
The region of your subscription. The parameter is fully optional because JS agent detects the regions automatically using the provided API key. Nevertheless, we recommend always specifying the parameter for a case when a part of our system is down. Otherwise the default region us
(which may mismatch your subscription) will be used in case of accident.
The parameter is ignored when both the endpoint
and tlsEndpoint
parameters are used.
Example:
const fpPromise = FingerprintJS.load({ region: 'eu' })
endpoint
default: no, required: false
This parameter should only be used with the Subdomain integration. Specify your custom endpoint here.
tlsEndpoint
default: no, required: false, since: v3.1.0
Your custom TLS endpoint URL address.
disableTls
default: no, required: false, since: v3.4.0
Set it to true
to disable the extra TLS request. This is not recommended as it will negatively affect your identification accuracy.
storageKey
default: '_vid', required: false
Name of key to store data in visitor browsers. The data is stored in cookies and local storage. You shouldn't change this parameter once your code runs in production because a change will cause the data in visitor browsers to be purged which will decrease identification accuracy.
scriptUrlPattern
default: 'https://fpnpmcdn.net/v<version>/<apiKey>/loader_v<loaderVersion>.js', required: false, only for NPM installation, since: v3.6.0
Pattern of the URL from where JS agent downloads the up-to-date identification JS code in runtime. By default JS agent downloads the code from our CDN. JS agent replaces the following substrings:
<version>
β the major version of JS agent;<apiKey>
β the public key set via theapiKey
parameter;<loaderVersion>
β the exact version of the@fingerprintjs/fingerprintjs-pro
package.
Visitor identification
Once an agent instance is initialized, you can start getting visitor identifiers. You are free to identify at any moment of time. You can configure FingerprintJS Pro to receive the identification data in the browser, on the server (via a webhook), or both.
Go to the extendedResult section to see the browser result format. The visitorId
field will contain an empty string when the visitor can't be identified, for example when it's a search bot.
Response objects contain a confidence score field that represents the probability of accurate identification. To learn more about how this value is calculated, go to Understanding your confidence score.
Below are a few examples of different approaches for identifying.
Automatic mode
In many cases you will use the automatic mode, because it's the simplest way to get started. The agent will get the data on every page load. You don't need to do anything else. Just add the call fp.get()
as soon as the agent is loaded:
const fpPromise = FingerprintJS.load(/* ... */)
const fp = await fpPromise
const result = await fp.get()
console.log(result.visitorId)
You can use both async/await
and promises to get a visitor identifier. Example of using promises:
const fpPromise = FingerprintJS.load(/* ... */)
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
When get()
is called, a FingerprintJS server will send a webhook request to your server.
Manual mode
Manual mode provides more granular control over how the identification requests are made. When you actually need to get visitor data (on a sign up event for example), call the .get()
method to get the data.
const fpPromise = FingerprintJS.load(/* ... */)
document.querySelector('#ad').addEventListener('click', async () => {
const fp = await fpPromise
const result = await fp.get()
console.log(result.visitorId)
})
const fpPromise = FingerprintJS.load(/* ... */)
document.querySelector('#ad').addEventListener('click', () => {
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
})
Search bots
The PRO API recognizes most well-known search bots (Google, Bing, Yahoo, Baidu, DuckDuckGo, and others) and treats them differently. Whenever a page is loaded by a search bot, an identification event is processed server-side, like it would with a normal visitor. The visitorId
field will contain an empty string, and the bot.safe
value will be true
(available when an extended result is requested). Note that the search bot identification requests are not billed by us.
Search bot detection example:
const result = await fp.get({ extendedResult: true })
if (!result.visitorId && result.bot && result.bot.safe) {
console.log('This is a search bot')
}
Parameters reference
tag
tag
tag
is a customer-provided value or an object that will be saved together with the identification event and will be returned back to you in a webhook message or when you search for the visit in the server API. You may want to use the tag
value to be able to associate a visit event with information from your current visitor's web request context or add any other information that is convenient for you.
Note that the tag
field is optional.
What values can be used as a tag
?
Any value that you need when processing a webhook event or that is useful when searching for visits in our server API. Scalar, string or object values can be sent.
For example you can pass a yourCustomId
as a tag
and then get this yourCustomId
back in the webhook, associated with a visitorId
.
Examples of using the tag
option:
// simple, scalar values
const yourCustomId = 2718281828
fp.get({ tag: yourCustomId })
// or a string value
const requestType = "signup"
// Example of sending and receiving the tag value
fp.get({ tag: yourCustomId })
// Webhook request
{
"visitorId": "nTxJ28Gt4CegeAwdWELL",
"tag": { "tag": 2718281828 },
// ...
}
// Note that tags are always objects, even when you use
// a regular scalar value.
// If you provide a scalar value, it will be converted to an object
// with `tag` attribute.
// You can also use a JavaScript object as a tag value
// and it will be returned back to you in a webhook.
//
// NOTE: nested objects are not supported in tag objects.
const requestMetadata = {
yourCustomId: 2718281828,
requestType: "signup"
}
// Making an API call and receiving a response via a webhook request
fp.get({ tag: requestMetadata })
// Webhook request
{
"visitorId": "nTxJ28Gt4CegeAwdWELL",
"tag": { "yourCustomId": 2718281828, "requestType": "signup" },
// ...
}
linkedId
linkedId
linkedId
is a way of linking current identification event with a custom identifier. This will allow you to filter visit information when using the Server API
Some examples of how you can use the linkedId:
- Link your website
userId
with a FingerprintJSvisitorId
to be able to analyze this data. - Link your e-commerce
orderId
with a FingerprintJSvisitorId
to be able to see the orders a visitor made. - Link a survey ID with a
visitorId
to ensure that the same visitor does not participate in a single survey multiple times. - Limit one visitor per item or one visitor per discount coupon.
// Making an API call
// Sending a linkedId value is helpful to filter by this value via server API
var orderId = 3936532456
fp.get({ linkedId: orderId })
// linkedId will be saved with this event and will be available to be queried later.
A linkedId
looks similar to tag
. When should you use each?
A tag
is an object that is "passed-through" and sent back to your webhook endpoint. A tag can contain an arbitrary number of attributes of any type (except for nested objects). You can use tags to store them in your database and use for any purpose. Tag
objects are meant to be consumed and processed by you eventually. You can think of a tag
object as metadata.
A linkedId
is a scalar, string identifier that gets indexed by FingerprintJS platform and can be used to filter visits efficiently. It's a way to create a custom index on your data and use that index to efficiently filter visits when querying them through the Server API. Objects or non-string values are not supported.
extendedResult
extendedResult
Two types of responses are supported: "default" and "extended". You don't need to pass any parameters to get the "default" response. "Extended" is an extended result format that includes geolocation, incognito mode and other information. It can be requested using the extendedResult: true
parameter.
The response object includes a confidence score field representing the probability of accurate identification. To learn more about how FingerprintJS calculates this value, please go to Understanding your confidence score.
The extended response object also includes several fields with useful timestamps related to a visitor. See more information on firstSeenAt/lastSeenAt
timestamps here.
Response object format is provided below. Every request has a unique requestId
that is returned in the response and is also available in API to query later. It is a convenient way to get specific identification events in the Server API.
fp.get()...
// response:
{
// requestId is different for every request
// it's a request identifier
"requestId": "8nbmT18x79m54PQ0GvPq",
// visitorId is the main browser identifier
"visitorId": "2JGu1Z4d2J4IqiyzO3i4",
// if true, this visitor was found and visited before
// if false, this visitor wasn't found and probably didn't visit before
"visitorFound": true,
// A number between 0 and 1 that tells how much the agent is sure about
// the visitor identifier. The higher the number, the higher the chance
// of the visitor identifier to be true.
"confidence": { "score": 0.995 }
}
fp.get({ extendedResult: true })...
// response:
{
"requestId": "8nbmT18x79m54PQ0GvPq",
"visitorId": "2JGu1Z4d2J4IqiyzO3i4",
"visitorFound": true,
"confidence": { "score": 0.995 },
"ip": "185.230.125.20",
"ipLocation": {
"accuracyRadius": 10,
"latitude": 47.3925,
"longitude": 8.4546,
"postalCode": "8010",
"timezone": "Europe/Zurich",
"city": {
"name": "Zurich"
},
"continent": {
"code": "EU",
"name": "Europe"
},
"country": {
"code": "CH",
"name": "Switzerland"
},
"subdivisions": [
{
"isoCode": "ZH",
"name": "Zurich"
}
]
},
"browserName": "Chrome",
"browserVersion": "75.0.3770",
"os": "Mac OS X",
"osVersion": "10.14.5",
"device": "Other",
"bot": { probability: 1, safe: true },
"incognito": false,
"firstSeenAt": {
"global": "2022-03-16T11:26:45.362Z",
"subscription": "2022-03-16T11:31:01.101Z"
},
"lastSeenAt": {
"global": "2022-03-16T11:28:34.023Z",
"subscription": null
}
}
timeout
timeout
Controls client-side timeout. Client timeout controls total time (both client-side and server-side) that any identification event is allowed to run. It doesn't include time when the page is in background (not visible) because browser may suspend identification process in background. By default it's 10 seconds. You can control the client-side timeout using timeout
configuration key. The timeout
option is in milliseconds. Example usage:
// A timeout of 20 seconds
// An example of the client-side timeout handling
try {
const result = await fp.get({ timeout: 20000 })
// ...
} catch (error) {
if (error.message === FingerprintJS.ERROR_CLIENT_TIMEOUT) {
console.log("A timeout of 20 seconds exceeded")
}
}
Error handling
JavaScript agent get
method returns a promise which will be rejected in case of an error. Below table summarizes possible types of errors that can lead to result promise rejections. See detailed information about the errors below the table.
Error | Short description |
---|---|
| FingerprintJS server connection error |
| FingerprintJS server request is aborted |
| Public API key is missing |
| Public API key is invalid |
| Public API key is expired |
| Bad FingerprintJS server request data. Can be caused by wrong TLS endpoint. |
| Bad FingerprintJS server response data. Can be caused by wrong endpoint. |
| General request server side failure |
| Client side timeout |
| Server request times out |
| Identification rate limit is exceeded |
| Identification request is blocked due to forbidden origin (see request filtering) |
| Identification request is blocked due to forbidden HTTP header (see request filtering) |
| Identification request is blocked due to forbidden |
| The region set in the agent options doesn't match the region that was used to create your subscription |
| Your subscription hasn't been activated in the dashboard or you've reached your free plan limit |
| The JS agent version is not supported |
| Failed to load the JS agent code. The error is available only for NPM installation. |
| The JS agent installation method is not allowed |
With the exception of ERROR_CLIENT_TIMEOUT
, ERROR_NETWORK_CONNECTION
and ERROR_NETWORK_ABORT
, all the errors described above will include the requestId
field. The get
method can also throw other unexpected errors, they should be treated as agent bugs.
Error handling example:
const fpPromise = FingerprintJS.load({ /* ... */ })
try {
const fp = await fpPromise
const result = await fp.get()
} catch (error) {
switch (error.message) {
case FingerprintJS.ERROR_GENERAL_SERVER_FAILURE:
console.log('Unknown server error. Request id:', error.requestId)
break
case FingerprintJS.ERROR_CLIENT_TIMEOUT:
console.log('Identification time limit of 10 seconds is exceeded')
break
default:
console.log('Other error')
}
}
const fpPromise = FingerprintJS.load({ /* ... */ })
fpPromise
.then(fp => fp.get())
.then(result => console.log(result.visitorId))
.catch(error => {
switch (error.message) {
case FingerprintJS.ERROR_GENERAL_SERVER_FAILURE:
console.log('Unknown server error. Request id:', error.requestId)
break
case FingerprintJS.ERROR_CLIENT_TIMEOUT:
console.log('Identification time limit of 10 seconds is exceeded')
break
default:
console.log('Other error')
}
})
The connection error occurs when the agent fails to connect to the server API. This can happen during a network outage or if a browser plugin blocks networking requests (e.g. AdBlock).
Timeouts
Two types of timeouts are possible: a server timeout and a client timeout.
Server timeout
The server timeout is fixed at 10 seconds of server-side processing time. If server-side processing exceeds 10 seconds for any reason, the promise will be rejected.
Client timeout
Client timeout controls total time (both client-side and server-side) that any identification event is allowed to run. By default it's 10 seconds. Note that even if the client-side timeout is exceeded, the server-side request can still be running, its results will just be discarded.
Rate limiting
Every subscription API key has a rate limit. It means that you cannot make more requests per second than your rate limit allows. Free subscription API keys have a limit of 3 requests/second (with 1 request/s being the default). You cannot increase that rate limit, unless you upgrade to a paid plan.
Paid subscriptions have a limit of 5 requests/second, which you can increase by emailing [email protected]. Whenever that rate limit is exceeded, a request is throttled and a special error is returned instead of the visitorId
value.
Supported browsers
The JS agent supports all popular browsers. See more details and learn how to run the agent in old browsers in the browser support guide.
TypeScript support
JS agent officially supports TypeScript version 4.0, but may work with newer and older versions of TypeScript. If you face a TypeScript error that occurs in a .d.ts
file provided by FingerprintJS (example 1, example 2), consider any of these solutions:
- Update the TypeScript package in your project to version 4.0 or newer
npm i [email protected]^4.0 # or yarn add [email protected]^4.0
- Prevent TypeScript from using the library types. To do it, replace
withimport ... from '@fingerprintjs/fingerprintjs-pro'
in yourimport ... from '@fingerprintjs/fingerprintjs-pro/dist/fp.esm.min'
.ts
files, and add the following line to a.d.ts
file (if there is no such file, create one anywhere with any name):declare module '@fingerprintjs/fingerprintjs-pro/dist/fp.esm.min'
Updated 3 days ago