← FingerprintCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Fingerprint
Snapshot Sep 30, 2026 · 23:11 UTC · version 1.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "fingerprint-javascript",
"description": "Integrate Fingerprint device identification into a vanilla JavaScript or plain HTML app with the JS Agent (@fingerprint/agent, npm or CDN) — initialize the agent and get the visitor's visitor_id and event_id. Use when there's no framework SDK — Vite, Webpack, a plain script tag, Solid, Lit, Alpine, htmx, or jQuery.",
"included_files": [
{
"relative_path": "skill.json",
"size_in_bytes": 286
},
{
"relative_path": "snippets/cdn.html",
"size_in_bytes": 630
},
{
"relative_path": "snippets/fingerprint.js",
"size_in_bytes": 525
},
{
"relative_path": "snippets/identify.js",
"size_in_bytes": 594
}
],
"skill_md_contents": "---\nname: fingerprint-javascript\ndescription: Integrate Fingerprint device identification into a vanilla JavaScript or plain HTML app with the JS Agent (@fingerprint/agent, npm or CDN) — initialize the agent and get the visitor's visitor_id and event_id. Use when there's no framework SDK — Vite, Webpack, a plain script tag, Solid, Lit, Alpine, htmx, or jQuery.\n---\n\n# Fingerprint — JavaScript\n\nIntegrate Fingerprint into a vanilla JavaScript app with the JS Agent directly: initialize the\nagent once at startup, then ask it for the visitor's `visitor_id` and a single-use `event_id`\nwherever you need it (on load, or on an action like login or checkout).\n\nUse this skill when there is no framework SDK to use. For React (or Preact), Vue, Angular, Svelte,\nor Next.js, use `fingerprint-react` / `fingerprint-vue` / `fingerprint-angular` /\n`fingerprint-svelte` / `fingerprint-nextjs` instead — they wrap this same agent with\nframework-native APIs and built-in caching.\n\n> Docs: https://docs.fingerprint.com/docs/javascript-quickstart · JS Agent v4: https://docs.fingerprint.com/reference/js-agent-v4\n\n## Package\n`@fingerprint/agent` — install the latest version. The npm package is a **loader**: it downloads\nthe current agent from the CDN at runtime rather than bundling the fingerprinting logic, so don't\nvendor or self-host the agent bundle. With no build step, skip the install and import from the CDN\ninstead — see `snippets/cdn.html`.\n\n> Fingerprint's CDN serves the agent at `/v4/<PUBLIC_API_KEY>`. A custom subdomain or proxy serves\n> it one level down, at `/web/v4/<PUBLIC_API_KEY>` — `/web/` is the path prefix the proxy uses to\n> separate agent downloads from identification requests on your own host, so the two URLs are\n> meant to differ. See `fingerprint-proxy-integration`.\n\n## Env var\n- `FINGERPRINT_PUBLIC_API_KEY` — the public key, safe to ship to the browser.\n\n> Bundlers only expose prefixed vars to client code — map the key to the bundler's convention:\n> - Vite: `VITE_FINGERPRINT_PUBLIC_API_KEY` → `import.meta.env.VITE_...`\n> - Webpack: inject with `DefinePlugin` / `EnvironmentPlugin` → `process.env.FINGERPRINT_...`\n> - No bundler: there is no env-var mechanism — the key goes in the CDN import URL and ships in the\n> HTML. That's fine for a public key; restrict it with `fingerprint-request-filtering`.\n> Never expose `FINGERPRINT_SECRET_API_KEY` to the frontend.\n\n## Steps\n\n1. **Install** `@fingerprint/agent` — or, with no build step, skip the install and import from the\n CDN (`snippets/cdn.html`) instead of adding a `package.json` the project doesn't have.\n\n2. **Initialize once at app startup.** Call `Fingerprint.start()` with the public key and region\n (`us` | `eu` | `ap`, matching the workspace), and export the instance so the rest of the app\n reuses it. `start()` returns the agent synchronously — the agent script downloads in the\n background and `get()` waits for it. Client-side only. See `snippets/fingerprint.js`.\n\n Prefer `import * as Fingerprint from '@fingerprint/agent'` over a default import — the namespace\n import tree-shakes better.\n\n3. **Get the identification where you need it.** Call `fp.get()`, which resolves to\n `{ visitor_id, event_id, ... }`. Each call is a billable identification event, so call it on the\n action you care about rather than on every page view. It accepts `{ tag, linkedId, timeout }`.\n See `snippets/identify.js`.\n\n4. **Verify it works.** Disable your ad blocker, run the dev server, trigger the call, and confirm\n a `visitor_id` is logged in the browser console (or that the event appears on the dashboard\n Events page).\n\n## Notes\n- Region must match the workspace (`us` | `eu` | `ap`).\n- Call `start()` once for the whole app; don't re-start per page or per action. In a SPA, keep the\n agent at module level so it survives client-side route changes — the deprecated\n `fingerprintjs-pro-spa` wrapper is not needed.\n- Don't block the UI on identification. `get()` rejects when the agent is blocked, offline, or\n times out — catch it, use `isFingerprintError(error)` and `error.code` to log the cause, and let\n the flow continue.\n- Caching is **off** by default. If you enable the `cache` option, a cache hit returns the *same*\n `event_id` (with `cache_hit: true`), which fails server-side freshness and one-time-use checks —\n keep `get()` uncached for security-relevant actions.\n- Don't run the agent in a sandboxed iframe; it isn't supported.\n- **Production:** protect the agent from ad blockers with a custom subdomain or proxy —\n https://docs.fingerprint.com/docs/protecting-the-javascript-agent-from-adblockers.\n- Don't use legacy `@fingerprintjs/fingerprintjs-pro`, `FingerprintJS.load()`, or `scriptUrlPattern`.\n"
}SHA-256: 40b19e2c0fef7a1c8e032d9d816a2f0d2147ca692fa60a238cf8f6faf6384889