Back to blog
SecurityJanuary 1, 2024· 14 min read

Website Fingerprinting and Privacy Detection: A Developer's Guide

A practical Fusebox guide to website fingerprinting and privacy detection.

Website Fingerprinting and Privacy Detection: A Developer's Guide

Browser fingerprinting has become the invisible tracker of the modern web. Unlike cookies, which users can delete, fingerprinting creates a unique identifier from your browser's characteristics. Studies show that modern fingerprinting techniques can uniquely identify 99.24% of users. This guide reveals how fingerprinting works and how to detect and defend against it.

Why Privacy Detection Matters

In 2019, a study of the top 10,000 websites found that 70% employed some form of fingerprinting. Major companies use these techniques for fraud detection, but the same technology enables invasive tracking across the web. Understanding fingerprinting is essential for both protecting user privacy and implementing legitimate security measures.

Browser Fingerprint Analyzer

Comprehensive fingerprint detection tool:

// Browser Fingerprint Analyzer
const FingerprintAnalyzer = {
    fingerprint: {},
    
    // Collect all fingerprint data
    async collectFingerprint() {
        const start = performance.now();
        
        this.fingerprint = {
            timestamp: new Date().toISOString(),
            basic: await this.getBasicInfo(),
            screen: this.getScreenInfo(),
            browser: this.getBrowserInfo(),
            hardware: await this.getHardwareInfo(),
            webgl: this.getWebGLInfo(),
            audio: await this.getAudioInfo(),
            fonts: await this.getFontsInfo(),
            canvas: this.getCanvasFingerprint(),
            permissions: await this.getPermissionsInfo(),
            sensors: this.getSensorInfo(),
            network: this.getNetworkInfo(),
            battery: await this.getBatteryInfo(),
            timing: performance.now() - start
        };
        
        // Calculate uniqueness score
        this.fingerprint.uniqueness = this.calculateUniqueness();
        this.fingerprint.privacy = this.assessPrivacy();
        
        return this.fingerprint;
    },
    
    // Basic browser information
    async getBasicInfo() {
        return {
            userAgent: navigator.userAgent,
            language: navigator.language,
            languages: navigator.languages,
            platform: navigator.platform,
            cookieEnabled: navigator.cookieEnabled,
            doNotTrack: navigator.doNotTrack,
            hardwareConcurrency: navigator.hardwareConcurrency,
            maxTouchPoints: navigator.maxTouchPoints,
            vendor: navigator.vendor,
            vendorSub: navigator.vendorSub,
            product: navigator.product,
            productSub: navigator.productSub,
            onLine: navigator.onLine,
            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
            timezoneOffset: new Date().getTimezoneOffset(),
            sessionStorage: !!window.sessionStorage,
            localStorage: !!window.localStorage,
            indexedDB: !!window.indexedDB,
            openDatabase: !!window.openDatabase
        };
    },
    
    // Screen and display information
    getScreenInfo() {
        return {
            width: screen.width,
            height: screen.height,
            availWidth: screen.availWidth,
            availHeight: screen.availHeight,
            colorDepth: screen.colorDepth,
            pixelDepth: screen.pixelDepth,
            devicePixelRatio: window.devicePixelRatio,
            orientation: screen.orientation?.type,
            // Detect multiple monitors
            isExtended: screen.availWidth > screen.width || 
                       screen.availHeight > screen.height
        };
    },
    
    // Browser capabilities
    getBrowserInfo() {
        const info = {
            plugins: [],
            mimeTypes: [],
            features: {}
        };
        
        // Plugin detection
        if (navigator.plugins) {
            for (let i = 0; i < navigator.plugins.length; i++) {
                info.plugins.push({
                    name: navigator.plugins[i].name,
                    description: navigator.plugins[i].description,
                    filename: navigator.plugins[i].filename
                });
            }
        }
        
        // MIME types
        if (navigator.mimeTypes) {
            for (let i = 0; i < navigator.mimeTypes.length; i++) {
                info.mimeTypes.push(navigator.mimeTypes[i].type);
            }
        }
        
        // Feature detection
        info.features = {
            webRTC: !!(window.RTCPeerConnection || window.webkitRTCPeerConnection),
            webGL: !!window.WebGLRenderingContext,
            webGL2: !!window.WebGL2RenderingContext,
            webWorker: !!window.Worker,
            serviceWorker: 'serviceWorker' in navigator,
            sharedWorker: !!window.SharedWorker,
            audioContext: !!(window.AudioContext || window.webkitAudioContext),
            mediaDevices: !!navigator.mediaDevices,
            geolocation: !!navigator.geolocation,
            notifications: 'Notification' in window,
            bluetooth: 'bluetooth' in navigator,
            usb: 'usb' in navigator,
            midi: 'requestMIDIAccess' in navigator,
            clipboard: 'clipboard' in navigator,
            credentials: 'credentials' in navigator,
            mediaSession: 'mediaSession' in navigator,
            speechSynthesis: 'speechSynthesis' in window,
            vr: 'getVRDisplays' in navigator,
            ar: 'xr' in navigator
        };
        
        return info;
    },
    
    // Hardware fingerprinting
    async getHardwareInfo() {
        const info = {
            cpuClass: navigator.cpuClass,
            oscpu: navigator.oscpu,
            hardwareConcurrency: navigator.hardwareConcurrency
        };
        
        // Memory detection (Chrome only)
        if (navigator.deviceMemory) {
            info.deviceMemory = navigator.deviceMemory;
        }
        
        // Connection info
        if (navigator.connection) {
            info.connection = {
                effectiveType: navigator.connection.effectiveType,
                downlink: navigator.connection.downlink,
                rtt: navigator.connection.rtt,
                saveData: navigator.connection.saveData
            };
        }
        
        // Media devices
        try {
            const devices = await navigator.mediaDevices.enumerateDevices();
            info.mediaDevices = {
                audioinput: devices.filter(d => d.kind === 'audioinput').length,
                audiooutput: devices.filter(d => d.kind === 'audiooutput').length,
                videoinput: devices.filter(d => d.kind === 'videoinput').length
            };
        } catch (e) {
            info.mediaDevices = { error: 'Permission denied' };
        }
        
        return info;
    },
    
    // WebGL fingerprinting
    getWebGLInfo() {
        const canvas = document.createElement('canvas');
        const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
        
        if (!gl) {
            return { supported: false };
        }
        
        const info = {
            supported: true,
            vendor: gl.getParameter(gl.VENDOR),
            renderer: gl.getParameter(gl.RENDERER),
            version: gl.getParameter(gl.VERSION),
            shadingLanguageVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION),
            extensions: gl.getSupportedExtensions()
        };
        
        // Get WEBGL_debug_renderer_info if available
        const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
        if (debugInfo) {
            info.unmaskedVendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
            info.unmaskedRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
        }
        
        return info;
    },
    
    // Audio fingerprinting
    async getAudioInfo() {
        try {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const oscillator = audioContext.createOscillator();
            const analyser = audioContext.createAnalyser();
            const gainNode = audioContext.createGain();
            const scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);
            
            gainNode.gain.value = 0; // Mute
            oscillator.connect(analyser);
            analyser.connect(scriptProcessor);
            scriptProcessor.connect(gainNode);
            gainNode.connect(audioContext.destination);
            
            oscillator.start(0);
            
            return new Promise((resolve) => {
                let fingerprint = 0;
                scriptProcessor.onaudioprocess = (event) => {
                    const output = event.inputBuffer.getChannelData(0);
                    for (let i = 0; i < output.length; i++) {
                        fingerprint += Math.abs(output[i]);
                    }
                    
                    oscillator.stop();
                    audioContext.close();
                    
                    resolve({
                        fingerprint: fingerprint.toString(),
                        sampleRate: audioContext.sampleRate,
                        maxChannelCount: audioContext.destination.maxChannelCount,
                        numberOfInputs: audioContext.destination.numberOfInputs,
                        numberOfOutputs: audioContext.destination.numberOfOutputs,
                        channelCount: audioContext.destination.channelCount,
                        channelCountMode: audioContext.destination.channelCountMode,
                        channelInterpretation: audioContext.destination.channelInterpretation
                    });
                };
            });
        } catch (e) {
            return { error: e.message };
        }
    },
    
    // Font fingerprinting
    async getFontsInfo() {
        const baseFonts = ['monospace', 'sans-serif', 'serif'];
        const testString = 'mmmmmmmmmmlli';
        const testSize = '72px';
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        
        const baseFontWidths = {};
        
        // Measure base fonts
        baseFonts.forEach(baseFont => {
            context.font = `${testSize} ${baseFont}`;
            baseFontWidths[baseFont] = context.measureText(testString).width;
        });
        
        // Test fonts
        const fonts = [
            'Arial', 'Arial Black', 'Arial Hebrew', 'Arial MT', 'Arial Narrow',
            'Comic Sans MS', 'Courier', 'Courier New', 'Georgia', 'Helvetica',
            'Impact', 'Lucida Console', 'Lucida Sans Unicode', 'Microsoft Sans Serif',
            'Monaco', 'Palatino', 'Tahoma', 'Times', 'Times New Roman', 'Trebuchet MS',
            'Verdana', 'Wingdings', 'Wingdings 2', 'Wingdings 3'
        ];
        
        const detectedFonts = [];
        
        fonts.forEach(font => {
            const detected = baseFonts.some(baseFont => {
                context.font = `${testSize} ${font}, ${baseFont}`;
                const width = context.measureText(testString).width;
                return width !== baseFontWidths[baseFont];
            });
            
            if (detected) {
                detectedFonts.push(font);
            }
        });
        
        return {
            count: detectedFonts.length,
            fonts: detectedFonts
        };
    },
    
    // Canvas fingerprinting
    getCanvasFingerprint() {
        const canvas = document.createElement('canvas');
        canvas.width = 280;
        canvas.height = 60;
        const context = canvas.getContext('2d');
        
        // Draw test content
        context.fillStyle = '#f60';
        context.fillRect(125, 1, 62, 20);
        
        context.fillStyle = '#069';
        context.font = '11pt Arial';
        context.fillText('Canvas fingerprint test 🙃', 2, 15);
        
        context.fillStyle = 'rgba(102, 204, 0, 0.7)';
        context.font = '18pt Arial';
        context.fillText('BrowserLeaks.com', 4, 45);
        
        // Get canvas data
        const dataURL = canvas.toDataURL();
        
        // Calculate hash
        let hash = 0;
        for (let i = 0; i < dataURL.length; i++) {
            const char = dataURL.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & hash; // Convert to 32-bit integer
        }
        
        return {
            hash: hash.toString(),
            dataLength: dataURL.length
        };
    },
    
    // Permission API fingerprinting
    async getPermissionsInfo() {
        const permissions = {};
        const permissionNames = [
            'geolocation', 'notifications', 'push', 'midi', 'camera',
            'microphone', 'speaker', 'device-info', 'background-sync',
            'bluetooth', 'persistent-storage', 'ambient-light-sensor',
            'accelerometer', 'gyroscope', 'magnetometer', 'clipboard'
        ];
        
        for (const permission of permissionNames) {
            try {
                const result = await navigator.permissions.query({ name: permission });
                permissions[permission] = result.state;
            } catch (e) {
                permissions[permission] = 'not-supported';
            }
        }
        
        return permissions;
    },
    
    // Sensor API detection
    getSensorInfo() {
        return {
            accelerometer: 'Accelerometer' in window,
            gyroscope: 'Gyroscope' in window,
            magnetometer: 'Magnetometer' in window,
            absoluteOrientationSensor: 'AbsoluteOrientationSensor' in window,
            relativeOrientationSensor: 'RelativeOrientationSensor' in window,
            ambientLightSensor: 'AmbientLightSensor' in window,
            proximirtySensor: 'ProximitySensor' in window
        };
    },
    
    // Network information
    getNetworkInfo() {
        const info = {
            onLine: navigator.onLine
        };
        
        if ('connection' in navigator) {
            const conn = navigator.connection;
            info.connection = {
                effectiveType: conn.effectiveType,
                downlink: conn.downlink,
                downlinkMax: conn.downlinkMax,
                rtt: conn.rtt,
                type: conn.type,
                saveData: conn.saveData
            };
        }
        
        return info;
    },
    
    // Battery API
    async getBatteryInfo() {
        if ('getBattery' in navigator) {
            try {
                const battery = await navigator.getBattery();
                return {
                    charging: battery.charging,
                    chargingTime: battery.chargingTime,
                    dischargingTime: battery.dischargingTime,
                    level: battery.level
                };
            } catch (e) {
                return { error: 'Not available' };
            }
        }
        return { supported: false };
    },
    
    // Calculate uniqueness score
    calculateUniqueness() {
        let score = 0;
        let factors = 0;
        
        // Factors that increase uniqueness
        const uniqueFactors = {
            screenResolution: 10,
            timezone: 5,
            plugins: 15,
            fonts: 20,
            canvas: 25,
            webgl: 20,
            audio: 15
        };
        
        // Check each factor
        if (this.fingerprint.screen) {
            const resolution = `${this.fingerprint.screen.width}x${this.fingerprint.screen.height}`;
            if (!['1920x1080', '1366x768', '1440x900'].includes(resolution)) {
                score += uniqueFactors.screenResolution;
            }
            factors++;
        }
        
        if (this.fingerprint.basic?.timezone) {
            score += uniqueFactors.timezone;
            factors++;
        }
        
        if (this.fingerprint.browser?.plugins.length > 3) {
            score += uniqueFactors.plugins;
            factors++;
        }
        
        if (this.fingerprint.fonts?.count > 15) {
            score += uniqueFactors.fonts;
            factors++;
        }
        
        if (this.fingerprint.canvas?.hash) {
            score += uniqueFactors.canvas;
            factors++;
        }
        
        if (this.fingerprint.webgl?.unmaskedRenderer) {
            score += uniqueFactors.webgl;
            factors++;
        }
        
        if (this.fingerprint.audio?.fingerprint) {
            score += uniqueFactors.audio;
            factors++;
        }
        
        return {
            score: Math.min(100, score),
            factors: factors,
            rating: score > 80 ? 'Very High' : 
                   score > 60 ? 'High' : 
                   score > 40 ? 'Medium' : 
                   score > 20 ? 'Low' : 'Very Low'
        };
    },
    
    // Assess privacy level
    assessPrivacy() {
        const issues = [];
        const recommendations = [];
        
        // Check for privacy issues
        if (this.fingerprint.basic?.doNotTrack !== '1') {
            issues.push('Do Not Track is not enabled');
            recommendations.push('Enable Do Not Track in browser settings');
        }
        
        if (this.fingerprint.canvas?.hash) {
            issues.push('Canvas fingerprinting is possible');
            recommendations.push('Use browser extensions that block canvas fingerprinting');
        }
        
        if (this.fingerprint.webgl?.unmaskedRenderer) {
            issues.push('WebGL reveals hardware information');
            recommendations.push('Consider disabling WebGL for privacy');
        }
        
        if (this.fingerprint.browser?.plugins.length > 0) {
            issues.push('Browser plugins are detectable');
            recommendations.push('Minimize browser plugins/extensions');
        }
        
        if (this.fingerprint.fonts?.count > 20) {
            issues.push('Many unique fonts detected');
            recommendations.push('Use default system fonts only');
        }
        
        return {
            score: Math.max(0, 100 - (issues.length * 15)),
            issues,
            recommendations,
            rating: issues.length === 0 ? 'Excellent' :
                   issues.length <= 2 ? 'Good' :
                   issues.length <= 4 ? 'Fair' : 'Poor'
        };
    }
};

