Browser fingerprinting has its own vocabulary. This page explains each word the WhiskerJS docs use, in one to three sentences first, then how WhiskerJS applies it. Each term has its own anchor, so you can link straight to it, for example /glossary/#farbling.
Anti-replay
Anti-replay is any measure that stops a recorded message from being accepted a second time. For device signals it means a result made once cannot be sent again later, or from another machine, and still pass.
WhiskerJS supports it with the optional binding: your server issues a single-use nonce and a timestamp, collect({ binding }) copies them into the result and adds a digest over the whole result. Your server checks that the nonce is its own, unused and recent, and that the digest matches.
See: Anti-replay binding, Nonce, Binding digest.
Automation globals
Automation globals are variables that browser automation tools leave on the page’s window or document, such as properties added by Selenium, PhantomJS or ChromeDriver. Their presence suggests the page is driven by a tool rather than a person.
WhiskerJS checks a list of 32 known global names, document properties starting with $cdc_, $wdc_ or cdc_, and webdriver, selenium or driver attributes on <html>. A hit sets the automation_globals flag.
See: automation_globals, WebDriver.
Binding digest
The binding digest is a 128-bit hash that WhiskerJS computes over a whole result, including the nonce and timestamp your server passed in. It lets your server notice whether the result was changed after it was made.
It is the first 128 bits of SHA-256 over the text that the exported bindingInput(result) returns. It is not a signature: code running in the page can compute it too, so it stops replay and accidental edits, not a forged result.
See: The digest, Anti-replay.
Browser class
A browser class is WhiskerJS’s own coarse label for the browser family: brave, firefox_rfp, firefox, safari, chromium or other. It is worked out from cheap, prompt-free hints such as navigator.brave, the user agent and navigator.vendor.
The class picks the row of the exclusion table and is reported as the browser_class component. It is a guess from values the client controls, so treat it as a hint.
See: browser_class, Browsers, Exclusion table.
Canvas fingerprinting
Canvas fingerprinting draws a fixed picture (text, shapes, colours) on an HTML canvas and reads the pixels back. Small differences in fonts, anti-aliasing and graphics stacks make the result differ between devices.
WhiskerJS’s canvas component draws a 260x80 scene with text, a cat emoji, blended circles and an even-odd ring, exports it with toDataURL() and reports only a digest.
See: canvas, Canvas noise, Double render.
Canvas noise
Canvas noise is small random change that a browser or extension adds to canvas or WebGL readback on purpose, so that the picture differs a little on every read. It defeats fingerprints that rely on an exact image.
WhiskerJS does not try to undo it. It detects it with the double render and reports the component as noisy; the separate canvas_readback probe reports exact or altered.
See: Noise handling, canvas_readback.
Clean iframe realm
A clean iframe realm is a fresh, untouched copy of the browser’s built-in objects, taken from a new about:blank iframe. Scripts that override functions usually do so only in the page, so the fresh copy shows the original behaviour.
WhiskerJS creates one hidden iframe with no src after the collectors finish, compares against it for the iframe_mismatch and prototype_lie checks, and removes it straight away. After an abort no iframe is made.
See: The clean iframe realm, Lie detection.
Client Hints
User-Agent Client Hints are a browser API (navigator.userAgentData) that reports the browser brands, platform and whether the device is mobile, with more detail available on request. It is offered by Chromium-based browsers.
WhiskerJS reads them into two components: ua_client_hints (brands without versions, platform, architecture and similar, in the visitorId) and ua_versions (full versions, outside both ids). Safari and Firefox do not offer the API, so both are unavailable there.
See: ua_client_hints, ua_versions, GREASE, High-entropy hints.
Collision
A collision is two different devices producing the same identifier. With browser fingerprints it happens when devices share the same hardware, software and settings, such as two identical phones on the same system version.
WhiskerJS’s ids describe a browser setup, not a person, so collisions are expected for identical setups. No collision rate is published yet: the measurement that could give one has not run.
See: Identifiers, Entropy.
Component
A component (also called a signal) is one measurement in a WhiskerJS result, such as the screen size or a digest of the installed fonts. Each component has a status and, when it was read, a value.
WhiskerJS reports 46 components, always all of them. 37 are stable and make up the ids; 9 are reported but kept out of the ids.
See: Signals, Statuses and reason codes.
Content blocker
A content blocker is a browser feature or extension that hides or blocks page elements and requests, typically ads and trackers. Cosmetic filters hide elements whose class names or ids look like ads.
WhiskerJS’s content_blockers component adds eight 1x1 bait elements off screen, waits 50 ms and reports which ones were hidden. It makes no request and is outside both ids, because users switch blockers on and off.
See: content_blockers.
Digest
A digest is a short, fixed-length hash computed from a larger value. It stays the same for the same input, but the input cannot be read back from it.
WhiskerJS uses the first 128 bits of SHA-256, written as 32 lowercase hex characters. Large values (images, audio samples, font lists and similar) leave the library only as a digest; a component carries hashed: true when its value is one.
See: Hashing, Web Crypto.
Double render
The double render is WhiskerJS’s way of noticing canvas and WebGL noise: it draws the same scene twice and compares the two results. Identical drawings should give identical output, so a difference means something adds randomness.
When the two differ, the component is noisy with ruleId render_mismatch and carries no value, which keeps the id the same from run to run instead of changing every time. It is used by canvas and webgl_image; audio has no double render.
See: Noise handling, Canvas noise.
Entropy
Entropy, in fingerprinting, measures how much a signal tells devices apart, usually in bits: a signal with more possible, evenly spread values has more entropy. It depends on the audience, so the same signal has different entropy on different sites.
WhiskerJS publishes no entropy figures for its signals: none have been measured yet. Expectations in the project roadmap are labelled as expectations.
Exclusion table
The exclusion table is the fixed list, per browser class, of components WhiskerJS does not collect because that browser randomises or normalises them on purpose. Such components report status excluded with the table’s ruleId.
Brave loses seven components (brave_farbling) and Firefox with resistFingerprinting nine (firefox_rfp). The table is exported as EXCLUSION_TABLE; changing it bumps signalsVersion.
See: The exclusion table, Farbling, resistFingerprinting.
Farbling
Farbling is Brave’s name for its fingerprinting protection: it adds small, per-site and per-session random changes to values such as canvas and audio output. A site sees stable values during a session, while different sites see different values.
WhiskerJS recognises Brave by navigator.brave.isBrave being a function and does not collect the farbled components (audio, canvas, fonts, fonts_canvas, hardware_concurrency, plugins, webgl_image); they report excluded with ruleId brave_farbling.
See: Brave, Exclusion table.
Font fingerprinting
Font fingerprinting finds out which fonts are installed by measuring text: a font that exists changes the width or height of text set in it, compared with a generic fallback. Installed fonts vary with the operating system, language packs and software.
WhiskerJS probes 54 families two ways, with hidden spans (fonts) and with canvas measureText() (fonts_canvas), and measures the default font settings (font_preferences). Only digests leave the library.
See: fonts, fonts_canvas, font_preferences.
GREASE
GREASE (Generate Random Extensions And Sustain Extensibility) is a deliberately fake brand that Chromium browsers add to their Client Hints brand list, with a name that changes between versions, such as “Not)A;Brand”. It keeps servers from depending on an exact list.
WhiskerJS removes it before using the brands: any brand that reads “notabrand” once reduced to letters is dropped, so the changing name does not change the id.
See: ua_client_hints, Client Hints.
Headless browser
A headless browser runs without a visible window, usually controlled by a script for testing, scraping or automation. Headless builds often differ in small ways from a normal browser.
WhiskerJS has two flags for it: headless_user_agent (the user agent contains HeadlessChrome, PhantomJS or SlimerJS) and headless_markers (outer window size 0x0, or a desktop Chrome user agent without window.chrome). Neither is a verdict.
See: headless_markers, headless_user_agent, Bot detection.
High-entropy hints
High-entropy hints are the detailed Client Hints values a page must ask for with navigator.userAgentData.getHighEntropyValues(), such as the CPU architecture, bitness, device model and full version list. The call does not prompt the user.
WhiskerJS makes one such request per collection. When a Permissions Policy refuses it, the component reports the stable marker he=blocked instead (or he=failed, he=none).
See: ua_client_hints, Permissions Policy.
idVersion
idVersion is the version number of how WhiskerJS derives the visitorId and structuredId from the components: the line encoding, the prefix and the groups. It is in every result.
A new idVersion gives every device a new id, because the prefix line contains it. The current idVersion is 2. Compare ids only within the same idVersion and signalsVersion.
See: Why versions bump, signalsVersion.
Integrity flag
An integrity flag is the name of a WhiskerJS check that fired, listed in result.integrityFlags. Each one is a sign that the page may be automated or that browser functions were changed.
There are 14 checks at signalsVersion 5. They are read-only, never a verdict, and their absence proves nothing: a client can remove them. Your server decides what they mean.
See: Integrity checks, Lie detection.
Lie detection
Lie detection looks for browser values or functions that were overridden to report something false, for example a spoofed user agent or a patched canvas function. It compares how a function prints and behaves with how a native one does.
WhiskerJS’s checks include native_tampering, navigator_own_property, prototype_lie and iframe_mismatch. Privacy extensions trigger them too, so a hit means “changed”, not “fraud”.
See: native_tampering, prototype_lie, Clean iframe realm.
Nonce
A nonce is a value used only once. In anti-replay, the server makes a fresh random nonce for each request and accepts it back only once.
WhiskerJS accepts a nonce of 8 to 128 printable ASCII characters without spaces and recommends at least 128 random bits, for example 32 hex characters from a cryptographic source. It reads no randomness of its own for the binding.
See: In the page, Anti-replay.
Offline audio rendering
Offline audio rendering asks the browser’s audio engine to compute sound into a buffer without playing it. The exact floating-point samples differ between engines, operating systems and CPUs.
WhiskerJS’s audio component renders a 10 kHz triangle wave through a dynamics compressor in an OfflineAudioContext (1 channel, 5000 frames at 44100 Hz) and hashes the last 500 samples. Nothing is played and no audio device is opened.
See: audio.
Permissions Policy
A Permissions Policy is a set of rules, sent by a site in an HTTP header or an iframe’s allow attribute, that decides which browser features a page or frame may use. It can, for example, refuse detailed Client Hints to an embedded frame.
When WhiskerJS’s high-entropy Client Hints request is refused this way, ua_client_hints and ua_versions end with the marker he=blocked instead of failing.
See: High-entropy hints, ua_client_hints.
Private Click Measurement
Private Click Measurement is a Safari (WebKit) feature for measuring ad clicks without cross-site tracking. Links can carry an attributionSourceId attribute for it.
WhiskerJS’s private_click component reads attributionSourceId from a new <a> element that gets no href and is never attached. Outside Safari it reports the plain value none.
See: private_click, Safari on macOS.
resistFingerprinting
privacy.resistFingerprinting is a Firefox setting, also used by Tor Browser, that makes the browser report fixed or normalised values (for example UTC as the time zone and the content area as the screen size) so that users look alike.
WhiskerJS classes Firefox as firefox_rfp only when every resistFingerprinting trait holds at once and navigator.webdriver is not true, and then does not collect nine components (ruleId firefox_rfp).
See: Firefox resistFingerprinting and Tor Browser, Exclusion table.
ruleId
A ruleId is the short reason code that WhiskerJS attaches to every component whose status is not ok, such as no_api, timeout or brave_farbling. It says why the value is missing.
A ruleId always matches ^[a-z0-9_]{1,32}$. The binding uses its own ruleIds (invalid_binding, invalid_nonce, invalid_timestamp, no_digest).
See: Statuses and reason codes.
Secure context
A secure context is a page the browser trusts to be delivered safely: served over https, or from http://localhost during development. Some APIs, including crypto.subtle, exist only there.
Without a secure context WhiskerJS cannot hash, so visitorId and structuredId are null and every component that must be hashed reports unavailable with ruleId no_digest.
See: Getting started, Web Crypto.
Signal group
A signal group is one of the seven sets the stable components are sorted into: gpu, audio, fonts, device, browser, locale and prefs. Each stable component belongs to exactly one group.
Each group gives one 12-hex part of the structuredId, so two results can be compared group by group. The groups are exported as ID_GROUPS and their order as ID_GROUP_ORDER.
See: structuredId, Signals.
signalsVersion
signalsVersion is the version number of what WhiskerJS measures: the collectors, the integrity checks and the exclusion table. It is in every result.
It goes up when a collector changes what it measures, a check changes or the exclusion table changes. A bump can change ids and flags. The current signalsVersion is 5.
See: What’s new, idVersion.
Software renderer
A software renderer draws graphics on the CPU instead of a GPU, for example SwiftShader, llvmpipe or Mesa’s offscreen renderer. It is common on servers, in containers and in virtual machines.
When the WebGL renderer or vendor names one, WhiskerJS sets the software_renderer flag. Real users with hardware acceleration turned off or remote desktops can trigger it too.
See: software_renderer, webgl_renderer.
Stability
Stability is how often a signal or identifier stays the same for the same device over time and across visits. A stable signal changes only with real changes, such as a new GPU driver or an installed font.
WhiskerJS keeps signals it expects to change easily (zoom, taskbar, permissions, keyboard layout, voices, versions and others) out of the ids. No stability figures are published yet; the early lab sample (signalsVersion 1, four device-browser pairs) is not a benchmark.
See: What changes the id, Stable component.
Stable component
A stable component is one of the 37 WhiskerJS components that are part of the visitorId and the structuredId. They were chosen because they are expected to change rarely for the same device.
In the code each collector has a stable flag. The other 9 components are still reported, but kept out of both ids.
See: Signals, Signal group.
Structured id
The structured id (structuredId) is WhiskerJS’s identifier made of seven short hashes, one per signal group, so two results can match in some groups and differ in others. It tells you which part of a device changed.
Its format is <idVersion>_<gpu>_<audio>_<fonts>_<device>_<browser>_<locale>_<prefs>, each part the first 48 bits (12 hex characters) of SHA-256. It is null without a digest.
See: structuredId, Comparing two results.
Visitor id
The visitor id (visitorId) is WhiskerJS’s single identifier: one 128-bit hash over the 37 stable components. Two results either have the same visitor id or not.
It describes a browser setup, not a person: two identical devices can share one, and one person with two browsers has two. It is null without Web Crypto, and comparable only within the same idVersion and signalsVersion.
See: visitorId, Structured id.
Web Crypto
Web Crypto is the browser’s built-in cryptography API, crypto.subtle. WhiskerJS uses only its digest function, for SHA-256.
It exists only in secure contexts. Without it, WhiskerJS never sends a raw large value: such components become unavailable with ruleId no_digest, and both ids are null.
See: Hashing, Secure context.
WebDriver
WebDriver is the standard protocol that tools such as Selenium use to control a browser. A browser under WebDriver control sets navigator.webdriver to true; Playwright and Puppeteer set it by default too.
WhiskerJS sets automation_webdriver when navigator.webdriver is true, and webdriver_writable when the property was redefined, usually to hide automation. Your own end-to-end tests set the first flag as well.
See: automation_webdriver, webdriver_writable.
WebGPU
WebGPU is a newer browser API for graphics and computation on the GPU, reached through navigator.gpu. Its adapter describes the GPU and its features and limits.
WhiskerJS’s webgpu component calls requestAdapter() (no prompt, no device requested) and hashes the adapter’s info, sorted features and seven limits. Without the API it is unavailable.
See: webgpu.