# FingerprintJS visitor ID changes: what a pass looks like

> A FingerprintJS visitor ID should differ per profile and hold across launches of one. Colliding ids link profiles; ids that change flag a spoofer.

Source: https://mosaicbrowser.com/blog/fingerprintjs-visitor-id-two-halves

## A FingerprintJS pass has two halves

A FingerprintJS visitor ID should differ per profile and hold across launches of one. Colliding ids link profiles; ids that change flag a spoofer.

![Launch 1 versus Launch 2, each name in its own tile: Different per profile, the same every launch](https://mosaicbrowser.com/covers/fingerprintjs-visitor-id-two-halves.webp)

A clean FingerprintJS result has two halves. Each profile gets a different visitor ID, and one profile gets the same visitor ID every time it is launched. Fail the first and two profiles that are meant to be two people can be linked without a single cookie. Fail the second and the profile's id changes from one launch to the next, which no ordinary browser does, so it reads as a spoofer. That is the pass line for the FingerprintJS row in our detection catalogue, and it is harder to measure than it sounds.

## Why a FingerprintJS visitor ID changes

FingerprintJS turns a long list of things a page can read into one identifier: screen, fonts, canvas and audio output, languages, timezone, hardware figures and more. The visitor ID is computed from all of it together, so when any one input reads differently the id can change.

On a real browser that happens for ordinary reasons. Install a font, switch on dark mode, add an extension, update the browser, and the id may move. Those changes are rare and they stick: the new id then holds until the next change.

The other reason an id changes is a privacy tool that adds fresh random noise each time a page reads the canvas or audio. Then the id changes on every visit, sometimes on every call. That defeats tracking by one id, and it hands the site a different signal instead, because a device whose canvas never draws the same picture twice is not a device anybody owns.

Mosaic is a desktop app

Email yourself the link and open it on your computer.

[How it works: Machines that exist](https://mosaicbrowser.com/features/real-fingerprints)

## Two failures, in opposite directions

The two halves of the pass are two separate mistakes an anti-detect browser can make.

**Collision.** Every profile on a machine shares the same hardware underneath. If a surface is passed through untouched, every profile reads the same value there, and enough shared values can produce the same visitor ID across profiles. We found one of those surfaces ourselves: the WebGL image was identical for every profile on the machine until we noised it per profile ([the same WebGL hash on every profile](https://mosaicbrowser.com/blog/webgl-hash-same-every-profile) has the measurement).

**Drift.** Noise that is drawn fresh at each launch, or at each read, fixes collision by making the id unstable. A logged-in account whose visitor ID is new every morning is telling the site something no real customer's laptop does.

So the noise has to be per profile and fixed. In Mosaic every profile's fingerprint is drawn from its own seed, and the same seed gives the same machine every time. The canvas noise is keyed on the colour of each pixel rather than its position, which is why the two ways a page can read a WebGL canvas agreed on 4096 of 4096 pixels and stayed stable across repeat reads when we measured it. Repairing a profile's hardware redraws the machine from that same seed and keeps its canvas identity, so a repair does not quietly turn the profile into a new visitor.

## What one run can and cannot tell you

Here is the awkward part. Both halves are facts about more than one run. Collision needs two profiles. Drift needs two launches. A single visit to the demo gives you one id, which proves neither.

Our runner is honest about that. On the FingerprintJS row it reads the panel the demo renders: the visitor ID, the confidence score, and the browser and operating system it names. From one run it asserts only what one run can show. If the panel did not render, the row is `unread`, not a pass. If the demo cannot name the browser, the row fails, for reasons that turned out to be about Google's branding rather than our fingerprint ([when FingerprintJS can't name your browser](https://mosaicbrowser.com/blog/fingerprintjs-cannot-name-browser) tells that story). If the confidence is under 0.9, the figure a stock browser scored, the row asks for attention. Otherwise it passes, and the detail line prints the visitor ID with a note that stability and uniqueness are not asserted from this run, so the id has to be compared against the previous report.

That is less satisfying than a green tick, and it is the true answer. A runner that declared a stability pass from one sample would be scoring a question it never asked. Two descriptions of the same fact had already drifted apart in this catalogue once, with rows marked automatic that nothing could read; the full count of how that happened is in [automating fingerprint tests](https://mosaicbrowser.com/blog/automating-fingerprint-tests).

## How to run the two halves yourself

It takes about five minutes, and it works for any browser, not only ours:

1. Open the FingerprintJS demo in profile A. Write down the visitor ID.
2. Close the browser completely and open profile A again. Read the id. It should be the same.
3. Open the demo in profile B. Its id should be different from A's.
4. Repeat step 2 for profile B once, so you know its id holds too.

If A's id changes between steps 1 and 2, something in the profile is being redrawn at launch. If A and B match, something they share is reaching the page unchanged. Either result is more useful than the demo's confidence score, because it is the part a site actually uses: the visitor ID is how it decides whether two visits are one person. How the rest of a profile's values are drawn to agree with each other is on [real fingerprints](https://mosaicbrowser.com/features/real-fingerprints).

## Questions

### Why does my FingerprintJS visitor ID change?

Because something it reads changed: a new font, dark mode turned on, an extension, a browser update, or a privacy tool that adds fresh random noise to every read. An id that changes on every visit is the last case, and it is the least like a real person.

### Should two browser profiles get different visitor IDs?

Yes. If two profiles that are meant to be separate people get the same visitor ID, a site using FingerprintJS can tie them together without any cookie.

### Is a visitor ID that changes every time good for privacy?

It stops one id from following you, but it makes the browser stand out. Real devices read the same from one visit to the next, so values that never repeat are a signal of their own.

### How do you test visitor ID stability yourself?

Open the FingerprintJS demo in one profile, note the id, close the browser and open it again, then read it again. Then do the same in a second profile. The first pair should match and the two profiles should differ.

## Related

[When the FingerprintJS demo can't name your browser](https://mosaicbrowser.com/blog/fingerprintjs-cannot-name-browser): FingerprintJS read 'Chromium-Based Browser Not Available' for our engine. We blamed the version; the real variable was Google's branding.

[Every profile on one Mac drew the same WebGL image](https://mosaicbrowser.com/blog/webgl-hash-same-every-profile): A WebGL fingerprint is the same in every browser profile on one machine because the GPU draws it. Ours was too, until per-profile noise moved the hash.

[Running 49 fingerprint tests unattended, and what that takes](https://mosaicbrowser.com/blog/automating-fingerprint-tests): To automate browser fingerprint testing, tell a failed profile from a dead site, an unreadable page and your own bug. Our runner names each across 49 rows.

[Machines that exist: fingerprints drawn from real hardware](https://mosaicbrowser.com/features/real-fingerprints): Mosaic draws each profile's GPU, screen, CPU, memory and fonts from one real device, so the parts of a fingerprint agree with each other and with the host.







[Same fonts, different measurements: per-profile glyph advances](https://mosaicbrowser.com/blog/glyph-advances-per-profile): Font fingerprint randomization can hide fonts or change how wide glyphs measure. Hiding read as masking; per-profile glyph advances did not.

## Mosaic, on your own computer

The browser this blog is about: its own Chromium, fingerprints from real machines and a proxy exit per profile. Free holds 3 profiles. Pro is $49 a month for any number.

Mosaic is a desktop app

Email yourself the link and open it on your computer.
