How do I run a system command or an external program in NodeJS?
NicolasBrondinBernard
If seeing the "node-ffmpeg" library made you think ffmpeg had been rewritten in JS, then read this article to the end!

Article published on 21/07/2020, last updated on 09/08/2026
It sometimes happens that the APIs provided by NodeJS for interacting with the system aren't enough for our needs. Imagine, for example, that you need your program to shut down the machine after it finishes running.
Even better, what if you needed to launch an external program and control its execution from NodeJS! How do you do that?
The answer to this problem is simple: we're going to use the child_process module.
Child processes
As you probably know, the operating system manages many processes simultaneously, some of which are dependent on the process that created them: these are called "child processes".
For example, Chrome launches a child process for every new tab. These processes can be closed independently, but if you close the parent process, all the others are destroyed too!
This mechanism prevents leaving behind ghost processes that would consume resources unnecessarily.
Launching a new process
Launching a new process is very simple in NodeJS, it only takes two lines of code:
const child_process = require('child_process');
let ls_process = child_process.exec("ls -a");
exec() vs spawn()
There are two different methods for creating a new process, each with its own particularities. Here's the same piece of code as before with the spawn method.
const child_process = require('child_process');
let ls_process = child_process.spawn("ls",["-a"]);
The differences are:
- exec() creates a shell in which it will pass the command to be executed
- spawn() continuously streams the data returned by the process, whereas exec() returns it at the end of execution
- exec() is limited to a data transfer of 200kb by default
Ultimately, if you want to run a simple command, use exec() instead, whereas for launching an external program with which you're going to communicate, we'll favor spawn(), as in the rest of this tutorial!
Controlling a process
Launching a process isn't everything, you also need to be able to send it information and receive what it sends back to us, whether during a successful execution or in case of an error.
stdin, stdout, stderr
If you've never heard of them, here are the three standard data streams (std) of a program: input (in), output (out), and errors (err).
When a program asks you to enter information via keyboard after launching, you're sending information into the standard input, and when it displays text in the terminal, it's simply redirecting its standard output to the terminal (same thing for errors).
Listening to data streams
Data streams are handled by events that you need to subscribe to, as in the example below:
ls_process.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls_process.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
Keep in mind that the format of the returned data is specific to the external program being invoked and sometimes to the particular command of that program.
Writing to the standard input
Instead of invoking a program that will run based on the parameters passed at initialization and then close, it's sometimes wise to use programs that run in the background and take commands on the fly.
This method is particularly useful for programs that take a certain amount of time to start up. Here's an example of sending data to a running program:
ls_process.stdin.setEncoding('utf-8');
ls_process.stdin.write("play");
//it is sometimes necessary to add a \n at the end of the command to validate the sending
ls_process.stdin.end();
For the rest, I'll let you get familiar with all the many features of the child_process module directly in the official documentation available here: https://nodejs.org/api/child_process.html
Note
When you come across video, image, or audio processing libraries in NodeJS (such as node-ffmpeg for example), you should be aware that these libraries are not coded in Javascript (most of the time), but these libraries are only wrappers that run an external program written in a lower-level language.
Now you too can write your own wrappers!
Warning: When you call system commands, your program becomes dependent on that particular system and may not run on another OS (unless you account for all possible cases), so this must be done with full awareness of the execution environment!
No spam. Only free content, news, and ever more resources to level up your skills!
Join +1500 developers
No comments yet