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

n8n-nodes-browser-cli

v0.3.1

Published

n8n community node that controls a remote browser by talking directly to a browser-cli serve endpoint (Ed25519 + post-quantum encrypted)

Readme

n8n-nodes-browser-cli

An n8n community node, published on npm as n8n-nodes-browser-cli, that controls a real, visible browser from your workflows via browser-cli.

browser-cli drives a running browser through a native-messaging host and a browser extension — it cannot be installed inside the n8n container. So this node speaks the browser-cli serve protocol directly: a length-framed TCP connection authenticated with an Ed25519 key, with request/response bodies encrypted end-to-end via an ML-KEM-768 (post-quantum) key exchange — the same wire protocol the browser-cli --remote client uses.

n8n workflow ──TCP (Ed25519 + ML-KEM-768)──▶ browser-cli serve (remote host) ──▶ browser

Because the payloads are end-to-end encrypted, the endpoint is safe to expose on an untrusted network without a TLS proxy in front of it.

Remote setup (on the browser machine)

Install browser-cli, register the extension, trust your n8n key, then start serve opening exactly the command tiers you need (it is safe-only by default):

uv tool install real-browser-cli
browser-cli install brave            # one-time: register the extension/native host

# On the n8n side, generate a client key and print its public key:
browser-cli auth keygen -o n8n_key.pem

# On the browser machine, trust that public key (optionally scope its policy):
browser-cli auth trust <pubkey-hex> --allow-control

# Expose the browser. Open only what your workflow needs:
browser-cli serve --host 0.0.0.0 --port 8765 \
  --authorized-keys ~/.browser_cli/authorized_keys --allow-read-page --allow-control

Paste the contents of n8n_key.pem into the n8n credential.

n8n credential — "Browser CLI API"

| Field | Description | |-------|-------------| | Host | host of the serve endpoint, e.g. browser-host.example | | Port | serve TCP port (default 8765) | | Ed25519 Private Key | PKCS8 PEM from browser-cli auth keygen (empty only for --no-auth loopback) | | Browser Alias | optional _route target — required if the endpoint serves multiple browsers | | Server Public Key/Fingerprint | pinned browser-cli serve identity (SHA256:... fingerprint or 64-char server public key hex) | | Allow Unknown Server Identity | disables SSH-style server pinning; use only for loopback/dev | | Use TLS | wrap the connection in TLS (only for a TLS-terminating proxy; the protocol is already encrypted) | | Ignore SSL Issues | when TLS is on, accept a self-signed proxy cert |

Server identity pinning

Recent browser-cli serve versions advertise a persistent Ed25519 server identity in the challenge frame. The n8n node verifies the challenge signature and compares the key against the credential's Server Public Key/Fingerprint field, similar to SSH known_hosts.

On a trusted machine, pin the server once with the Python CLI and copy the fingerprint into the n8n credential:

browser-cli remote trust-host browser-host.example:8765
browser-cli remote known-hosts

If the server key changes, the node fails with REMOTE SERVER IDENTITY CHANGED. Only enable Allow Unknown Server Identity for local/dev endpoints where you explicitly do not want pinning.

Operations

Every operation maps to one raw browser-cli command, each subject to the server policy tier noted below.

| Resource | Operation | Command | Server flag needed | |----------|-----------|---------|--------------------| | Tab | List / Query / Get / Count / Filter / Active in Window | tabs.list / tabs.query / tabs.status / tabs.count / tabs.filter / tabs.active_in_window | safe (default) | | Tab | Get HTML | tabs.html | --allow-read-page | | Tab | Open / Close / Activate / Move / Navigate To / Reload / Hard Reload / Back / Forward | navigate.open / tabs.close / tabs.active / tabs.move / navigate.to / navigate.reload / navigate.hard_reload / navigate.back / navigate.forward | --allow-control | | Tab | Mute / Unmute / Pin / Unpin / Dedupe / Sort / Merge Windows | tabs.mute / tabs.unmute / tabs.pin / tabs.unpin / tabs.dedupe / tabs.sort / tabs.merge_windows | --allow-control | | Tab | Screenshot | tabs.screenshot | --allow-dangerous | | Page | Get Info | page.info | safe (default) | | Page | Extract Text / Links / Images / HTML / Markdown / JSON | extract.* | --allow-read-page | | DOM | Query / Text / Attribute / Exists | dom.query / dom.text / dom.attr / dom.exists | --allow-read-page | | DOM | Click / Type / Select / Hover / Focus / Check / Uncheck / Clear / Submit / Scroll / Key | dom.* | --allow-control | | DOM | Eval | dom.eval | --allow-dangerous | | Group | List / Query / Tabs | group.list / group.query / group.tabs | safe (default) | | Group | Count / Create / Add Tab / Move / Close | group.count / group.open / group.add_tab / group.move / group.close | --allow-control | | Window | List | windows.list | safe (default) | | Window | Open / Close / Rename | windows.open / windows.close / windows.rename | --allow-control | | Session | List / Save / Load / Remove / Export / Diff / Auto Save | session.* | --allow-control | | Storage | Get / Set | storage.get / storage.set | --allow-dangerous | | Performance | Status | perf.status | safe (default) | | Extension | Info / Capabilities | extension.info / extension.capabilities | safe (default) | | Extension | Reload | extension.reload | --allow-control | | Client | List | clients.list | safe (default) | | Command | Execute | any command name + JSON args | per command |

Command → Execute is the escape hatch: any command string the server policy allows (tabs.query, session.save, windows.list, …) with a JSON args object. Use it for anything the typed operations don't cover.

Note: serve returns the raw command result (no SDK post-processing). extract.markdown therefore returns the page payload as the extension hands it back, not the CLI's rendered Markdown. For clean text use Extract Text.

Tab → Filter / Count URL Pattern: matched against the full tab URL. A plain string is a case-sensitive substring (twitch.tv); a pattern containing * or ? is a glob (twitch.tv/*, *.twitch.tv). Glob needs the serve-side extension at 0.16.4+; older extensions treat the whole pattern as a literal substring, so twitch.tv/* matches nothing there — use twitch.tv instead.

Develop / build

cd n8n-nodes-browser-cli
npm install                 # add --ignore-scripts if a transitive native dep
                            # (isolated-vm) fails to compile on your Node version
npm test          # pure unit tests: command mapping + crypto known-answer vectors
npm run build     # tsc -> dist/, copies the icon

Install the published package in n8n as a community node using the package name n8n-nodes-browser-cli, or symlink dist/ into ~/.n8n/custom for local testing.

License

PolyForm Noncommercial License 1.0.0 — same as browser-cli.