FingerprintJS

JavaScript agent

FingerprintJS Pro JavaScript API. Not supported in Node.js, requires Internet 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 usage will be the same.

Global variable

This is the easiest way to start. Add the following HTML code to your pages:

<script>
  function initFingerprintJS() {
    FingerprintJS.load({ token: 'your-browser-token' })
      .then(fp => fp.get())
      .then(result => console.log(result.visitorId));
  }
</script>
<script
  async
  src="//cdn.jsdelivr.net/npm/@fingerprintjs/[email protected]/dist/fp.min.js"
  onload="initFingerprintJS()"
></script>

You can get a token at dashboard.fingerprintjs.com.

ECMAScript module

We recommend this installation method. First install the agent NPM package:

npm install @fingerprintjs/fingerprintjs-pro
yarn add @fingerprintjs/fingerprintjs-pro

Then import the package into your code:

import FingerprintJS from '@fingerprintjs/fingerprintjs-pro'

FingerprintJS.load({ token: 'your-browser-token' })
  .then(fp => fp.get())
  .then(result => console.log(result.visitorId))

EcmaScript module comes with a TypeScript declaration for superior development experience. The module can be used with various module bundlers such as Webpack, Rollup.js or Browserify.

UMD

It's designed for module loaders like RequireJS. Use the following JS code:

require(
  ['//cdn.jsdelivr.net/npm/@fingerprintjs/[email protected]/dist/fp.umd.min.js'],
  (FingerprintJS) => {
    FingerprintJS.load({ token: 'your-browser-token' })
      .then(fp => fp.get())
      .then(result => console.log(result.visitorId))
  }
)

CommonJS

It's very similar to ECMAScript module, but it's legacy. First install the agent NPM package:

npm install @fingerprintjs/fingerprintjs-pro
yarn add @fingerprintjs/fingerprintjs-pro

Then import the package in your code:

const FingerprintJS = require('@fingerprintjs/fingerprintjs-pro')

FingerprintJS.load({ token: 'your-browser-token' })
  .then(fp => fp.get())
  .then(result => console.log(result.visitorId))

Agent initialization

const fp = await FingerprintJS.load({ /* ... */ })
// You can write a code that calls `fp.get()` here

This code creates an agent instance and puts it into the fp constant. You can use both async/await and promises to initialize an agent. Example of using promises:

FingerprintJS.load({ /* ... */ }).then(fp => {
 // You can write a code that calls `fp.get()` here
})

You should configure the agent. Pass configuration parameters into load function. A summary of all the parameters is provided below. You can also find detailed parameter information below.

ParameterDescription
tokenYour browser token that authenticates the agent with the API.
regionWhich region to use.
endpointServer API URL. Should be only used with CNAME or CloudFlare integrations.
tlsEndpointCustom TLS endpoint.
storageKeyName of key to store data in visitor browsers.

Full list of parameters:

token default: no, required: yes

Browser token to authenticate the agent with the server API. You can get one at dashboard.fingerprintjs.com.

Example usage:

const fp = await FingerprintJS.load({ token: "dXk12f271339d9ag93d" })

regiondefault: 'us', required: false

Available values: us and eu

The region of the FingerprintJS Pro servers you want to send data to. The default is us, which sends data to the N. Virginia server location. This parameter is ignored when endpoint and tlsEndpoint parameters are used.

Example:

const fp = await FingerprintJS.load({ region: "us" })

endpointdefault: no, requied: false

This parameter should only be used with the CNAME or CloudFlare integration. Specify your custom endpoint here.

tlsEndpointdefault: no, required: false, since: v3.1.0

Your custom TLS endpoint URL address.

storageKeydefault: '_vid', requied: 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.

Visitor identification

Once an agent instance is initialized, you can start getting visitor identification. You are free to identify at any moment of time. You can configure FingerprintJS Pro to receive the identification data in the browser, in 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 crawler bot.

There is a couple of examples of different approaches for identifying below.

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() right after the initialization code:

const fp = await FingerprintJS.load({ /* ... */ })
const result = await fp.get()
const visitorId = result.visitorId
console.log(visitorId)

