Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use a browser runner when your JavaScript must execute against a real URL. A tool such as browser-run starts a browser (Electron by default), reads JavaScript from standard input, and streams console output. Use npm exec (or its npx alias) when the npm package exposes a command you want to invoke; npm can resolve a package, version, tag, tarball URL, or Git URL for that command. These are different jobs: one supplies a page context with location and the DOM, while the other launches a Node-oriented executable.

Choose the execution model first

The phrase “run JavaScript on a URL” can mean two different things. Decide which one matches your code before installing anything.

Browser-context code

Choose a browser runner when the script needs window, document, location, cookies, layout, or other page APIs. The browser actually opens (or serves) content, then evaluates your script in that page. browser-run is designed for this workflow and describes itself as “The easiest way of running code in a browser environment.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Node command with an npm dependency

Choose npm exec when a package provides a command-line program. It resolves the requested package and runs its executable, but it does not navigate to a URL or create a DOM by itself. Your command must perform any HTTP request, browser launch, or other URL handling.

Need Use What you get
Read or modify a live page browser-run Browser globals, DOM, page navigation and console output
Invoke a package’s CLI npm exec/npx Node process and the package’s command arguments
Run in Linux CI without a display Browser runner plus Xvfb A virtual display for headed-browser software

Install and run browser-run

One-off installation

Install locally in a project so the version is recorded in package.json and your lockfile:

npm install browser-run

For a globally available command, the project documents:

npm install -g browser-run

The CLI reads JavaScript from standard input. This minimal example prints the page location and then closes the browser:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
echo "console.log('Hey from ' + location); window.close()" | browser-run

Expect the CLI to report a localhost page URL while it starts its web server and browser. Calling window.close() is important in scripts that should terminate unattended; otherwise the browser can remain open waiting for more input.

Use a script file

Put browser code in a file and pipe it to the command:

cat > inspect.js <<'EOF'
console.log('URL:', location.href)
console.log('Title:', document.title)
console.log('Links:', document.links.length)
window.close()
EOF
cat inspect.js | browser-run

Your code runs with page APIs, so DOM queries work without importing a DOM shim. The page URL available through location.href is the URL the browser runner opened or served for that run.

Accept HTML input

The CLI defaults to JavaScript input. With --input html, pass an HTML file instead:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
browser-run --input html page.html

This is useful for testing local markup and scripts. Keep the input mode explicit in automation so a JavaScript file is not accidentally interpreted as HTML.

Load npm packages in the page workflow

npm defines a package as a file or directory described by package.json. Registry names, exact versions, tags, tarball URLs and Git URLs are valid package references. A module in node_modules is loaded with require or import; a loose JavaScript file is not an npm package unless it is described by a package manifest.

Node-side modules and browser-side modules are different

A dependency installed with npm is normally resolved by Node. Browser code can use it only when the runner makes that module available to the page (for example, through a browser-compatible bundle or an explicit Node-integration option). A package that uses filesystem, child-process, or other Node-only APIs cannot automatically run in an ordinary web page.

Keep the boundary visible in your project:

  • Page code: DOM and browser APIs, with no assumption that require exists.
  • Node harness: npm imports, filesystem setup, URL selection, and orchestration.
  • Bridge: only the values you intentionally pass between the harness and page.

Node integration is a deliberate security decision

browser-run exposes a Node-integration switch. Enabling it can make Node APIs available to page code, but it changes the browser’s security model: code loaded from the target page may gain capabilities you did not intend to grant. Keep the default isolation whenever possible. If integration is unavoidable, use trusted content, restrict network access, and treat the run as code execution with access to the credentials and files available to the process.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Browser-run options that matter in automation

The project documents options for selecting a browser, enabling or disabling its sandbox, serving static assets, mocking requests, enabling Node integration, and setting a basedir for requiring modules in Node mode.

Browser and sandbox

Electron is the default browser. Select another supported browser when your page depends on a particular engine. The sandbox is enabled by default; do not disable it merely to hide an installation problem. In CI, first fix missing display or dependency issues, then change isolation only with a documented reason.

Static files and a basedir

Use static assets when the page under test references local JavaScript, CSS, images, or fixtures. Set basedir to the directory from which Node-mode modules should resolve so that relative imports behave consistently on a developer machine and in CI.

Request mocking

Mock requests for deterministic tests or to avoid sending test data to a production endpoint. A mock is not evidence that the real URL behaves the same; keep at least one separate integration run against the real service.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run a package command with npm exec

When the package itself supplies a CLI, use npm’s documented forms:

npm exec -- <pkg>[@<version>] [args...]
npm exec --package=<pkg>[@<version>] -- <cmd> [args...]

For example, the package can be resolved for one invocation rather than added permanently to your project:

npm exec --package=some-cli@1 -- some-cli --help

The npx alias provides the familiar equivalent:

npx some-cli --help

