> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fingerprintiq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK

Integrate FingerprintIQ into any JavaScript application.

## Installation

```bash npm
npm install @fingerprintiq/js
```

```bash yarn
yarn add @fingerprintiq/js
```

```bash pnpm
pnpm add @fingerprintiq/js
```

```html CDN
<script src="https://cdn.fingerprintiq.com/v1/fiq.min.js"></script>
<script>
  const fiq = new FingerprintIQ({ apiKey: 'fiq_live_...' });
  fiq.identify().then(result => console.log(result.visitorId));
</script>
```

## Basic Usage

```javascript
import FingerprintIQ from '@fingerprintiq/js';

const fiq = new FingerprintIQ({
  apiKey: 'fiq_live_your_key',
  endpoint: 'https://fingerprintiq.com', // default
  timeout: 10000, // 10 seconds (default)
  detectWallets: true, // detect Web3 wallets (default: true)
});

// Identify the current device
const result = await fiq.identify();
```

Instantiate `FingerprintIQ` once at module load time, not inside an event handler or on each page load. The instance is lightweight and reusable across multiple `identify()` calls.

## Configuration Options

Your API key from the dashboard. Use `fiq_live_` for production and `fiq_test_` for development. Test keys don't count toward your monthly quota.

API endpoint URL. Defaults to `https://fingerprintiq.com`. Override this if you're using a proxy or a self-hosted instance.

Request timeout in milliseconds. Defaults to `10000` (10 seconds). Increase this on slow networks or decrease it if you need faster failure.

Enable Web3 wallet detection. Defaults to `true`. Set to `false` to skip wallet enumeration and save ~50 ms if you don't need Web3 signals.

## Response Type

```typescript
interface IdentifyResponse {
  requestId: string;
  visitorId: string;
  confidence: number;
  botProbability: number;
  suspectScore: number;
  visitCount: number;
  firstSeenAt: number;
  lastSeenAt: number | null;
  riskFactors: string[];
  verdicts: {
    bot: { result: boolean; probability: number };
    vpn: { result: boolean; confidence: number };
    tor: { result: boolean };
    proxy: { result: boolean };
    incognito: { result: boolean };
    tampering: { result: boolean; anomalyScore: number };
    headless: { result: boolean };
    virtualMachine: { result: boolean };
    devtools: { result: boolean };
    privacyBrowser: { result: boolean; name: string | null };
    highActivity: { result: boolean };
    ipBlocklist: { result: boolean };
  };
  ip: string;
  ipLocation: {
    country: string;
    city: string;
    region: string;
    latitude: number;
    longitude: number;
  };
  sybilRisk?: { score: number; level: string; reasons: string[] };
  web3?: { walletsDetected: string[] };
  timestamp: number;
}
```

## Error Handling

```javascript
try {
  const result = await fiq.identify();
  // handle result
} catch (error) {
  if (error.message.includes('429')) {
    // Rate limited — retry after a delay, or show a fallback
    console.warn('FingerprintIQ rate limit hit');
  } else if (error.message.includes('401')) {
    // Invalid or missing API key — check your configuration
    console.error('Invalid FingerprintIQ API key');
  } else {
    // Network timeout or connectivity issue
    console.error('FingerprintIQ request failed:', error.message);
  }
}
```

If `identify()` fails, your application should degrade gracefully — don't block the user experience. Log the error and continue without the fingerprint when possible.

## Use Cases

**Free Trial Abuse Prevention**

```javascript
    const result = await fiq.identify();

    if (result.visitCount > 1) {
      // This device has been seen before — check trial status
      const hasUsedTrial = await checkTrialStatus(result.visitorId);
      if (hasUsedTrial) {
        showPaywall();
      }
    }
    ```

    Always verify `visitorId` server-side before making trial decisions. A client-side check is easy to bypass.
  **Bot Detection**

```javascript
    const result = await fiq.identify();

    if (result.botProbability > 0.7) {
      // Very likely a bot — block or hard challenge
      blockRequest();
    } else if (result.botProbability > 0.3) {
      // Suspicious — show CAPTCHA
      showCaptcha();
    } else if (result.botProbability > 0.1) {
      // Slightly elevated — increase monitoring
      logSuspiciousActivity(result);
    }
    ```
  **Web3 Sybil Detection**

```javascript
    const result = await fiq.identify();
    const wallets = result.web3?.walletsDetected ?? [];

    if (wallets.length > 0) {
      console.log('Detected wallets:', wallets);

      // Same device with multiple wallet addresses = potential Sybil
      if (result.visitCount > 5 && wallets.length > 1) {
        flagForReview(result.visitorId);
      }
    }
    ```

**Advanced: Custom proxy endpoint**

If you want to route FingerprintIQ traffic through your own domain (to avoid ad blockers or maintain a first-party relationship), set a custom endpoint:

  ```javascript
  const fiq = new FingerprintIQ({
    apiKey: 'fiq_live_...',
    endpoint: 'https://fp.yoursite.com', // proxy to fingerprintiq.com
  });
  ```

  Configure your proxy to forward requests to `https://fingerprintiq.com` and pass through the `X-API-Key` header. Cloudflare Workers make an excellent proxy layer for this pattern.