You can use both async/await and promises to get a visitor identifier. Example of using promises:

FingerprintJS.load({ /* ... */ })
  .then(fp => fp.get())
  .then(result => {
    const visitorId = result.visitorId
    console.log(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 processed. When you actually need to get visitor data (on an Ad click for example), call the .get() method to get the data.

You can use both async/await and promises to send the data. Example of async/await:

const fp = await FingerprintJS.load({ /* ... */ })
document.querySelector('#ad').addEventListener('click', () => {
  const result = await fp.get()
  const visitorId = result.visitorId
  console.log(visitorId)
})

Example of identifying with promises:

FingerprintJS.load({ /* ... */ }).then(fp => {
  document.querySelector('#ad').addEventListener('click', () => {
    fp.get().then(result => {
      const visitorId = result.visitorId
      console.log(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). Crawl bot detection example:

const result = await fp.get({ extendedResult: true })
if (!result.visitorId && result.bot && result.bot.safe) {
  console.log('This is a crawl bot')
}

Parameters reference

tag

tag is a customer-provided value or an object that will be saved together with the visit and will be returned back to you in a webhook message or when you search for the visit in the visitor 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.

Is the tag field required?
No, it 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 visitor 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 provid a scalar value, it will 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 is a way of linking current identification event with a custom identifier. This can be helpful to be able to filter API visit information later.

Some examples of how you can use the linkedId:

  1. Link your website userId with a FPJS visitorId to be able to analyze this data.
  2. Link your e-commerce orderId with a FPJS visitorId to be able to see the orders a visitor made.
  3. Link a survey ID with a visitorId to ensure that the same visitor does not participate in a single survey multiple times.
  4. 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 FPJS 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 API. Objects or non-string values are not supported.

ipResolution

ipResolution is an option that controls the geolocation accuracy.

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 and can be requested using the extendedResult: true parameter.

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 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
}
fp.get({ extendedResult: true })...
// response:
{
  "requestId": "8nbmT18x79m54PQ0GvPq",
  "visitorId": "2JGu1Z4d2J4IqiyzO3i4",
  "visitorFound": true,
  "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
}
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")
  }
}
disableTls

Set to true to disable the extra TLS request.

debug

Set to true print debug messages to browser console.

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.

ErrorShort description
FingerprintJS.ERROR_NETWORK_CONNECTIONFingerprintJS server connection error
FingerprintJS.ERROR_NETWORK_ABORTFingerprintJS server request is aborted
FingerprintJS.ERROR_TOKEN_MISSINGToken is missing
FingerprintJS.ERROR_TOKEN_INVALIDToken is invalid
FingerprintJS.ERROR_TOKEN_EXPIREDToken expired
FingerprintJS.ERROR_BAD_REQUEST_FORMATBad FingerprintJS server request data. Can be caused by wrong TLS endpoint.
FingerprintJS.ERROR_GENERAL_SERVER_FAILUREGeneral request server side failure
FingerprintJS.ERROR_CLIENT_TIMEOUTClient side timeout
FingerprintJS.ERROR_SERVER_TIMEOUTServer request times out
FingerprintJS.ERROR_RATE_LIMITIdentification rate limit is exceeded

The get method can also throw other unexpected errors. They should be treated as agent bugs.

Error handling example:

const fp = FingerprintJS.load({ /* ... */ })
try {
  const result = await fp.get()
} catch (error) {
  switch (error.message) {
    case FingerprintJS.ERROR_NETWORK_CONNECTION:
      console.log('No network connection')
      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 account has a default rate limit of 10 requests / second. If you need to increase that value, email as at [email protected]. Whenever that rate limit is exceeded, a request is throttled and a special error is emitted.

Supported browsers

The JS agent supports all popular browsers. We use the following terminal command to decide which browsers to support:

npx browserslist "cover 95% in us, not IE < 10"

See more details and learn how to run the agent in old browsers in the browser support guide.

Updated 15 days ago

JavaScript agent


FingerprintJS Pro JavaScript API. Not supported in Node.js, requires Internet browser to work.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.