JSPM

@cookiefirst/fastdetect

1.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 22
  • Score
    100M100P100Q46829F
  • License AGPL-3.0

High-performance device detection library optimized for API usage with comprehensive device, browser, and OS detection

Package Exports

  • @cookiefirst/fastdetect
  • @cookiefirst/fastdetect/parsers/bot
  • @cookiefirst/fastdetect/parsers/browser
  • @cookiefirst/fastdetect/parsers/device
  • @cookiefirst/fastdetect/parsers/os

Readme

FastDetect 🚀

High-performance device detection library optimized for API usage with comprehensive device, browser, and OS detection.

npm version TypeScript AGPL-3.0 License Bundle Size Codecov

✨ Features

  • 🏃‍♂️ High Performance: Optimized for 10,000+ detections per second with sub-millisecond response times
  • 🎯 Comprehensive Detection: Device types, brands, models, browsers, operating systems, and bots
  • 💾 Smart Caching: Built-in LRU cache with configurable size for optimal memory usage
  • 📱 Mobile-First: Optimized patterns for modern mobile devices and emerging technologies
  • 🤖 AI-Ready: Detection for modern AI crawlers (GPTBot, ClaudeBot, PerplexityBot)
  • 🌳 Tree-Shakeable: Modular architecture allows importing only needed components
  • 📘 TypeScript: Full type definitions with comprehensive IntelliSense support
  • 🔒 Zero Dependencies: No external runtime dependencies for maximum security
  • ⚖️ AGPL-3.0 Licensed: Free software with copyleft protection

🚀 Installation

npm install @cookiefirst/fastdetect
yarn add @cookiefirst/fastdetect
pnpm add @cookiefirst/fastdetect

📖 Quick Start

Basic Usage

import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect();

const result = detector.parse('Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1');

console.log(result);
// Output:
// {
//   browser: { name: 'Safari', version: '16.6', major: '16', engine: 'WebKit', isMobile: true },
//   os: { name: 'iOS', version: '16.6', family: 'iOS' },
//   device: { type: 'smartphone', brand: 'Apple', model: 'iPhone' },
//   bot: { isBot: false, name: null, category: null },
//   userAgent: '...',
//   timestamp: 1703932800000
// }

Modular Usage (Tree-Shaking Optimized)

import { BrowserParser, DeviceParser } from '@cookiefirst/fastdetect';

const browserParser = new BrowserParser();
const deviceParser = new DeviceParser();

const browser = browserParser.parse(userAgent);
const device = deviceParser.parse(userAgent);

Express.js Middleware

import express from 'express';
import FastDetect from '@cookiefirst/fastdetect';

const app = express();
const detector = new FastDetect({ cacheSize: 5000 });

app.use((req, res, next) => {
  req.device = detector.parse(req.headers['user-agent'] || '');
  next();
});

app.get('/api/analytics', (req, res) => {
  const { device } = req;
  
  // Log device information for analytics
  console.log(`Device: ${device.device.type}, Browser: ${device.browser.name}`);
  
  res.json({ success: true });
});

🔧 API Reference

FastDetect Class

Constructor

new FastDetect(options?: ParseOptions)

Options:

  • cacheSize?: number - LRU cache size (default: 1000)
  • skipCache?: boolean - Disable caching (default: false)
  • detailed?: boolean - Enable detailed parsing (default: false)
  • maxLength?: number - Maximum UA string length before rejection (default: 8192)

Methods

parse(userAgent: string, options?: ParseOptions): DetectionResult

Parse complete device information from user agent string.

