npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@denniskrol/device-profiles

v1.20260313.0

Published

Daily updated browser device profiles

Downloads

3,349

Readme

Device Profiles

npm downloads license node

Daily updated browser/device profiles with weighted random selection. Useful for realistic client fingerprint spoofing, testing, load generation.

Data comes from a website with about 65% mobile and 35% desktop traffic, and uses browser-profiler to get data.

This is inspired by intoli/user-agents which doesn't seem to get updated anymore and lacks some data that I needed.

Install

npm install @denniskrol/device-profiles

Basic Usage

import { DeviceProfiles } from '@denniskrol/device-profiles';

// Get a weighted random profile
const profile = new DeviceProfiles();
console.log(profile.userAgent, profile.deviceType);

Filtered Random

// Only mobile devices
const mobile = new DeviceProfiles({ deviceType: 'mobile' });

// Regex match browser name
const safari = new DeviceProfiles({ browser: /Safari/ });

// Inclusion list (e.g. mobile OR tablet)
const touch = new DeviceProfiles({ deviceType: ['mobile', 'tablet'] });

// Function predicate (custom logic)
const chromeWithUAData = new DeviceProfiles(profile =>
  profile.userAgent.includes('Chrome') && !!profile.userAgentData
);

// Using static random with predicate
const randomChrome = DeviceProfiles.random(profile =>
  /Chrome/.test(profile.userAgent) && profile.deviceType === 'desktop'
);

Static Helpers

import { DeviceProfiles } from '@denniskrol/device-profiles';

// Get array of all profiles
const all = DeviceProfiles.all();

// Get random with filter without instantiating
const randomDesktop = DeviceProfiles.random({ deviceType: 'desktop' });

Profile example

{
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
  "platform": "Win32",
  "deviceMemory": 8,
  "hardwareConcurrency": 8,
  "vendor": "Google Inc.",
  "screenHeight": 720,
  "screenWidth": 1280,
  "viewportHeight": 568,
  "viewportWidth": 1251,
  "devicePixelRatio": 1.5,
  "webglRenderer": "ANGLE (Intel, Intel(R) UHD Graphics (0x00009B41) Direct3D11 vs_5_0 ps_5_0, D3D11)",
  "webglVendor": "Google Inc. (Intel)",
  "webGpuArchitecture": "gen-9",
  "webGpuVendor": "intel",
  "storageQuota": {
    "quota": 113282066841,
    "usage": 0,
    "available": 113282066841
  },
  "jsHeapSizeLimit": 2248146944,
  "fonts": [
    "Aldhabi",
    "Bahnschrift",
    "Cambria Math",
    "Gadugi",
    "HoloLens MDL2 Assets",
    "Ink Free",
    "Javanese Text",
    "Leelawadee UI",
    "Lucida Console",
    "MS Outlook",
    "Myanmar Text",
    "Nirmala UI",
    "Segoe MDL2 Assets",
    "Segoe UI Emoji"
  ],
  "userAgentData": {
    "architecture": "x86",
    "bitness": "64",
    "brands": [
      {
        "brand": "Chromium",
        "version": "142"
      },
      {
        "brand": "Google Chrome",
        "version": "142"
      },
      {
        "brand": "Not_A Brand",
        "version": "99"
      }
    ],
    "fullVersionList": [
      {
        "brand": "Chromium",
        "version": "142.0.7444.134"
      },
      {
        "brand": "Google Chrome",
        "version": "142.0.7444.134"
      },
      {
        "brand": "Not_A Brand",
        "version": "99.0.0.0"
      }
    ],
    "mobile": false,
    "model": null,
    "platform": "Windows",
    "platformVersion": "10.0.0",
    "uaFullVersion": "142.0.7444.134"
  },
  "weight":26,
  "deviceType":"desktop",
  "browser":"Chrome",
  "osName":"Windows"
}

Filtering Rules

  • Primitive equality (deviceType: 'mobile')
  • Inclusion list (deviceType: ['mobile','tablet'])
  • RegExp match (browser: /Safari/)
  • Function predicate (profile => boolean) for full custom logic

Weighted Selection

Each profile has a weight. Random selection is proportional to weight.

JSON Access

You can also import the raw JSON:

import profilesJson from '@denniskrol/device-profiles/deviceprofiles.json';
console.log(profilesJson.length);

License

Unlicense