type StorageAccessMode = 'off' | 'on-gesture'; interface optionsInterface { exclude?: string[]; include?: string[]; permissions_to_check?: PermissionName[]; timeout?: number; logging?: boolean; api_key?: string; cache_api_call?: boolean; performance?: boolean; stabilize?: string[]; experimental?: boolean; apiKey?: string; domain?: string; sessionId?: string; pageId?: string; extendedChecks?: boolean; fpcomApiKey?: string; fpcomDomain?: string; behaviour?: boolean; firstPartyBase?: string; storageAccess?: StorageAccessMode; stunUrl?: string; extChunk?: { url: string; sri?: string; }; loaderTimings?: { [key: string]: number | string; }; } /** * Behaviour summary for OTP / 3DS pages (EMB-2786). * * WHAT IT IS FOR. Fraud signals, not identity: was the one-time code pasted, autofilled from SMS or * typed with pauses and corrections; how long until the first interaction; did the user leave the * page (a code being dictated over the phone). On 4–6 digits behaviour cannot identify a device * (TypeNet: even 30 keystrokes give an EER of 8.6–14 %), so nothing here feeds device matching. * * WHAT IT NEVER RECORDS. Field values, `event.key`, `event.data`, coordinates, trajectories. Keys * are reduced to a class (digit / backspace / …), inserted text to its LENGTH, pointer movement to * speed and acceleration statistics. The suite asserts that the typed code does not appear anywhere * in the payload (tests/components/behaviour.spec.ts). * * HOW IT SITS ON A FOREIGN PAGE. Listeners are `passive: true` on `document` in the capture phase; * nothing is prevented, nothing is read from the DOM except the tag name and two attributes of the * event target. The raw event stream (type + class + relative time, no values) is kept only for the * 1 % sample of sessions and is capped at RAW_EVENT_CAP entries. * * HOW IT ARRIVES. Not in the main bundle: the collector ships in the optional chunk * (/cdn/fp-ext.js, see src/ext.ts) and starts when that has loaded. What the user did before that * is not seen; `collectorStartMs` says how long the gap was, and every time stays measured from * SDK start (`startedAt`), as it was when the collector started synchronously. * * LEGAL FRAME (EDPB Guidelines 3/2019 §§ 74–82): behavioural data becomes special-category biometric * data only when processed for the purpose of UNIQUELY IDENTIFYING a person. Classifying bot/human * and pasted/typed is not that purpose; the option is nevertheless OFF by default and must not be * enabled for a merchant before the legal document in EMB-2786 is signed off. */ type InputMethod = 'none' | 'typed' | 'paste' | 'autofill' | 'mixed'; type FlushReason = 'submit' | 'pagehide' | 'manual'; interface BehaviourSummary { inputMethod: InputMethod; /** A field with inputmode="numeric" or autocomplete="one-time-code" received input. */ otpFieldSeen: boolean; timeToFirstInteractionMs: number | null; timeToSubmitMs: number | null; durationMs: number; /** * When the listeners went on, from SDK start. The collector arrives with the optional chunk * (/cdn/fp-ext.js), so anything the user did before this point was not seen. */ collectorStartMs: number; keydownCount: number; backspaceCount: number; deleteCount: number; enterCount: number; inputEventCount: number; typedChars: number; pastedChars: number; autofilledChars: number; pasteCount: number; autofillCount: number; interKeyPauseMedianMs: number | null; interKeyPauseP90Ms: number | null; interKeyPauseMaxMs: number | null; focusChangeCount: number; visibilityHiddenCount: number; visibilityHiddenMs: number; visibilityHiddenMaxMs: number; /** Dominant PointerEvent.pointerType: mouse | touch | pen | '' */ pointerType: string; pointerMoveCount: number; /** px per ms between consecutive pointermove events. */ pointerSpeedMedian: number | null; pointerSpeedMax: number | null; pointerAccelMedian: number | null; touchCount: number; touchRadiusMedian: number | null; touchForceMedian: number | null; /** Share of pointerdown events whose target is not a form control. */ touchOutsideInputsShare: number | null; flushReason: FlushReason | null; eventsSampled: boolean; eventsTruncated: boolean; } /** * Third argument of the onComplete callback. * * `fingerprintExternal` is the Fingerprint.com visitorId — the same value, under the same name, * as `fingerprintExternal` in the antifraud public API rows. It is `null` when the fpcomApiKey / * fpcomDomain options are not set or the identification failed. Our own fingerprint hash is * deliberately absent: the server computes it, the browser never has it. */ interface CompleteResult { fingerprintExternal: string | null; } type CompleteCallback = (success: boolean, error?: string, result?: CompleteResult) => void; /** * A client for generating browser fingerprints with a persistent configuration. */ declare class Fingerprint { private options; private callback?; private isCollecting; private readonly constructedAtMs; private collectionPromise?; private behaviour; private behaviourFlushPending; private identity; private storageAccess; /** * Creates a new Fingerprint client instance. * @param options - Default configuration options for this instance. * If domain is provided, fingerprint will be automatically collected and sent. */ constructor(options?: optionsInterface); /** * Extracts client_transaction_id from URL query parameters * @returns sessionId or undefined */ private extractSessionIdFromUrl; /** * Collects fingerprint data and sends it to the configured domain */ private collectAndSend; /** * Sends encrypted fingerprint data to the server. * * The request is marked `keepalive` so it outlives the document: on a processing page the * redirect fires as soon as the page's own identification resolves, and an ordinary fetch in * flight dies with the page — a collection that finished a few milliseconds too late used to * be lost outright. `navigator.sendBeacon` is the fallback for the browsers and body sizes * `keepalive` does not cover; see utils/keepalivePost. * * @param data - Encrypted fingerprint result */ private sendToServer; /** * EMB-2786: the second POST. Fired from the collector on submit / pagehide, so it has to survive * the page going away: `fetch` with `keepalive` (64 KB budget — the summary is ~1 KB, the sampled * event stream ≤ 200 entries) and `credentials: 'include'` so the device cookie travels with it; * `navigator.sendBeacon` is the fallback where keepalive is unsupported. The budget and the * beacon live in utils/keepalivePost, shared with the payload POST. */ private sendBehaviour; /** * Smart Signals early attempt binding: POSTs {kind:'attempt_binding', encryptedData, hash} to * `${domain}/attempt-binding` the moment the Fingerprint.com identification (own run or the * loader's early hand-off) resolves with an id — usually while the components are still * running — so the backend can bind the attempt to the identification before this page's full * payload arrives. Once per collection, only on `ok`, fire-and-forget: never awaited by the * collection, never retried (the payload carries the same ids), errors swallowed. Same * credentials mode as the payload POST, so it rides the connection the payload will use. */ private sendAttemptBinding; /** * Current behaviour summary (EMB-2786), or null when the option is off or the collector has * not arrived yet (it ships in /cdn/fp-ext.js). Live: reflects the events seen so far, before * any flush. */ getBehaviourSummary(): BehaviourSummary | null; /** * Sends the behaviour summary now (once). Normally not needed: the SDK flushes on the form's * submit event and on pagehide. For single-page flows that never submit a form, call this when * the code has been accepted. Called before the collector has arrived, the flush happens as * soon as it starts. */ flushBehaviour(reason?: FlushReason): void; /** * Register a callback to be called when fingerprint collection and sending completes * @param callback - Function to call with success status, optional error message and the * {@link CompleteResult} (passed on success and on failure alike) */ onComplete(callback: CompleteCallback): void; } declare function getAudio(): Promise; declare function getCanvas(): Promise; declare function getFonts(options?: optionsInterface): Promise; declare function getHardware(): Promise; declare function getLocales(): Promise; declare function getMath(): Promise; declare function getPermissions(options?: optionsInterface): Promise; declare function getPlugins(): Promise; declare function getScreen(): Promise; declare function getSystem(): Promise; declare function getWebGL(): Promise; declare function getWebGLInfo(): Promise; declare function getSpeech(): Promise; declare function getClientHints(): Promise; declare function getStorageIds(): Promise; declare function getWebGPU(): Promise; declare function getMedia(): Promise; declare function getEnvironment(): Promise; declare function getCSSSupports(): Promise; /** * document.fonts.check() over the same font list the width probe uses (EMB-2787). * * A sibling of `fonts` rather than a key inside it: `fonts` is a flat {name: width} map that * ClickHouse stores as dc_fonts and the Go hash iterates by key — a `check` object there would * have become a "font" called check. Known caveat kept from the ticket: some engines answer true * for fonts they only stub, so this is a second opinion next to measureText, never a replacement. */ declare function getFontsCheck(): Promise; declare function getEngine(): Promise; declare function getTextMetrics(): Promise; declare function getIntegrity(options?: optionsInterface): Promise; declare function getHardwareProbe(): Promise; /** * Display and input facts a VPS farm does not have (EMB-2791): a second monitor * (screen.isExtended, Window Management API, no permission prompt) and the physical keyboard * layout map (Chromium desktop only). Absence of an API is a value of its own. */ declare function getDisplay(): Promise; /** * Battery API (EMB-2791). Not an identity signal (it changes every session) — an antidetect one: * a VPS farm has no battery, a phone always does. level rounded to 0.05. Deliberately excluded * from device linking (EMB-2779 non-goal). */ declare function getBattery(): Promise; declare function getRttClient(options?: optionsInterface): Promise; declare function getWebRTC(options?: optionsInterface): Promise; declare function getRenderWorker(options?: optionsInterface): Promise; declare function getCpuClass(): Promise; declare function getGpuTrace(): Promise; /** * This file is used to create the includeComponent function as well as the interfaces each of the * fingerprint components must implement. * */ /** * @description key->function map of built-in components. Do not call the function here. */ declare const tm_component_promises: { audio: typeof getAudio; canvas: typeof getCanvas; fonts: typeof getFonts; hardware: typeof getHardware; locales: typeof getLocales; math: typeof getMath; permissions: typeof getPermissions; plugins: typeof getPlugins; screen: typeof getScreen; speech: typeof getSpeech; system: typeof getSystem; webgl: typeof getWebGL; webglInfo: typeof getWebGLInfo; clientHints: typeof getClientHints; storageIds: typeof getStorageIds; webgpu: typeof getWebGPU; media: typeof getMedia; environment: typeof getEnvironment; cssSupports: typeof getCSSSupports; fontsCheck: typeof getFontsCheck; webrtc: typeof getWebRTC; engine: typeof getEngine; textMetrics: typeof getTextMetrics; integrity: typeof getIntegrity; hardwareProbe: typeof getHardwareProbe; display: typeof getDisplay; battery: typeof getBattery; rttClient: typeof getRttClient; }; /** * @description key->function map of experimental components (extendedChecks / `experimental`). * Each value loads the optional chunk on first call and runs the real component from it; when the * chunk is unavailable it resolves to `{ error: 'ext-chunk: ' }` (see utils/extChunk.ts). * The real implementations are registered by src/ext.ts under the same keys. */ declare const tm_experimental_component_promises: { mathml: componentFunctionInterface; wasm: componentFunctionInterface; timingCpu: componentFunctionInterface; timingMemory: componentFunctionInterface; vmSignals: componentFunctionInterface; }; /** * @description Components collected on a deterministic sample of sessions only (see * utils/sampling.ts), or on every session with extendedChecks: the hardware-class probes * (EMB-2784), too heavy for every session, and renderWorker, the release comparison of canvas / * fonts / webgl in a worker, whose code is in the optional chunk. */ declare const tm_sampled_component_promises: { cpuClass: typeof getCpuClass; gpuTrace: typeof getGpuTrace; renderWorker: typeof getRenderWorker; }; interface componentInterface { [key: string]: string | string[] | number | number[] | boolean | componentInterface; } interface componentFunctionInterface { (options?: optionsInterface): Promise; } /** * includeComponent is the function each custom component function needs to call in order for the component to be included * in the fingerprint. * @param {string} name - the name identifier of the component * @param {componentFunctionInterface} creationFunction - the function that implements the component * @returns nothing */ declare const includeComponent: (name: string, creationFunction: componentFunctionInterface, options?: optionsInterface) => void; /** * Main encrypted export pipeline * Combines compression, encryption, and HMAC fingerprinting */ /** * Result of encrypted fingerprint data */ interface EncryptedFingerprintResult { /** Base64-encoded encrypted and compressed data */ encryptedData: string; /** HMAC-SHA256 fingerprint hash (hex) from original JSON */ fingerprint: string; } /** * EmbermindFingerprint: Main fingerprinting and API logic * * This module handles component collection, API calls, uniqueness scoring, and data filtering * for the EmbermindFingerprint browser fingerprinting library. * */ /** * Final fingerprint response structure */ interface fingerprintResponse { components: componentInterface; info: { [key: string]: any; }; version: string; fingerprint: string; visitorId?: string; elapsed?: any; error?: string; experimental?: componentInterface; } /** * Main entry point: collects all components, optionally calls API, and returns fingerprint data. * * @param options - Options for fingerprinting and API * @returns fingerprintResponse (elapsed is present only if options.performance is true) */ declare function getFingerprint(options?: optionsInterface): Promise; /** * Returns ONLY encrypted data + fingerprint hash * No raw components exposed * * This is the main entry point for encrypted fingerprinting. * Returns only encrypted data and HMAC fingerprint hash. * * @param options - Fingerprint options * @returns Encrypted fingerprint data and hash */ declare function getFingerprintEncrypted(options?: optionsInterface): Promise; /** * Контекст страницы: открыта ли страница внутри чужого iframe и внутри какого webview. * * Это НЕ компонент фингерпринта, и он сознательно не регистрируется в tm_component_promises. * Клиентский хеш считается как HMAC-SHA256 по JSON ВСЕХ собранных компонентов * (см. utils/encryptedExport.ts): попади page-context в этот набор, и одно устройство давало бы * разные фингерпринты в зависимости от того, кто встроил страницу, а колонка fingerprint_client в * аналитике перестала бы означать устройство. Поэтому значение едет отдельным полем тела POST. * * location.ancestorOrigins есть в Chromium и WebKit, но отсутствует в Firefox. Поэтому факт * вложенности определяется независимо от цепочки, а isChainAvailable отличает «цепочку знаем» от * «во фрейме, но цепочку не знаем» — это разные состояния, и сливать их нельзя. */ type PageContextResult = { isNestedFrame: boolean; nestingDepth: number; isChainAvailable: boolean; ancestorOriginList: string[]; referrerOrigin: string | null; webviewMarkerList: string[]; }; declare function collectPageContext(): PageContextResult; export { type CompleteResult, Fingerprint, type PageContextResult, collectPageContext, getFingerprint, getFingerprintEncrypted, includeComponent, type optionsInterface, tm_component_promises, tm_experimental_component_promises, tm_sampled_component_promises };