Skip to main content

get-port vs detect-port vs portfinder: Port Detection Utilities in Node.js (2026)

·PkgPulse Team

TL;DR

get-port is the minimal port finder — gets a random available port or checks specific ports, tiny (no dependencies), async, by Sindre Sorhus. detect-port is Alibaba's port detector — finds an available port starting from a preferred number, used by Umi and Egg.js, returns the next free port. portfinder is the classic port finder — scans from a base port upward, callback and promise API, the most widely used. In 2026: get-port for minimal port detection, detect-port for auto-incrementing port fallback, portfinder for legacy projects.

Key Takeaways

  • get-port: ~10M weekly downloads — minimal, random or specific, by Sindre Sorhus
  • detect-port: ~10M weekly downloads — Alibaba, auto-increment, fallback port
  • portfinder: ~10M weekly downloads — classic, base port scanning, callback/promise
  • All three find available TCP ports on localhost
  • get-port is the most modern (ESM-only, no dependencies)
  • detect-port and portfinder scan upward from a preferred port

get-port

get-port — minimal port finder:

Basic usage

import getPort from "get-port"

// Get a random available port:
const port = await getPort()
console.log(port) // → 52741 (random available port)

// Prefer a specific port, fallback to random:
const port2 = await getPort({ port: 3000 })
console.log(port2) // → 3000 if available, or random

// Prefer from a list of ports:
const port3 = await getPort({ port: [3000, 3001, 3002] })
console.log(port3) // → First available from list, or random

Port range

import getPort, { portNumbers } from "get-port"

// Get port from a range:
const port = await getPort({ port: portNumbers(3000, 3100) })
console.log(port) // → First available in 3000-3100, or random

// Use in a dev server:
import express from "express"

const app = express()
const port = await getPort({ port: portNumbers(3000, 3010) })

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`)
})

Make a range of ports

import getPort, { portNumbers } from "get-port"

// portNumbers returns an iterable:
const ports = portNumbers(8000, 8100)
const port = await getPort({ port: ports })

// Exclude specific ports:
const port2 = await getPort({
  port: portNumbers(3000, 3100),
  exclude: [3001, 3005],
})

// Host-specific:
const port3 = await getPort({
  port: 3000,
  host: "0.0.0.0",  // Check on all interfaces
})

Dev server pattern

import getPort, { portNumbers } from "get-port"
import { createServer } from "node:http"

async function startServer() {
  const port = await getPort({ port: portNumbers(3000, 3010) })

  const server = createServer((req, res) => {
    res.end("Hello!")
  })

  server.listen(port, () => {
    console.log(`→ http://localhost:${port}`)
  })

  return { server, port }
}

detect-port

detect-port — auto-increment port:

Basic usage

import detect from "detect-port"

// Find available port starting from 3000:
const port = await detect(3000)
console.log(port)
// → 3000 if available
// → 3001 if 3000 is taken
// → 3002 if 3001 is also taken
// → etc.

// Default (starts from 1):
const port2 = await detect()

With callback

import detect from "detect-port"

// Callback style:
detect(3000, (err, port) => {
  if (err) {
    console.error(err)
    return
  }

  if (port === 3000) {
    console.log("Port 3000 is available")
  } else {
    console.log(`Port 3000 is taken, using ${port} instead`)
  }
})

User prompt pattern

import detect from "detect-port"
import readline from "readline"

async function getServerPort(preferred: number): Promise<number> {
  const available = await detect(preferred)

  if (available === preferred) {
    return preferred
  }

  // Port is taken — ask user:
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  })

  return new Promise((resolve) => {
    rl.question(
      `Port ${preferred} is in use. Use ${available} instead? (Y/n) `,
      (answer) => {
        rl.close()
        resolve(answer.toLowerCase() === "n" ? preferred : available)
      }
    )
  })
}

// Usage:
const port = await getServerPort(3000)
// → "Port 3000 is in use. Use 3001 instead? (Y/n)"

CLI usage

# CLI:
npx detect-port 3000
# → 3000 (if available)
# → 3001 (if 3000 is taken)

# Check specific port:
npx detect-port 8080

portfinder

portfinder — classic port scanner:

Basic usage

import portfinder from "portfinder"

// Find available port (default starts at 8000):
const port = await portfinder.getPortPromise()
console.log(port) // → 8000 (or next available)

// Start from specific port:
const port2 = await portfinder.getPortPromise({ port: 3000 })
console.log(port2) // → 3000 or next available

// With options:
const port3 = await portfinder.getPortPromise({
  port: 3000,
  stopPort: 3100,  // Don't scan beyond 3100
  host: "127.0.0.1",
})

Callback style

import portfinder from "portfinder"

// Set base port:
portfinder.basePort = 3000

// Set highest port to scan:
portfinder.highestPort = 3100

portfinder.getPort((err, port) => {
  if (err) {
    console.error("No available port found:", err)
    return
  }
  console.log(`Available port: ${port}`)
})

Multiple ports

import portfinder from "portfinder"

// Get multiple consecutive ports:
const ports = await portfinder.getPortPromise({ port: 3000 })
  .then(async (port1) => {
    const port2 = await portfinder.getPortPromise({ port: port1 + 1 })
    return [port1, port2]
  })

console.log(ports) // → [3000, 3001] (or next available pair)

With dev servers

import portfinder from "portfinder"
import { createServer } from "vite"

async function startViteDev() {
  const port = await portfinder.getPortPromise({ port: 5173 })

  const server = await createServer({
    server: { port },
  })

  await server.listen()
  console.log(`Vite dev server: http://localhost:${port}`)
}

Feature Comparison

Featureget-portdetect-portportfinder
API stylePromisePromise + callbackPromise + callback
Default behaviorRandom portScan from preferredScan from 8000
Port range✅ (portNumbers)✅ (stopPort)
Exclude ports
Host option
CLI
ESM-only
Dependencies012
TypeScript✅ (@types)
Maintained✅ (Sindre Sorhus)✅ (Alibaba)⚠️
Weekly downloads~10M~10M~10M

When to Use Each

Use get-port if:

  • Want a minimal, zero-dependency port finder
  • Need random port assignment or port ranges
  • Building modern ESM projects
  • Want to exclude specific ports

Use detect-port if:

  • Want auto-incrementing port fallback (3000 → 3001 → 3002)
  • Need a CLI for quick port checks
  • Building tools where user confirmation of port change is needed
  • In the Alibaba/Egg.js ecosystem

Use portfinder if:

  • Need legacy callback support
  • Want configurable port scan range (base + stop)
  • Existing project already uses it
  • Need a battle-tested port finder

Methodology

Download data from npm registry (weekly average, February 2026). Feature comparison based on get-port v7.x, detect-port v2.x, and portfinder v1.x.

Compare networking utilities and developer tooling on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.