I'm writing an application using Node.js.
One of the functions I want to create is to open the default web browser and navigate to a specific URL.
I want it to be portable so that it runs on Windows/Mac/Linux.
I'm writing an application using Node.js.
One of the functions I want to create is to open the default web browser and navigate to a specific URL.
I want it to be portable so that it runs on Windows/Mac/Linux.
Use open (formerly known as opn) because it will handle the cross platform issue. To install:
$ npm install open
To use:
const open = require('open');
// opens the url in the default browser
open('http://sindresorhus.com');
// specify the app to open in
open('http://sindresorhus.com', {app: 'firefox'});
var url = 'http://localhost';
var start = (process.platform == 'darwin'? 'open': process.platform == 'win32'? 'start': 'xdg-open');
require('child_process').exec(start + ' ' + url);
&'s in the URL should be escaped with ^&node-open is deprecated. Now use open:
const open = require('open')
await open('http://sindresorhus.com') // Opens the url in the default browser
await open('http://sindresorhus.com', {app: 'firefox'}) // Specify the app to open in
Install:
$ npm install open
Usage:
const open = require('open');
(async () => {
// Opens the image in the default image viewer and waits for the opened app to quit.
await open('unicorn.png', {wait: true});
console.log('The image viewer app quit');
// Opens the URL in the default browser.
await open('https://sindresorhus.com');
// Opens the URL in a specified browser.
await open('https://sindresorhus.com', {app: 'firefox'});
// Specify app arguments.
await open('https://sindresorhus.com', {app: ['google chrome', '--incognito']});
})();
You may need to implement a switch using the value of ...
require('os').type()
And then use spawn("open") or spawn("xdg-open") depending on the platform?
require('child_process').spawn('explorer', ['url']) is a nice oneliner!The easiest and neatest way, IMHO is using an npm package called openurl. Do a npm install openurl . You could try this real quick in your Nodejs REPL
require("openurl").open("http://stackoverflow.com/questions/8500326/how-to-use-nodejs-to-open-default-browser-and-navigate-to-a-specific-url")
You could also send emails with it if the need arises like so;
require("openurl").open("mailto:[email protected]")
#!/usr/bin/env node
const url = 'http://localhost'
require('child_process')
.exec((process.platform
.replace('darwin','')
.replace(/win32|linux/,'xdg-') + 'open ' + url));
var url = '\\index.html';
var start = (process.platform == 'darwin'? 'open': process.platform == 'win32'? 'start': 'xdg-open');
require('child_process').exec(start + ' ' + __dirname + url);
Lexa-B’s answer worked best for me, but I was getting “Windows could not locate index.html” error. I was using lexa-b code child_process exec command to open a local webpage within an npm package I was writing. Needed to open an html file in my npm package when running it / opening it from package bin.js with npx command.
All that was needed was to append __dirname to file path to ensure the relative directory path to the file calling the child_process was correct. The child_process was running at the home folder, which is far away from the npx temp file location. __dirname solves that problem and links the two, solving my missing file error.
The open package now forces you to use import tested as of v10.1.0 in Node.js < 22
I don't understand all the details, there is likely a rationale, but it is extremely annoying that you can't just require anymore, instead you have to:
main.js
import open from 'open'
open('http://example.com')
with mandatory "type": "module", in:
package.json
{
"name": "test",
"version": "1.0.0",
"type": "module",
"dependencies": {
"open": "10.1.0"
}
}
then it worked:
node main.js
If you try:
const open = require('open')
open('http://example.com')
then it fails with:
file:///home/ciro/tmp/open/main.js:1
const open = require('open')
^
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/home/ciro/tmp/open/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
at file:///home/ciro/tmp/open/main.js:1:14
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:34:7)
at async handleMainPromise (node:internal/modules/run_main:113:12)
Node.js v20.10.0
If you forget the:
"type": "module",
then it fails with:
(node:67598) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/home/ciro/tmp/open/main.js:1
import open from 'open'
^^^^^^
SyntaxError: Cannot use import statement outside a module
at internalCompileFunction (node:internal/vm:77:18)
at wrapSafe (node:internal/modules/cjs/loader:1288:20)
at Module._compile (node:internal/modules/cjs/loader:1340:27)
at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
at Module.load (node:internal/modules/cjs/loader:1207:32)
at Module._load (node:internal/modules/cjs/loader:1023:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
at node:internal/main/run_main_module:28:49
Node.js v20.10.0
as per: "Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6
Option 2: dynamic import
This works without any changes to anything else:
(async () => {
const { default: open } = await import('open')
open('http://example.com')
})()
The default thing is mentioned e.g. at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
Limitations:
Option 3: revert to v8
require break seems to be in v9, so going to v8 is a workaround.
"dependencies": {
"open": "8.4.2",
Docs
The README has a warning about this mess:
Warning: This package is native ESM and no longer provides a CommonJS export. If your project uses CommonJS, you will have to convert to ESM or use the dynamic import() function. Please don't open issues for questions regarding CommonJS / ESM.
and it links to: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c which explains things a bit.
Tested on Node.js v20.10.0, Ubuntu 24.04.