// Run fingerprint analysis
FingerprintAnalyzer.collectFingerprint().then(console.log);

Tracking Detection System

Detect various tracking methods:

// Comprehensive Tracking Detector
const TrackingDetector = {
    detectedTrackers: {
        cookies: [],
        localStorage: [],
        fingerprinting: [],
        pixels: [],
        beacons: []
    },
    
    // Start detection
    async detectTracking() {
        console.log('Starting tracking detection...');
        
        this.detectCookies();
        this.detectLocalStorage();
        this.detectFingerprinting();
        this.detectTrackingPixels();
        this.detectBeacons();
        await this.detectThirdPartyRequests();
        
        return this.generateReport();
    },
    
    // Detect tracking cookies
    detectCookies() {
        const cookies = document.cookie.split(';');
        const trackingPatterns = [
            '_ga', '_gid', '__utm', '_fbp', '_gcl', 'IDE', 'NID',
            'fr', 'tr', '_pinterest', '_twitter', 'personalization_id'
        ];
        
        cookies.forEach(cookie => {
            const [name, value] = cookie.trim().split('=');
            
            // Check for tracking patterns
            const isTracker = trackingPatterns.some(pattern => 
                name.toLowerCase().includes(pattern.toLowerCase())
            );
            
            if (isTracker) {
                this.detectedTrackers.cookies.push({
                    name,
                    value: value?.substring(0, 20) + '...',
                    type: this.identifyTrackerType(name),
                    domain: window.location.hostname
                });
            }
        });
    },
    
    // Detect localStorage tracking
    detectLocalStorage() {
        const suspiciousKeys = [];
        
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            
            // Check for tracking patterns
            if (key.includes('track') || key.includes('analytics') || 
                key.includes('_ga') || key.includes('user_id') ||
                key.includes('session') || key.includes('visitor')) {
                
                suspiciousKeys.push({
                    key,
                    size: localStorage.getItem(key).length,
                    type: 'localStorage tracking'
                });
            }
        }
        
        this.detectedTrackers.localStorage = suspiciousKeys;
    },
    
    // Detect fingerprinting attempts
    detectFingerprinting() {
        const fingerprintingAPIs = {
            canvas: this.detectCanvasFingerprinting(),
            webgl: this.detectWebGLFingerprinting(),
            audio: this.detectAudioFingerprinting(),
            fonts: this.detectFontFingerprinting()
        };
        
        Object.entries(fingerprintingAPIs).forEach(([type, detected]) => {
            if (detected) {
                this.detectedTrackers.fingerprinting.push({
                    type,
                    detected: true,
                    details: detected
                });
            }
        });
    },
    
    // Detect canvas fingerprinting
    detectCanvasFingerprinting() {
        const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
        const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
        let canvasRead = false;
        
        // Override methods temporarily
        HTMLCanvasElement.prototype.toDataURL = function(...args) {
            canvasRead = true;
            return originalToDataURL.apply(this, args);
        };
        
        CanvasRenderingContext2D.prototype.getImageData = function(...args) {
            canvasRead = true;
            return originalGetImageData.apply(this, args);
        };
        
        // Create test canvas
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        ctx.fillText('test', 0, 0);
        
        // Restore original methods
        HTMLCanvasElement.prototype.toDataURL = originalToDataURL;
        CanvasRenderingContext2D.prototype.getImageData = originalGetImageData;
        
        return canvasRead ? 'Canvas reading detected' : false;
    },
    
    // Detect WebGL fingerprinting
    detectWebGLFingerprinting() {
        const canvas = document.createElement('canvas');
        const gl = canvas.getContext('webgl');
        
        if (gl) {
            const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
            if (debugInfo) {
                return 'WebGL debug info accessible';
            }
        }
        
        return false;
    },
    
    // Detect audio fingerprinting
    detectAudioFingerprinting() {
        return 'AudioContext' in window || 'webkitAudioContext' in window;
    },
    
    // Detect font fingerprinting
    detectFontFingerprinting() {
        // Check if fonts are being measured
        const originalMeasureText = CanvasRenderingContext2D.prototype.measureText;
        let fontMeasured = false;
        
        CanvasRenderingContext2D.prototype.measureText = function(...args) {
            fontMeasured = true;
            return originalMeasureText.apply(this, args);
        };
        
        // Restore
        setTimeout(() => {
            CanvasRenderingContext2D.prototype.measureText = originalMeasureText;
        }, 100);
        
        return fontMeasured;
    },
    
    // Detect tracking pixels
    detectTrackingPixels() {
        const images = document.querySelectorAll('img');
        const pixels = [];
        
        images.forEach(img => {
            // Check for 1x1 pixels
            if ((img.width === 1 && img.height === 1) || 
                (img.naturalWidth === 1 && img.naturalHeight === 1) ||
                img.src.includes('pixel') || img.src.includes('track')) {
                
                pixels.push({
                    src: img.src,
                    type: 'tracking pixel',
                    domain: new URL(img.src).hostname
                });
            }
        });
        
        this.detectedTrackers.pixels = pixels;
    },
    
    // Detect beacon API usage
    detectBeacons() {
        const originalSendBeacon = navigator.sendBeacon;
        const beacons = [];
        
        // Override sendBeacon
        navigator.sendBeacon = function(url, data) {
            beacons.push({
                url,
                data: data ? 'Data sent' : 'No data',
                timestamp: new Date().toISOString()
            });
            
            console.warn('Beacon detected:', url);
            return originalSendBeacon.apply(navigator, arguments);
        };
        
        // Restore after detection period
        setTimeout(() => {
            navigator.sendBeacon = originalSendBeacon;
            this.detectedTrackers.beacons = beacons;
        }, 5000);
    },
    
    // Detect third-party requests
    async detectThirdPartyRequests() {
        const requests = performance.getEntriesByType('resource');
        const thirdParty = [];
        const currentDomain = window.location.hostname;
        
        requests.forEach(request => {
            try {
                const url = new URL(request.name);
                if (url.hostname !== currentDomain && 
                    !url.hostname.includes(currentDomain)) {
                    
                    // Known trackers
                    const trackers = [
                        'google-analytics.com', 'googletagmanager.com',
                        'facebook.com', 'doubleclick.net', 'amazon-adsystem.com',
                        'googlesyndication.com', 'googleadservices.com',
                        'twitter.com', 'linkedin.com', 'pinterest.com',
                        'hotjar.com', 'mixpanel.com', 'segment.com'
                    ];
                    
                    const isTracker = trackers.some(tracker => 
                        url.hostname.includes(tracker)
                    );
                    
                    if (isTracker) {
                        thirdParty.push({
                            url: url.hostname,
                            type: this.identifyTrackerType(url.hostname),
                            requests: 1
                        });
                    }
                }
            } catch (e) {
                // Invalid URL
            }
        });
        
        // Aggregate by domain
        const aggregated = {};
        thirdParty.forEach(item => {
            if (aggregated[item.url]) {
                aggregated[item.url].requests++;
            } else {
                aggregated[item.url] = item;
            }
        });
        
        this.detectedTrackers.thirdParty = Object.values(aggregated);
    },
    
    // Identify tracker type
    identifyTrackerType(identifier) {
        const types = {
            analytics: ['google-analytics', '_ga', 'gtm', 'analytics'],
            advertising: ['doubleclick', 'adsystem', 'adservices', '_fbp'],
            social: ['facebook', 'twitter', 'linkedin', 'pinterest'],
            marketing: ['hubspot', 'marketo', 'pardot', 'eloqua'],
            heatmap: ['hotjar', 'fullstory', 'mouseflow'],
            customer: ['intercom', 'drift', 'zendesk']
        };
        
        for (const [type, patterns] of Object.entries(types)) {
            if (patterns.some(pattern => identifier.toLowerCase().includes(pattern))) {
                return type;
            }
        }
        
        return 'unknown';
    },
    
    // Generate tracking report
    generateReport() {
        const report = {
            summary: {
                totalTrackers: 0,
                byType: {},
                privacyScore: 100,
                recommendations: []
            },
            details: this.detectedTrackers
        };
        
        // Count trackers
        Object.values(this.detectedTrackers).forEach(category => {
            report.summary.totalTrackers += Array.isArray(category) ? category.length : 0;
        });
        
        // Score calculation
        report.summary.privacyScore = Math.max(0, 100 - (report.summary.totalTrackers * 5));
        
        // Recommendations
        if (this.detectedTrackers.cookies.length > 0) {
            report.summary.recommendations.push('Use privacy-focused browser or extensions to block tracking cookies');
        }
        
        if (this.detectedTrackers.fingerprinting.length > 0) {
            report.summary.recommendations.push('Enable fingerprinting protection in browser settings');
        }
        
        if (this.detectedTrackers.thirdParty?.length > 5) {
            report.summary.recommendations.push('Consider using ad blocker to reduce third-party tracking');
        }
        
        return report;
    }
};

