Server-Side Verification

Validate fingerprints on your backend to prevent spoofing.

Why Server-Side Verification?

Client-side fingerprinting can be spoofed. A malicious user could intercept the SDK response and replay a different visitorId to your application. Always verify on the server before making trust decisions like granting trial access, processing payments, or allowing votes.

This guide covers verifying visitorId values from the Identify product. If you want to classify API callers directly on the server without a client SDK at all, see the Sentinel guide — it uses @fingerprintiq/server to inspect every incoming request at the middleware level.

Never trust client-side data alone. The visitorId sent from the browser is user-controlled. Verify it against the FingerprintIQ API using your server-side secret key.

The Verification Pattern

1

Identify on the client

Call fiq.identify() in the browser and get a visitorId.

2

Send the visitorId to your server

Include the visitorId in your API request body or as a header — not as a query parameter (avoid logging it in access logs).

3

Verify with the FingerprintIQ API

Fetch the visit history for that visitorId from the FingerprintIQ API using your server-side secret key.

4

Apply your trust logic

Check confidence, bot probability, recency, and any risk factors before making a decision.

Client Code

typescript
// 1. Identify the device const result = await fiq.identify(); const { visitorId, confidence, botProbability } = result; // 2. Send visitorId to your server with the user's request const response = await fetch('/api/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ visitorId }), }); const { verified } = await response.json();

Server Implementation

app.post('/api/verify', async (req, res) => {
  const { visitorId } = req.body;

  const fiqRes = await fetch(
    `https://api.fingerprintiq.com/v1/demo/visits/${visitorId}`,
    {
      headers: {
        'X-API-Key': process.env.FIQ_SECRET_KEY,
        'Content-Type': 'application/json',
      },
    }
  );

  const data = await fiqRes.json();
  const latestVisit = data.visits[0];

  const isLegitimate =
    data.totalVisits >= 1 &&
    latestVisit?.confidence >= 0.8 &&
    latestVisit?.botProbability < 0.3 &&
    Date.now() - latestVisit?.timestamp < 5 * 60 * 1000; // within 5 minutes

  res.json({ verified: isLegitimate, visits: data.totalVisits });
});

Security Best Practices

The checks below are layered defenses. Implement all of them — skipping any one check leaves a gap an attacker can exploit.

  1. Verify recency — Check that the latest visit timestamp is within the last 5 minutes. A visitorId from an hour ago should not grant access to a current session.

  2. Check confidence — Reject fingerprints with confidence below 0.7. Low confidence means too many signals failed to collect, which is itself suspicious.

  3. Monitor bot probability — Flag visitors with botProbability above 0.3 for review. Block those above 0.7.

  4. Check risk factors — Inspect the riskFactors array for signals like HEADLESS_BROWSER, TOR_EXIT_NODE, UA_TLS_MISMATCH, or SOFTWARE_RENDERER.

  5. Use server-side API keys only — The secret key used to call the FingerprintIQ API must never be exposed to the browser.

Store verified visitorId values in your session after the first verification. This avoids a round-trip to the FingerprintIQ API on every authenticated request while still establishing the initial trust anchor.

Ask a question... ⌘I