A single asynchronous function that returns a browser fingerprint (8‑char hex) without requiring any user permission.
Live example here.
fingerprint— MurmurHash3 (32-bit, hex) of the stable stringified payload.elapsedMs— Execution time in milliseconds.- All collected signals are also spread on the returned object (e.g.
timezone,canvasID,webglID,languages, …).
- UA / platform:
vendor,platform,userAgentHighEntropy(UA Client Hints: architecture, bitness, platformVersion, model, fullVersionList). - Locale / Intl:
languages,timezone,timezoneOffset,numberingSystem,intlCalendar,hourCycle,intlSupportedCalendars. - Preferences:
reducedMotion,colorScheme,prefersContrast,prefersReducedTransparency,forcedColors. - Screen:
devicePixelRatio,pixelDepth,colorDepth,screenOrientation; on mobile:width,height,aspectRatio,maxTouchPoints. - Network:
connectionType,effectiveType,saveData(when available). - Device:
hardwareConcurrency,deviceMemory,touchSupport. - Media / codecs:
mediaCodecs(canPlayType for common MIME types),canvasID,webglID,webgpuID,audioID. - Other:
fonts(detected list),pdfViewerEnabled,webdriver,permissionsState(geolocation, notifications).
Signals that fail or are unavailable are set to null (no throw).
The function targets stock installations of:
- Google Chrome (desktop and Android)
- Mozilla Firefox (desktop, default tracking protection)
- Microsoft Edge (desktop and Android)
- Apple Safari (macOS)
- Safari on iOS / iPadOS
Assumptions:
- No privacy-focused extensions or add-ons.
- Browser privacy settings at factory defaults.
- No hardened or anti-detect browser variants.
Under these conditions the signals keep useful entropy; on Safari iOS or strict Firefox modes entropy can be lower. The script does not try to bypass intentional randomization or hardening.
// Import the default async function
import getBrowserFingerprint from 'get-browser-fingerprint'
// Call once; result holds fingerprint, elapsedMs, and all collected signals
const result = await getBrowserFingerprint()
// Log the 8-char hex fingerprint
console.log(result.fingerprint)
// Log execution time in milliseconds
console.log(result.elapsedMs)
// Or destructure to get only the fingerprint
const { fingerprint } = await getBrowserFingerprint()
console.log(fingerprint)Options:
debug(defaultfalse): append canvas / WebGL / audio debug elements todocument.bodyand include extra debug output.
const result = await getBrowserFingerprint({ debug: true })Load as ESM from a CDN:
<script type="module">
import getBrowserFingerprint from 'https://cdn.jsdelivr.net/npm/get-browser-fingerprint/+esm'
const { fingerprint, elapsedMs } = await getBrowserFingerprint()
console.log(fingerprint, elapsedMs)
</script>Or with a version pin:
<script type="module">
import getBrowserFingerprint from 'https://cdn.jsdelivr.net/npm/get-browser-fingerprint@latest/+esm'
const result = await getBrowserFingerprint()
console.log(result.fingerprint)
</script>Install and run tests:
fnm install
npm install -g corepack
corepack enable
corepack install
pnpm install
pnpm exec playwright install chromium
pnpm exec playwright install firefox
pnpm testRun the demo locally (serve src/):
pnpm serve -p 80 ./src
# or
npm run serveThen open http://localhost/index.html (or port 80 if using -p 80).
- Fingerprinting (MDN Glossary)
- HTTP Client hints (MDN)
- Intl.DateTimeFormat.resolvedOptions() (MDN)
- Intl.supportedValuesOf() (MDN)
- Mitigating Browser Fingerprinting (W3C)
- Navigator (MDN)
- NavigatorUAData.getHighEntropyValues() (MDN)
- NetworkInformation (MDN)
- Permissions API (MDN)
- Screen (MDN)
- User-Agent Client Hints API (MDN)
- Window.devicePixelRatio (MDN)