Skip to content

Random Port Generator — TypeScript source

Generate one or many random TCP/UDP port numbers across registered, ephemeral, or the full range - optionally unique. Runs entirely in your browser with crypto-grade randomness.

This is the TypeScript implementation — the same logic the interactive tool runs, in a shareable, citable form.

// Pure random port generator. Zero deps; an injectable RNG makes generation
// deterministic for tests. The unit-test surface for the Random Port Generator.

export type PortRange = 'any' | 'registered' | 'ephemeral' | 'custom';

export interface PortOptions {
  range?: PortRange;
  min?: number; // custom-range lower bound
  max?: number; // custom-range upper bound
  count?: number; // how many ports (for randomPorts)
  unique?: boolean; // dedupe (for randomPorts)
  rng?: () => number; // injectable random in [0, 1)
}

const RANGES: Record<'any' | 'registered' | 'ephemeral', [number, number]> = {
  any: [1, 65535],
  registered: [1024, 49151],
  ephemeral: [49152, 65535],
};

function defaultRng(): number {
  return crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32;
}

export function resolveRange(opts: PortOptions): { lo: number; hi: number } {
  if (opts.range === 'custom') return { lo: opts.min ?? 1, hi: opts.max ?? 65535 };
  const [lo, hi] = RANGES[opts.range ?? 'registered'];
  return { lo, hi };
}

function assertRange(lo: number, hi: number): void {
  if (!Number.isInteger(lo) || !Number.isInteger(hi) || lo < 0 || lo > 65535 || hi > 65535 || lo > hi) {
    throw new Error(`Invalid port range ${lo}-${hi}`);
  }
}

export function randomPort(opts: PortOptions = {}): number {
  const rng = opts.rng ?? defaultRng;
  const { lo, hi } = resolveRange(opts);
  assertRange(lo, hi);
  return lo + Math.floor(rng() * (hi - lo + 1));
}

export function randomPorts(opts: PortOptions = {}): number[] {
  const count = Math.max(1, opts.count ?? 1);
  const { lo, hi } = resolveRange(opts);
  assertRange(lo, hi);
  if (!opts.unique) return Array.from({ length: count }, () => randomPort(opts));

  // Fisher-Yates partial shuffle over the range to pick `n` unique ports.
  const capacity = hi - lo + 1;
  const n = Math.min(count, capacity);
  const rng = opts.rng ?? defaultRng;
  const pool = Array.from({ length: capacity }, (_, i) => lo + i);
  for (let i = 0; i < n; i++) {
    const j = i + Math.floor(rng() * (capacity - i));
    [pool[i], pool[j]] = [pool[j], pool[i]];
  }
  return pool.slice(0, n);
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →