# Device Fingerprint SDK

A privacy-focused, permission-less device fingerprinting library for modern browsers. Generates a stable, high-entropy device identifier using browser signals.

[中文版](./README.md)

## 📋 Core Principles (How it works)

Modern browsers optimize performance using underlying hardware (GPU, sound card) for rendering and computation. Due to differences in hardware manufacturers, driver versions, and operating system anti-aliasing strategies, even identical text and graphics render with microscopic binary differences that are barely noticeable to the human eye.

Device Fingerprint generates a highly unique hash string by combining multiple browser signals. This SDK uses 5 signal sources:

- 🎨 **Canvas Fingerprint** - Subtle differences in how GPUs and rendering engines draw graphics
- 🔊 **Audio Fingerprint** - Characteristic differences in audio stack processing waveforms
- 💻 **Hardware Features** - CPU cores, memory, platform, language, timezone, etc.
- 🎮 **WebGL Fingerprint** - GPU vendor, renderer model, and WebGL parameters
- 📝 **Font Detection** - List of 20 common installed system fonts

### 🔐 Entropy Estimation

The 5 signal sources combine to provide approximately 38 bits of entropy, theoretically distinguishing about 274 billion different devices.

## 📦 Installation

```bash
npm install device-fingerprint-js
```

## 🚀 Usage

### 1. Basic Usage (ES Module)

```javascript
import { generateFingerprint } from 'device-fingerprint-js';

// Generate fingerprint
const result = await generateFingerprint({
  canvas: true, // Enable Canvas fingerprinting
  audio: true, // Enable Audio fingerprinting
  webgl: true, // Enable WebGL fingerprinting
  fonts: true, // Enable font detection
  hardware: true, // Enable hardware features
});

console.log(result.deviceId);
// Output: "84e1b..." (16-character stable unique ID)
```

### 2. Vue.js Integration

#### Vue 3 Composition API

```vue
<template>
  <div>
    <h1>Device Fingerprint</h1>
    <p v-if="isLoading">Generating fingerprint...</p>
    <p v-else>Your Device ID: {{ deviceId }}</p>
    <button @click="generate">Regenerate</button>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { generateFingerprint } from 'device-fingerprint-js';

const deviceId = ref('');
const isLoading = ref(false);

async function generate() {
  isLoading.value = true;
  try {
    const result = await generateFingerprint();
    deviceId.value = result.deviceId;
  } catch (error) {
    console.error('Failed to generate fingerprint:', error);
  } finally {
    isLoading.value = false;
  }
}

// Generate on mount
onMounted(() => {
  generate();
});
</script>
```

#### Vue 2 Options API

```vue
<template>
  <div>
    <h1>Device Fingerprint</h1>
    <p v-if="isLoading">Generating fingerprint...</p>
    <p v-else>Your Device ID: {{ deviceId }}</p>
    <button @click="generate">Regenerate</button>
  </div>
</template>

<script>
import { generateFingerprint } from 'device-fingerprint-js';

export default {
  data() {
    return {
      deviceId: '',
      isLoading: false,
    };
  },
  mounted() {
    this.generate();
  },
  methods: {
    async generate() {
      this.isLoading = true;
      try {
        const result = await generateFingerprint();
        this.deviceId = result.deviceId;
      } catch (error) {
        console.error('Failed to generate fingerprint:', error);
      } finally {
        this.isLoading = false;
      }
    },
  },
};
</script>
```

### 3. React Integration

```jsx
import React, { useState, useEffect } from 'react';
import { generateFingerprint } from 'device-fingerprint-js';

function FingerprintComponent() {
  const [deviceId, setDeviceId] = useState('');
  const [isLoading, setIsLoading] = useState(true);

  async function generate() {
    setIsLoading(true);
    try {
      const result = await generateFingerprint();
      setDeviceId(result.deviceId);
    } catch (error) {
      console.error('Failed to generate fingerprint:', error);
    } finally {
      setIsLoading(false);
    }
  }

  useEffect(() => {
    generate();
  }, []);

  return (
    <div>
      <h1>Device Fingerprint</h1>
      {isLoading ? (
        <p>Generating fingerprint...</p>
      ) : (
        <>
          <p>Your Device ID: {deviceId}</p>
          <button onClick={generate}>Regenerate</button>
        </>
      )}
    </div>
  );
}

export default FingerprintComponent;
```

