mrkeyoor.com_
Thu 06 Aug 15:39 UTC
npmWeb Backendupdated 06 Aug 2026

systeminformation

systeminformation is a server-side Node library that reports hardware and operating system detail that Node's built-in os module does not expose: CPU model and per-core load, memory layout, physical disks and S.M.A.R.T. status, filesystems, GPUs, battery, USB and audio devices, network interfaces and per-second throughput, running processes and services, wifi, bluetooth, printers, and Docker containers. It has no npm dependencies, ships its own TypeScript definitions, and every function returns a promise (or takes a callback). Under the hood most values come from parsing the output of platform command line tools, which is the thing to understand before you rely on it.

Verdict

The most complete way to read machine state from Node, and worth it when you need the breadth. Treat every field as optional, test on each OS you ship to, and cache the expensive calls, because the numbers come from command output rather than a stable system API.

API stability3/5The version 5 line has been additive for a long time and new fields keep arriving in minor releases, but the maintainer has announced a TypeScript version 6 with a cleaned-up API and breaking changes, and individual properties still return undefined on platforms where the underlying command is unavailable.
Docs4/5systeminformation.io documents every function with example output, and the README carries a per-property table showing which of Linux, BSD, macOS, Windows, and SunOS each field works on, plus an honest known-issues section covering temperature and S.M.A.R.T.
Maintenance3/5A single author funded by donations, last push in July 2026 with 5.33.1 current and 95 open issues; releases are frequent, but attention is currently split with the version 6 rewrite.
Ecosystem4/5Zero dependencies, bundled type definitions, an npx CLI, tested on Node, Bun, and Deno, and widely embedded in Electron apps and monitoring agents; the extras it depends on for temperature are separate packages by the same author.

Use it if

  • You are building a monitoring agent, admin dashboard, or status endpoint in Node and need per-core load, disk usage, and network throughput
  • You need hardware detail beyond os.cpus() and os.totalmem(), such as disk model and serial, GPU controllers, battery health, or memory stick layout
  • You ship an Electron or Bun desktop app and want the same system-specs call to work on Windows, macOS, and Linux
  • You want Docker container and image stats without pulling in a full Docker client library
Skip it if

Setup reality

npm i systeminformation installs one package with no dependencies and bundled TypeScript types, and the first si.cpu() works. The gap between that and production is the external tooling. Windows 11 dropped wmic, so the library moved to powershell and wants version 5 or newer; older Windows can still show encoding problems on non-ASCII values. Linux temperature needs lm-sensors installed and S.M.A.R.T. needs smartmontools. macOS temperature needs you to also install macos-temperature-sensor on Apple Silicon or osx-temperature-sensor on Intel, because the optional dependency was dropped to avoid install warnings elsewhere. Several Windows values only return anything when the process has admin rights. The package is CommonJS, so an ESM project gets the whole namespace through a default import. Calls that gather everything, such as getStaticData, can take tens of seconds on first run, so cache the static half instead of calling it per request.

Patterns

Read CPU and OS basicsbasic-system-info

const si = require('systeminformation')

const [cpu, os] = await Promise.all([si.cpu(), si.osInfo()])

console.log(cpu.manufacturer, cpu.brand, cpu.physicalCores, cpu.cores)
console.log(os.platform, os.distro, os.release, os.arch)

Every function except version() and time() is async. In an ESM file use import si from "systeminformation" as a default import, because the package is CommonJS.

Get CPU load overall and per corecurrent-load

const load = await si.currentLoad()

console.log(load.currentLoad.toFixed(1) + '%')
load.cpus.forEach((c, i) => console.log(`core ${i}: ${c.load.toFixed(1)}%`))

currentLoad is computed from tick deltas since the previous call, so the very first reading covers the time since boot and looks unnaturally flat. Poll twice and use the second value.

Memory, including the value you actually want on Linuxmemory-usage

const mem = await si.mem()

const usedGb = (mem.active / 1024 ** 3).toFixed(2)
console.log({ total: mem.total, free: mem.free, used: mem.used, active: mem.active })

On Linux mem.used counts buffers and cache, so it always looks near 100%. mem.active is the number a dashboard should show.