Pin a version in repeatable jobs. An unqualified package name may resolve a newer release later, changing output or command-line behavior. For production builds, record the version in your project or specify it explicitly in the command and review the resulting lockfile or npm cache policy.

What npm exec does not do

npm exec does not open a webpage, wait for client-side rendering, or provide document. If the CLI needs a URL, pass that URL using the CLI’s own documented option. If you need to execute JavaScript inside that page, use a browser automation or browser-run workflow instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Headless Linux and continuous integration

A browser runner normally needs a display, even when no physical monitor is attached. The project documents Xvfb for display-less systems and shows GitHub Actions usage with xvfb-run npm test.

xvfb-run npm test

Adapt the command to your script, for example:

xvfb-run --auto-servernum sh -c 'cat inspect.js | browser-run'

Make CI runs predictable:

  • Install the same browser and npm dependency versions used locally.
  • Use an explicit timeout around the job so a page that never closes cannot consume a runner indefinitely.
  • Close the page with window.close() after assertions and logging.
  • Capture standard output and standard error as build artifacts when diagnosing failures.
  • Separate network-dependent tests from mocked tests and label them accordingly.

Working with arbitrary URLs safely

Navigation and page readiness

A URL can return a redirect, an error page, or HTML that never finishes loading. Log location.href after navigation and wait for the page state your script actually needs rather than assuming the first response is the final document. For dynamic applications, a selector or application-specific readiness signal is more reliable than a fixed short delay.

Authentication and secrets

Do not place passwords or API keys in a URL, shell history, or source file. Supply secrets through the CI secret store or environment variables, and pass only the minimum data to the browser context. Clear test profiles after runs if they contain session cookies.

Cross-origin limits

Browser security rules still apply. A script running on one origin cannot freely read another origin’s DOM merely because it navigated there. Use an approved server-side API, configure the target application for the required access, or run separate page-context scripts for each origin.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Untrusted URLs

If users can submit the URL, treat this as a server-side request-forgery and code-execution boundary. Restrict schemes to HTTP(S), block internal address ranges, isolate the browser process, disable Node integration, and enforce CPU, memory, and time limits.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting

browser-run: command not found

The package is not installed globally or its npm bin directory is not on PATH. Install it locally and invoke the project binary through your package scripts, or install globally and verify the global npm bin path.

The process hangs after printing output

The browser is still open or a pending timer/request keeps the event loop alive. Call window.close() after the final operation, and add a harness-level timeout for failed navigations.

“Display” or Electron startup errors in CI

Run the command under Xvfb as documented, confirm the browser dependencies are installed, and preserve the full startup error. Do not immediately disable the sandbox; that is a separate security trade-off.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

require is undefined in page code

That is expected in an isolated browser page. Bundle a browser-compatible dependency, move the import to the Node harness, or deliberately enable Node integration only for trusted content.

The npm command runs but the URL is unchanged

You invoked a package CLI, not a page runner. Pass the URL using that CLI’s documented argument, or switch to browser-run when the JavaScript must access the page DOM.

Results differ between local and CI

Compare browser choice, viewport, locale, environment variables, installed package versions, network availability, and whether requests were mocked. Pin versions and record the final URL and readiness signal in logs.

Or skip the browser setup

If your goal is a reliable screenshot or PDF of a URL rather than custom in-page computation, ScreenshotNeo provides a single HTTP call. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets you turn each cleanup step off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed; response headers identify the page verdict and whether it was billed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

See the complete parameter list in the ScreenshotNeo documentation. cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

It also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every feature is on every plan; 1,000 screenshots per month are free with no card, and paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Performance, reliability, and cost decisions

  • Local browser runner: best when you need arbitrary JavaScript, DOM assertions, request mocks, or access to local fixtures. Browser startup and CI display setup add operational work.
  • npm exec: simplest for a package command; remote resolution is convenient but should be version-pinned for repeatability.
  • Screenshot service: avoids browser installation and manages capture-specific cleanup. Check the returned verdict and billing headers rather than assuming every response was a successful page.

For high-volume jobs, reuse a controlled browser process where the runner supports it, avoid unnecessary full-page work, and set explicit timeouts. For screenshots, caching with a chosen TTL and bulk capture can reduce repeated requests; ScreenshotNeo supports both, along with asynchronous jobs and signed webhooks.

Frequently Asked Questions

Can I use any npm package directly inside a webpage?

No. The package must be browser-compatible or bundled for the browser. Packages requiring Node-only APIs such as the filesystem need to stay in the Node harness or run with deliberately enabled integration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is npx different from npm exec?

npx is npm’s alias for invoking a package executable; the documented npm exec forms make package and command boundaries explicit.

Do I need Xvfb on every headless run?

Only when the browser software requires a display and your Linux runner has none. The browser-run project documents Xvfb for that environment; a desktop runner with a real display does not need it.

How do I prove which URL was actually tested?

Log location.href from the page after navigation. This reveals redirects and the final origin instead of relying only on the input string.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.