// Run tracking detection
TrackingDetector.detectTracking().then(console.log);

Privacy Protection Analyzer

Analyze and recommend privacy protections:

// Privacy Protection Analyzer
const PrivacyProtector = {
    // Check browser privacy features
    checkBrowserPrivacy() {
        const features = {
            doNotTrack: navigator.doNotTrack === '1',
            cookieEnabled: navigator.cookieEnabled,
            thirdPartyCookies: this.checkThirdPartyCookies(),
            trackingProtection: this.checkTrackingProtection(),
            httpsOnly: location.protocol === 'https:',
            referrerPolicy: document.referrerPolicy || 'not set',
            permissions: {}
        };
        
        // Check permissions API
        const permissions = ['geolocation', 'camera', 'microphone', 'notifications'];
        permissions.forEach(async permission => {
            try {
                const result = await navigator.permissions.query({ name: permission });
                features.permissions[permission] = result.state;
            } catch (e) {
                features.permissions[permission] = 'not supported';
            }
        });
        
        return features;
    },
    
    // Check third-party cookie support
    checkThirdPartyCookies() {
        // This is a heuristic check
        const testCookie = 'test_third_party=1';
        document.cookie = testCookie;
        const enabled = document.cookie.includes('test_third_party');
        
        // Clean up
        if (enabled) {
            document.cookie = 'test_third_party=; expires=Thu, 01 Jan 1970 00:00:00 UTC';
        }
        
        return !enabled; // If we can't set cookies, third-party might be blocked
    },
    
    // Check tracking protection
    checkTrackingProtection() {
        // Check for common tracking protection indicators
        const indicators = {
            firefoxTP: navigator.doNotTrack === '1' && navigator.userAgent.includes('Firefox'),
            safariITP: navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome'),
            braveShields: navigator.brave !== undefined
        };
        
        return Object.values(indicators).some(v => v);
    },
    
    // Generate privacy recommendations
    generateRecommendations(fingerprint, tracking) {
        const recommendations = {
            critical: [],
            high: [],
            medium: [],
            low: []
        };
        
        // Based on fingerprint uniqueness
        if (fingerprint.uniqueness?.score > 80) {
            recommendations.critical.push({
                issue: 'Highly unique browser fingerprint',
                action: 'Use Tor Browser or Firefox with privacy settings',
                impact: 'Prevents cross-site tracking'
            });
        }
        
        // Based on tracking detection
        if (tracking.summary?.totalTrackers > 10) {
            recommendations.high.push({
                issue: 'Multiple trackers detected',
                action: 'Install uBlock Origin or Privacy Badger',
                impact: 'Blocks most tracking attempts'
            });
        }
        
        // Canvas fingerprinting
        if (fingerprint.canvas?.hash) {
            recommendations.high.push({
                issue: 'Canvas fingerprinting possible',
                action: 'Enable canvas blocker extension',
                impact: 'Prevents canvas-based tracking'
            });
        }
        
        // WebGL info exposed
        if (fingerprint.webgl?.unmaskedRenderer) {
            recommendations.medium.push({
                issue: 'Hardware information exposed via WebGL',
                action: 'Disable WebGL or use WebGL blocker',
                impact: 'Hides GPU information'
            });
        }
        
        // Battery API
        if (fingerprint.battery?.level !== undefined) {
            recommendations.low.push({
                issue: 'Battery API accessible',
                action: 'Use browser that blocks Battery API',
                impact: 'Prevents battery-based tracking'
            });
        }
        
        return recommendations;
    },
    
    // Privacy-preserving alternatives
    suggestAlternatives() {
        return {
            browsers: [
                {
                    name: 'Tor Browser',
                    privacy: 10,
                    pros: ['Maximum privacy', 'Anti-fingerprinting'],
                    cons: ['Slower', 'Some sites may break']
                },
                {
                    name: 'Firefox + uBlock Origin',
                    privacy: 8,
                    pros: ['Good privacy', 'Fast', 'Customizable'],
                    cons: ['Requires configuration']
                },
                {
                    name: 'Brave',
                    privacy: 7,
                    pros: ['Built-in ad blocking', 'Easy to use'],
                    cons: ['Some privacy concerns with crypto features']
                }
            ],
            extensions: [
                {
                    name: 'uBlock Origin',
                    purpose: 'Ad and tracker blocking',
                    effectiveness: 'Very High'
                },
                {
                    name: 'Privacy Badger',
                    purpose: 'Learns to block trackers',
                    effectiveness: 'High'
                },
                {
                    name: 'Canvas Blocker',
                    purpose: 'Prevents canvas fingerprinting',
                    effectiveness: 'High'
                },
                {
                    name: 'HTTPS Everywhere',
                    purpose: 'Forces HTTPS connections',
                    effectiveness: 'Medium'
                }
            ],
            settings: [
                'Enable "Do Not Track"',
                'Block third-party cookies',
                'Use strict tracking protection',
                'Disable WebRTC',
                'Clear cookies on browser close',
                'Use private/incognito mode for sensitive browsing'
            ]
        };
    }
};