const result = detector.parse('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
parseBrowser(userAgent: string): BrowserInfo

Parse browser information only (lightweight).

const browser = detector.parseBrowser(userAgent);
// { name: 'Chrome', version: '91.0.4472.124', major: '91', engine: 'Blink' }
parseDevice(userAgent: string): DeviceInfo

Parse device information only.

const device = detector.parseDevice(userAgent);
// { type: 'smartphone', brand: 'Apple', model: 'iPhone 14 Pro' }
parseOS(userAgent: string): OSInfo

Parse operating system information only.

const os = detector.parseOS(userAgent);
// { name: 'iOS', version: '16.6', family: 'iOS' }
parseBot(userAgent: string): BotInfo

Parse bot/crawler information only.

const bot = detector.parseBot(userAgent);
// { isBot: true, name: 'Googlebot', category: 'search-engine' }

Quick Detection Methods

detector.isMobile(userAgent)    // boolean
detector.isTablet(userAgent)    // boolean
detector.isDesktop(userAgent)   // boolean
detector.isBot(userAgent)       // boolean

Cache Management

detector.clearCache()           // Clear cache
detector.getCacheStats()        // Get cache statistics

📊 Supported Detections

Device Types

  • Smartphones - iPhone, Android phones, etc.
  • Tablets - iPad, Android tablets, Surface tablets
  • Desktops - Windows, macOS, Linux computers
  • Smart TVs - Android TV, webOS, Tizen, Roku, Apple TV
  • Gaming Consoles - PlayStation, Xbox, Nintendo Switch, Steam Deck
  • VR/AR Headsets - Meta Quest, Apple Vision Pro, HTC Vive
  • Wearables - Apple Watch, Galaxy Watch, Wear OS
  • E-readers - Kindle, Kobo, Nook
  • Automotive - Android Automotive, CarPlay systems
  • IoT Devices - Smart home devices, embedded systems

Browsers (50+ supported)

  • Desktop: Chrome, Firefox, Safari, Edge, Opera, Internet Explorer
  • Mobile: Chrome Mobile, Safari Mobile, Samsung Internet, UC Browser
  • WebViews: Android WebView, iOS WebView, Facebook Browser

Operating Systems (30+ supported)

  • Desktop: Windows (7-10/11), macOS, Linux distributions

Note: Windows 10 and Windows 11 both report NT 10.0 in the user-agent string and cannot be reliably distinguished via UA alone. FastDetect returns "Windows 10/11" for these. Accurate Windows 11 detection requires Client Hints (Sec-CH-UA-Platform-Version).

  • Mobile: iOS, iPadOS, Android, Windows Phone
  • Specialized: Chrome OS, Tizen, webOS, KaiOS

Device Brands (100+ supported)

  • Mobile: Apple, Samsung, Google, Huawei, Xiaomi, OPPO, vivo, OnePlus
  • Desktop: Dell, HP, Lenovo, ASUS, Microsoft Surface
  • Gaming: Sony, Microsoft, Nintendo, Valve

Bots & Crawlers (50+ supported)

  • Search Engines: Googlebot, Bingbot, Yahoo Slurp, Baidu Spider
  • AI Crawlers: GPTBot, ClaudeBot, PerplexityBot (2024-2025)
  • Social Media: Facebook, Twitter, LinkedIn, Pinterest bots
  • SEO Tools: Ahrefs, Semrush, Majestic crawlers
  • Monitoring: UptimeRobot, Pingdom, DataDog

🎯 Performance

FastDetect is optimized for high-throughput API usage:

  • Speed: 5,000,000+ detections per second (cached)
  • Memory: < 1MB memory usage with default cache
  • Latency: Sub-microsecond response time for cached UAs
  • Accuracy: 99%+ accuracy for known devices
  • Cache Hit Rate: 85-95% in typical usage

Benchmark Results

FastDetect Performance Benchmarks (Node.js v20, Apple M-series)
───────────────────────────────────────────────────────────────
✓ Mixed Workload:      5,745,475 ops/sec  (0.0002ms avg)
✓ Cache Hit:           8,565,310 ops/sec  (0.0001ms avg)
✓ Mobile Detection:    4,824,509 ops/sec  (0.0002ms avg)
✓ Cold Parse:            170,703 ops/sec  (0.006ms avg)
✓ Memory per Detection:  0.82 KB

🔧 Configuration

Cache Configuration

const detector = new FastDetect({
  cacheSize: 2000,        // Increase cache for high-traffic APIs
  skipCache: false        // Enable caching for better performance
});

// Monitor cache performance
const stats = detector.getCacheStats();
console.log(`Cache hit rate: ${stats.hitRate}%`);

Memory Management

// Clear cache periodically in long-running processes
setInterval(() => {
  const stats = detector.getCacheStats();
  if (stats.hitRate < 50) {
    detector.clearCache(); // Clear ineffective cache
  }
}, 300000); // Every 5 minutes

Cache sizing and tradeoffs

  • What the cache does: Stores parsed results by exact user agent string for O(1) reuse. Great when UA strings repeat; less useful when every request is unique.
  • Memory vs. speed: Larger caches increase hit rate (more reuse) but consume more memory. With typical detection results, expect roughly ~0.7–0.9 KB per cached entry. For example, a cacheSize of 5,000 used ~7.5 MB in our stress test with 10,000 unique UAs.
  • When to increase cache: High-traffic APIs with meaningful UA repetition (e.g., mobile apps, crawlers, corporate fleets). Aim for hitRate ≥ 80%.
  • When to decrease/disable cache: Workloads with many unique UAs (e.g., logs/backfills). If hitRate < 50%, consider smaller cache or disabling per-call.

Recommended defaults by environment:

  • Serverless/function: cacheSize: 200–1000
  • Container/service (2–4 GB RAM): cacheSize: 1000–5000
  • Batch/log processing (low repetition): use skipCache: true on parse calls

Examples

// 1) Tune via env var with safe default
const detector = new FastDetect({
  cacheSize: Number(process.env.FD_CACHE_SIZE ?? 1000)
});

// 2) Disable caching for specific calls (e.g., batch jobs)
detector.parse(ua, { skipCache: true });

// 3) Monitor and adjust based on hit rate
const { hitRate, size, capacity } = detector.getCacheStats();
if (hitRate < 50) {
  // Consider recreating detector with a smaller cacheSize or using skipCache
}

🚦 Browser Usage Warning

⚠️ Important: FastDetect is optimized for server-side usage. For browser usage, consider the lightweight alternatives:

// ✅ Recommended for browsers (lightweight)
import { BrowserParser } from '@cookiefirst/fastdetect/parsers/browser';

const browserParser = new BrowserParser();
const browser = browserParser.parse(navigator.userAgent);

📈 Migration Guide

From ua-parser-js

// Before (ua-parser-js)
import { UAParser } from 'ua-parser-js';
const parser = new UAParser();
const result = parser.setUA(userAgent).getResult();

// After (FastDetect)
import FastDetect from '@cookiefirst/fastdetect';
const detector = new FastDetect();
const result = detector.parse(userAgent);

// Mapping
result.browser.name    // ✓ Same
result.device.type     // ✓ Same concept
result.os.name         // ✓ Same

From mobile-detect

// Before (mobile-detect)
import MobileDetect from 'mobile-detect';
const md = new MobileDetect(userAgent);
const isMobile = md.mobile();

// After (FastDetect) 
import FastDetect from '@cookiefirst/fastdetect';
const detector = new FastDetect();
const isMobile = detector.isMobile(userAgent);

🧪 Testing

npm test                # Run all tests
npm run test:coverage   # Run with coverage
npm run benchmark       # Performance benchmarks

📄 License

AGPL-3.0 License - see LICENSE file for details.

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

Development Setup

git clone https://github.com/cookiefirst-dds/fastdetect.git
cd fastdetect
npm install
npm run build
npm test

Adding New Device Patterns

  1. Add pattern to parser: Update the relevant parser in src/parsers/
  2. Add test cases: Create comprehensive test cases
  3. Update documentation: Document new detections
  4. Performance test: Ensure no regression in performance

🔍 Examples

Real-World Usage Examples

API Analytics Service

import FastDetect from '@cookiefirst/fastdetect';
import express from 'express';

const app = express();
const detector = new FastDetect({ cacheSize: 10000 });

// Analytics middleware
app.use('/api', (req, res, next) => {
  const userAgent = req.headers['user-agent'];
  const detection = detector.parse(userAgent || '');
  
  // Log for analytics
  console.log({
    timestamp: Date.now(),
    deviceType: detection.device.type,
    browser: detection.browser.name,
    os: detection.os.name,
    isBot: detection.bot.isBot
  });
  
  // Add to request for downstream handlers
  req.deviceInfo = detection;
  next();
});

app.get('/api/content', (req, res) => {
  const { deviceInfo } = req;
  
  // Serve optimized content based on device
  if (deviceInfo.device.type === 'smartphone') {
    res.json({ content: 'mobile-optimized-content' });
  } else {
    res.json({ content: 'desktop-content' });
  }
});

Bot Detection Service

import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect();

function handleRequest(userAgent: string) {
  const detection = detector.parse(userAgent);
  
  if (detection.bot.isBot) {
    console.log(`Bot detected: ${detection.bot.name} (${detection.bot.category})`);
    
    // Handle different bot types
    switch (detection.bot.category) {
      case 'search-engine':
        return { action: 'allow', priority: 'high' };
      case 'ai-crawler':
        return { action: 'rate-limit', priority: 'medium' };
      case 'seo-tool':
        return { action: 'allow', priority: 'low' };
      default:
        return { action: 'block', priority: 'none' };
    }
  }
  
  return { action: 'allow', priority: 'high' };
}

Device-Specific Feature Detection

import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect();

function getAvailableFeatures(userAgent: string) {
  const detection = detector.parse(userAgent);
  const features = [];
  
  // Device-specific features
  switch (detection.device.type) {
    case 'smartphone':
      features.push('touch', 'geolocation', 'camera', 'push-notifications');
      break;
    case 'tablet':
      features.push('touch', 'large-screen', 'orientation');
      break;
    case 'desktop':
      features.push('keyboard', 'mouse', 'large-screen', 'file-system');
      break;
    case 'smart-tv':
      features.push('large-screen', 'remote-control');
      break;
  }
  
  // Browser-specific features
  if (detection.browser.name === 'Chrome' && 
      parseInt(detection.browser.major || '0') >= 90) {
    features.push('webrtc', 'webassembly', 'service-worker');
  }
  
  return features;
}

Batch Processing Example

import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect({ cacheSize: 5000 });

// Process large user agent logs efficiently
function processUserAgentLogs(userAgents: string[]) {
  const results = [];
  const uniqueUAs = [...new Set(userAgents)]; // Deduplicate for performance
  
  // Process unique user agents once
  const detectionMap = new Map();
  for (const ua of uniqueUAs) {
    detectionMap.set(ua, detector.parse(ua));
  }
  
  // Map results back to original array
  for (const ua of userAgents) {
    results.push(detectionMap.get(ua));
  }
  
  return results;
}

🔬 Advanced Configuration

Custom Pattern Extensions

import FastDetect from '@cookiefirst/fastdetect';
import { DeviceParser } from '@cookiefirst/fastdetect/parsers/device';

// Extend DeviceParser for custom patterns
class CustomDeviceParser extends DeviceParser {
  parse(userAgent: string) {
    const result = super.parse(userAgent);
    
    // Add custom business logic
    if (userAgent.includes('CustomDevice')) {
      result.brand = 'CustomBrand';
      result.model = 'Custom Model';
    }
    
    return result;
  }
}

const detector = new FastDetect();
// Replace internal parser (advanced usage)
detector['deviceParser'] = new CustomDeviceParser();

Performance Monitoring

import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect({ cacheSize: 2000 });

// Monitor performance metrics
setInterval(() => {
  const stats = detector.getCacheStats();
  
  console.log('FastDetect Performance Metrics:');
  console.log(`Cache Size: ${stats.size}/${stats.capacity}`);
  console.log(`Hit Rate: ${stats.hitRate}%`);
  console.log(`Total Hits: ${stats.hits}`);
  console.log(`Total Misses: ${stats.misses}`);
  
  // Alert if performance degrades
  if (stats.hitRate < 70) {
    console.warn('Cache hit rate below 70%, consider increasing cache size');
  }
}, 60000); // Every minute

🌐 Framework Integration

Next.js Integration

// pages/api/device-info.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect();

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const userAgent = req.headers['user-agent'] || '';
  const deviceInfo = detector.parse(userAgent);
  
  res.status(200).json(deviceInfo);
}

