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

imagic-browser-launcher

v1.0.3

Published

Launch and control Chromium browser instances

Readme

imagic-browser-launcher

Launch and manage a Chromium-based browser process with remote debugging enabled.

Install

npm install imagic-browser-launcher

Quick Start

import Launcher from 'imagic-browser-launcher'

const browser = new Launcher({
    browserPath: '/usr/bin/chromium',
    url: 'https://example.com',
    debug: true,
})

const pid = await browser.launch()
console.log('Browser PID:', pid)

// Terminate when done
browser.kill()

API

new Launcher(options?)

Creates a new launcher instance. The browser process is not started until .launch() is called.

new Launcher(options?: {
    browserPath?: string    // default: '/usr/bin/chromium'
    port?: number | null    // default: null  (random free port assigned at launch)
    profileDir?: string     // default: '/tmp/chromium-profile'
    url?: string            // default: 'about:blank'
    flags?: string[]        // default: []
    launchTimeout?: number  // milliseconds; default: 10000
    debug?: boolean         // default: false
    detached?: boolean      // default: false
})

| Option | Type | Default | Description | |--------|------|---------|-------------| | browserPath | string | '/usr/bin/chromium' | Absolute path to the browser executable | | port | number \| null | null | Remote debugging port. When null, a random free OS port is assigned at launch time | | profileDir | string | '/tmp/chromium-profile' | Path to the browser user data directory (--user-data-dir) | | url | string | 'about:blank' | URL opened when the browser starts; appended as the last CLI argument | | flags | string[] | [] | Extra CLI flags. --remote-debugging-port and --user-data-dir are injected automatically unless already present in this array | | launchTimeout | number | 10000 | Milliseconds to wait for the remote debugging port to become reachable before giving up | | debug | boolean | false | Print internal status messages to console.log | | detached | boolean | false | Spawn the process detached from the parent. On kill, the entire process group is terminated (SIGKILL on -pid) |


launcher.launch(): Promise<number | null>

Spawns the browser and waits for its remote debugging port to accept TCP connections.

Returns the process PID (number) on success, or null when:

  • A launch is already in progress
  • An existing browser is already listening on the configured port
  • The debugging port did not become ready within launchTimeout

Automatically registers SIGINT, SIGTERM, and exit handlers on the Node.js process to call kill() on exit. Any previously registered handlers from a prior launch are removed before new ones are added.

Throws Error if the browser executable is not found at browserPath.


launcher.kill(): void

Sends SIGKILL to the browser process and removes all registered signal handlers.

Safe to call multiple times — no-op if the process is already gone or was never started. Sets this.process to null after killing.

When detached: true, kills the entire process group via process.kill(-pid, 'SIGKILL').


launcher.waitUntilReady(): Promise<boolean>

Polls isDebuggerReady() every 250 ms until the port opens or launchTimeout elapses.

Returns false immediately if the spawned process is killed while polling.


launcher.isDebuggerReady(): Promise<boolean>

Attempts a TCP connection to 127.0.0.1:{port} with a 2-second internal timeout.

Returns true on a successful connection, false on any error or timeout. Never throws.


launcher.getFlags(): string[]

Returns the full list of CLI arguments that will be (or were) passed to the browser.

Always includes --remote-debugging-port={port} and --user-data-dir={profileDir} unless those keys are already present in options.flags. The url is appended last.


launcher.delay(ms): Promise<void>

Resolves after ms milliseconds. Used internally between polling attempts.


launcher.log(...args): void

Writes to console.log when debug: true. No-op otherwise.


Instance properties

| Property | Type | Description | |----------|------|-------------| | process | ChildProcess \| null | The spawned child process; null before launch or after kill | | port | number \| null | Debugging port in use; populated at launch time if not specified in options |

Error Handling

launch() throws a plain Error when the executable is missing:

Error: [Launcher] Browser not found at: /usr/bin/chromium

All other failure modes (timeout, process exiting early) cause launch() to return null. In every failure case kill() is called internally to clean up state and signal handlers.

isDebuggerReady() never throws — all network errors are caught and resolved as false.

Examples

See examples/index.js for a complete headless Chromium setup.

import Launcher from '../src/index.js'

const browser = new Launcher({
    browserPath: '/path/to/chrome',
    port: 9223,
    url: 'https://example.com',
    flags: [
        '--headless=new',
        '--no-sandbox',
        '--disable-gpu',
        '--disable-dev-shm-usage',
    ],
    debug: true,
})

browser
    .launch()
    .then((pid) => console.log('Browser PID:', pid))
    .catch((err) => console.error('Launch failed:', err))

License

MIT