Complete Privacy Audit

Comprehensive privacy audit function:

// Complete Privacy Audit
async function performPrivacyAudit() {
    console.log('Starting comprehensive privacy audit...');
    
    const audit = {
        timestamp: new Date().toISOString(),
        url: window.location.href,
        results: {},
        score: 0,
        summary: {}
    };
    
    try {
        // 1. Collect fingerprint
        console.log('Analyzing browser fingerprint...');
        audit.results.fingerprint = await FingerprintAnalyzer.collectFingerprint();
        
        // 2. Detect tracking
        console.log('Detecting tracking mechanisms...');
        audit.results.tracking = await TrackingDetector.detectTracking();
        
        // 3. Check privacy protections
        console.log('Checking privacy protections...');
        audit.results.protections = PrivacyProtector.checkBrowserPrivacy();
        
        // 4. Generate recommendations
        audit.results.recommendations = PrivacyProtector.generateRecommendations(
            audit.results.fingerprint,
            audit.results.tracking
        );
        
        // 5. Calculate privacy score
        const fingerprintScore = 100 - audit.results.fingerprint.uniqueness.score;
        const trackingScore = audit.results.tracking.summary.privacyScore;
        const protectionBonus = audit.results.protections.doNotTrack ? 10 : 0;
        
        audit.score = Math.round((fingerprintScore + trackingScore) / 2 + protectionBonus);
        audit.score = Math.min(100, Math.max(0, audit.score));
        
        // 6. Generate summary
        audit.summary = {
            privacyScore: audit.score,
            rating: audit.score > 80 ? 'Excellent' :
                   audit.score > 60 ? 'Good' :
                   audit.score > 40 ? 'Fair' :
                   audit.score > 20 ? 'Poor' : 'Very Poor',
            uniquenessRating: audit.results.fingerprint.uniqueness.rating,
            trackersFound: audit.results.tracking.summary.totalTrackers,
            criticalIssues: audit.results.recommendations.critical.length,
            protectionsEnabled: Object.values(audit.results.protections).filter(v => v === true).length
        };
        
        // 7. Add alternatives
        audit.alternatives = PrivacyProtector.suggestAlternatives();
        
    } catch (error) {
        audit.error = error.message;
    }
    
    console.log('Privacy audit complete!');
    return audit;
}

// Run the audit
performPrivacyAudit().then(audit => {
    console.log('Privacy Audit Results:');
    console.log(`Overall Score: ${audit.score}/100 (${audit.summary.rating})`);
    console.log(`Fingerprint Uniqueness: ${audit.summary.uniquenessRating}`);
    console.log(`Trackers Found: ${audit.summary.trackersFound}`);
    console.log(`Critical Issues: ${audit.summary.criticalIssues}`);
    console.log('\nFull report:', audit);
});

Best Practices for Privacy

  1. Use Privacy-Focused Browsers: Tor, hardened Firefox, or Brave
  2. Enable Tracking Protection: Use strict mode in browser settings
  3. Block Third-Party Cookies: Prevent cross-site tracking
  4. Use VPN Services: Hide your IP address and location
  5. Regular Cookie Cleaning: Clear cookies and site data regularly
  6. Minimize Extensions: Each extension increases fingerprint uniqueness
  7. Disable Unnecessary APIs: Turn off location, camera, microphone when not needed
  8. Use Privacy Extensions: uBlock Origin, Privacy Badger, etc.
  9. HTTPS Only: Use HTTPS Everywhere or browser HTTPS-only mode
  10. Compartmentalize: Use different browsers/profiles for different activities

Common Privacy Threats

  • Browser Fingerprinting: Unique identification without cookies
  • Canvas Fingerprinting: Using HTML5 canvas for tracking
  • WebRTC IP Leaks: Revealing real IP despite VPN
  • Third-Party Cookies: Cross-site tracking cookies
  • Supercookies: Persistent tracking via Flash, HTML5
  • Device Fingerprinting: Hardware and sensor-based tracking
  • Behavioral Analysis: Tracking via typing patterns, mouse movements
  • Social Media Tracking: Like buttons and embedded content
  • Analytics Services: Detailed user behavior tracking
  • Ad Networks: Extensive cross-site tracking networks

Privacy is not about hiding wrongdoing—it's about maintaining autonomy in an increasingly connected world. Use these tools to understand your digital footprint and make informed decisions about your online privacy.