// Middleware example
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect();

export function middleware(request: NextRequest) {
  const userAgent = request.headers.get('user-agent') || '';
  const deviceInfo = detector.parse(userAgent);
  
  // Add device info to headers
  const response = NextResponse.next();
  response.headers.set('x-device-type', deviceInfo.device.type);
  response.headers.set('x-is-mobile', deviceInfo.device.type === 'smartphone' ? 'true' : 'false');
  
  return response;
}

Fastify Plugin

import fastify from 'fastify';
import FastDetect from '@cookiefirst/fastdetect';

const detector = new FastDetect();

// Create Fastify plugin
const deviceDetectionPlugin = async (fastify: any) => {
  fastify.decorateRequest('device', null);
  
  fastify.addHook('preHandler', async (request: any) => {
    const userAgent = request.headers['user-agent'] || '';
    request.device = detector.parse(userAgent);
  });
};

const app = fastify();
app.register(deviceDetectionPlugin);

app.get('/api/info', async (request: any, reply) => {
  return { deviceInfo: request.device };
});

📊 Type Definitions

Complete TypeScript Interfaces

interface DetectionResult {
  browser: BrowserInfo;
  os: OSInfo;
  device: DeviceInfo;
  bot: BotInfo;
  userAgent: string;
  timestamp: number;
}

