Self-hosted browser fingerprinting & bot detection
An open source library designed with real-world constraints in mind: anti-replay, payload encryption, optional obfuscation, and strong, low-noise signals.
Capabilities
Fast Bot Detection
Client-side detection of strong automation signals: navigator.webdriver, CDP markers, Playwright artifacts, Selenium properties, and more.
Browser Fingerprinting
Short-lived fingerprint designed for attack detection, clustering, and session correlation. JA4-inspired structured fingerprint ID.
Encrypted Payloads
Optional payload encryption to prevent trivial forgery. The encryption key is injected at build time, not shipped in plaintext.
Code Obfuscation
Optional obfuscation to raise the cost of reverse-engineering and make it harder to forge valid fingerprints without executing the code.
Cross-Context Validation
Detects inconsistencies across JavaScript execution contexts: main page, iframes, and web workers.
Anti-Replay
Built-in timestamp and nonce to prevent captured fingerprints from being replayed at scale.
Quick Start
// Install
npm install fpscanner
// Build with your encryption key + obfuscation
npx fpscanner build --key=your-secret-key
// Client-side: collect fingerprint
import FingerprintScanner from 'fpscanner';
const scanner = new FingerprintScanner();
const payload = await scanner.collectFingerprint();
// Send to your server for decryption and analysis
await fetch('/api/fingerprint', {
method: 'POST',
body: JSON.stringify({ fingerprint: payload }),
headers: { 'Content-Type': 'application/json' }
}); What It Detects
| Detection | Signal | Frameworks |
|---|---|---|
| hasWebdriver | navigator.webdriver === true | Selenium, Puppeteer, Playwright |
| hasWebdriverWritable | webdriver property descriptor | Puppeteer, Playwright |
| hasSeleniumProperty | document.$cdc_, $wdc_ | Selenium WebDriver |
| hasCDP | CDP runtime markers | Chrome DevTools Protocol |
| hasPlaywright | __playwright, __pw_* | Playwright |
| headlessChromeScreenResolution | 800Ă—600 default resolution | Headless browsers |
| hasMissingChromeObject | Missing window.chrome | Headless Chrome |
| hasImpossibleDeviceMemory | Unrealistic memory values | Spoofed environments |
| hasHighCPUCount | Unrealistic core count | VM/container environments |
| hasBotUserAgent | Known bot UA strings | Headless, crawlers |
| hasSwiftshaderRenderer | Software GPU renderer | Headless/CI |
| hasUTCTimezone | UTC timezone only | Headless, containers |
| hasWebdriverIframe | webdriver in iframe context | Cross-context bots |
| hasWebdriverWorker | webdriver in web worker | Cross-context bots |
| hasMismatchPlatformIframe | Platform differs main vs iframe | Cross-context bots |
| hasMismatchWebGLInWorker | WebGL renderer differs in worker | Cross-context bots |
A few examples—the library includes additional checks for cross-JavaScript context validation, GPU mismatches, and more.
Fingerprint ID (fsid)
The fsid is a JA4-inspired, locality-preserving fingerprint identifier. Unlike a simple hash, it is structured into semantic sections, making it both human-readable and useful for partial matching, similarity detection, and clustering.
FS1_<det>_<auto>_<dev>_<brw>_<gfx>_<cod>_<loc>_<ctx>
Try It Now
See FPScanner in action. The demo collects your browser fingerprint, sends the encrypted payload to the server for decryption, and displays the full results.
Run the Live Demo