Filesystem usage per mountdisk-usage

const disks = await si.fsSize()

for (const d of disks) {
  console.log(d.mount, d.type, d.use.toFixed(1) + '%', d.size, d.available)
}

// a single drive only
const root = await si.fsSize('/')

In containers this lists the overlay and every bind mount, so filter by mount before rendering. Network mounts that are hung will make the call block until the underlying command times out.

Measure network throughput per secondnetwork-throughput

const iface = (await si.networkInterfaces('default')).iface

await si.networkStats(iface) // first call primes the counters

setInterval(async () => {
  const [s] = await si.networkStats(iface)
  console.log(s.rx_sec, s.tx_sec)
}, 1000)

rx_sec and tx_sec are null on the first call by design, because rates are derived from the delta between two calls. The README spells this out for networkStats, fsStats, and disksIO.

List the heaviest processestop-processes

const { all, running, list } = await si.processes()

const top = list
  .sort((a, b) => b.cpu - a.cpu)
  .slice(0, 10)
  .map((p) => ({ pid: p.pid, name: p.name, cpu: p.cpu, mem: p.mem }))

console.log({ all, running, top })

This is one of the slowest calls in the library because it enumerates every process. Do not put it behind an endpoint that can be hit repeatedly without a cache.

Read CPU temperature where it is availablecpu-temperature

const temp = await si.cpuTemperature()

if (temp.main === null || temp.main === -1) {
  console.log('no temperature sensor available on this host')
} else {
  console.log(temp.main, temp.cores, temp.max)
}

Linux needs lm-sensors installed, Windows often needs admin rights, and macOS returns nothing unless you separately install macos-temperature-sensor on Apple Silicon or osx-temperature-sensor on Intel.

Fetch exactly the fields you need in one callpartial-snapshot

const data = await si.get({
  cpu: 'manufacturer, brand, speed',
  mem: 'total, active',
  osInfo: 'platform, distro, release',
  currentLoad: 'currentLoad',
  fsSize: '*',
})

si.get is much cheaper than getAllData because it only runs the collectors you name. Use "*" for a whole section and a comma separated list otherwise.

Poll a value object and react only to changesobserve-changes

si.observe(
  { currentLoad: 'currentLoad', mem: 'active' },
  2000,
  (data) => {
    pushToDashboard(data)
  },
)

observe polls on your interval and calls back when the result differs from the previous poll. Pick an interval well above the time the underlying commands take, or polls will overlap.

Inspect Docker containers and their statsdocker-containers

const info = await si.dockerInfo()
console.log(info.containersRunning, info.images)

const containers = await si.dockerContainers(true) // true includes stopped
for (const c of containers) {
  const [stats] = await si.dockerContainerStats(c.id)
  console.log(c.name, c.state, stats.cpuPercent, stats.memUsage)
}

These talk to the Docker socket, so the Node process needs access to it. Inside a container that means mounting /var/run/docker.sock, which is effectively root on the host.

Split the expensive static data from the cheap dynamic datastatic-vs-dynamic

// once at boot, cache the result
const staticData = await si.getStaticData()

// per poll
const dynamic = await si.getDynamicData('*', 'eth0')

getStaticData walks hardware inventory and the README warns it can take up to 30 seconds. Calling it per request is the most common way people make this library look slow.

Physical disks, GPUs, and machine identityhardware-inventory

const [layout, gpu, uuid] = await Promise.all([
  si.diskLayout(),
  si.graphics(),
  si.uuid(),
])

console.log(layout.map((d) => [d.name, d.type, d.size, d.smartStatus]))
console.log(gpu.controllers.map((c) => c.model))
console.log(uuid.os, uuid.hardware)

smartStatus needs smartmontools on Linux and macOS and reports "unknown" without it. uuid.hardware is empty on many virtual machines, so do not use it alone as a licence key.

Alternatives

PackageRegistryPick it when
node-os-utilsnpmYou only need CPU, memory, disk, and network basics and want a much smaller surface to reason about.
pidusagenpmYou care about CPU and memory of specific processes rather than the whole machine.
dockerodenpmDocker is the actual subject and you want the full Engine API instead of a summary of containers.