## 📄 Result Object

```javascript
{
  deviceId: '84e1b...',       // 16-character hex device ID
  entropyScore: 38,           // Estimated entropy in bits
  generationTimeMs: 123,      // Time taken to generate in milliseconds
  components: {               // Raw components used for generation
    canvas: 'abc123...',
    audio: '0.1234',
    webgl: 'NVIDIA Corporation|NVIDIA GeForce GTX...',
    fonts: 'Arial|Verdana|Times New Roman|...',
    hardware: { ... }
  },
  details: {                  // Additional detailed information
    canvasDataUrl: 'data:image/png;base64,...',
    webgl: 'NVIDIA Corporation|NVIDIA GeForce GTX...',
    fonts: ['Arial', 'Verdana', 'Times New Roman', ...],
    hardware: {
      concurrency: 8,
      memory: 16,
      platform: 'Win32',
      language: 'en-US',
      colorDepth: 24,
      pixelDepth: 24,
      timezoneOffset: 480
    }
  },
  _debug_featureString: 'canvas:abc123...;;audio:0.1234;;...' // Raw feature string used for hashing
}
```

## 🕵️ Privacy & Limits

- ✅ **Privacy-Friendly**
  SDK only collects device hardware properties (e.g., GPU, sound card processing characteristics) and system configurations, not sensitive privacy information like IP, geolocation, or specific device accounts.

- ✅ **Stable & Persistent**
  Doesn't rely on cookies or localStorage. Clearing cache or using incognito mode typically doesn't change the ID. Collection logic has been optimized for stability against environmental fluctuations like daylight saving time.

- ⚠️ **Anti-Fingerprinting Browsers**
  Some privacy-focused browsers (e.g., Tor, Brave) or Safari's "Prevent Cross-Site Tracking" feature intentionally add random noise to Canvas/Audio. This causes different IDs to be generated each time, which is a normal privacy protection mechanism.

## 📝 Configuration Options

```typescript
interface GenerateFingerprintOptions {
  canvas?: boolean; // Default: true
  audio?: boolean; // Default: true
  webgl?: boolean; // Default: true
  fonts?: boolean; // Default: true
  hardware?: boolean; // Default: true
}
```

## 🛠️ Browser Support

- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+

## 📄 License

MIT License

## 📚 Technical Details

### Signal Sources

1. **Canvas Fingerprint**
   - Renders mixed fonts, emojis, and graphics with various blending modes
   - Captures pixel data from different areas of the canvas
   - Uses MurmurHash3 for efficient hashing

2. **Audio Fingerprint**
   - Generates audio silently using Web Audio API
   - Applies oscillator and compressor effects
   - Captures subtle differences in audio stack processing

3. **WebGL Fingerprint**
   - Collects GPU vendor, renderer, and version information
   - Captures WebGL parameter values
   - Uses vendor-specific extensions when available

4. **Font Detection**
   - Tests for 20 common system fonts
   - Uses canvas measurements to detect font availability
   - Returns sorted list of available fonts

5. **Hardware Features**
   - CPU core count (hardwareConcurrency)
   - Device memory (deviceMemory)
   - Platform information
   - Language settings
   - Color depth and pixel depth
   - Timezone offset (stable, DST-adjusted)

## 🔧 Development

```bash
# Install dependencies
npm install

# Build TypeScript
npm run build

# Watch mode
npm run dev
```

## 📦 Package Structure

```
device-fingerprint-js/
├── dist/                  # Built files
│   ├── index.js           # Main entry (ES module)
│   ├── index.umd.js       # UMD format (supports script tag import)
│   ├── index.d.ts         # Type definitions
│   ├── index.js.map       # Source map
│   └── index.d.ts.map     # Type definition map
├── src/                   # Source files
│   ├── index.js           # Main implementation
│   └── index.d.ts         # Type definitions
├── package.json           # Package configuration
├── tsconfig.json          # TypeScript configuration
└── README.md              # Documentation
```