interface BrowserInfo {
  name: string;
  version: string | null;
  major: string | null;
  engine?: string;
  isMobile?: boolean;
  isWebView?: boolean;
}

interface DeviceInfo {
  type: 'smartphone' | 'tablet' | 'desktop' | 'laptop' | 'smart-tv' | 
        'gaming-console' | 'wearable' | 'iot-device' | 'automotive' | 
        'vr-headset' | 'e-reader' | 'unknown';
  brand: string;
  model: string | null;
  marketingName?: string;
}

interface OSInfo {
  name: string;
  version: string | null;
  family?: string;
  architecture?: string;
}

interface BotInfo {
  isBot: boolean;
  name: string | null;
  category: string | null;
  company?: string;
  purpose?: string;
}

🚀 Performance Tips

Optimization Best Practices

  1. Use Appropriate Cache Size

    // High-traffic API (>10k requests/min)
    const detector = new FastDetect({ cacheSize: 5000 });
    
    // Low-traffic API (<1k requests/min)  
    const detector = new FastDetect({ cacheSize: 500 });
  2. Deduplicate User Agents

    // Efficient batch processing
    const uniqueUAs = [...new Set(userAgents)];
    const results = uniqueUAs.map(ua => detector.parse(ua));
  3. Use Quick Detection Methods

    // Fast path for simple checks
    if (detector.isMobile(userAgent)) {
      // Mobile-specific logic
    } else {
      // Desktop logic
    }
  4. Monitor Cache Performance

    const stats = detector.getCacheStats();
    if (stats.hitRate < 80) {
      // Consider increasing cache size or investigating patterns
    }

🛠️ Troubleshooting

Common Issues

Q: High memory usage A: Reduce cache size or clear cache periodically

detector.clearCache(); // Clear when hit rate is low

Q: Low cache hit rate A: User agents are highly diverse; increase cache size

const detector = new FastDetect({ cacheSize: 3000 });

Q: Inaccurate detection A: Please report with user agent string for pattern updates

Q: Bundle size too large A: Use modular imports for tree-shaking

import { BrowserParser } from '@cookiefirst/fastdetect/parsers/browser';

📞 Support

🏆 Acknowledgments

Note: Acknowledgments reflect inspiration for patterns and API design. No code was copied from these sources.

  • 51Degrees - Device database inspiration
  • Matomo Device Detector - Pattern organization concepts
  • ua-parser-js - API design reference
  • Bowser - Performance optimization techniques

Made with ❤️ for the JavaScript community

FastDetect is optimized for production API usage. Star ⭐ us on GitHub if this project helps you!