Node.js can expose a running process to a debugger through the V8 Inspector protocol. Use the inspector when a runtime bug needs breakpoints, startup tracing, or variable inspection instead of only log output.

The inspector listener is a local TCP endpoint, and Node.js listens on 127.0.0.1:9229 by default. Keeping the listener on loopback lets local debugger clients attach without opening the debug port to other machines.

The built-in node inspect client keeps the attach path reproducible from a terminal. Chrome DevTools, Edge DevTools, Visual Studio Code, and other inspector clients can attach to the same host and port after the process is started with the inspector enabled.

Steps to debug a Node.js process with the inspector:

  1. Keep the inspector address on loopback unless remote access is protected by a tunnel or firewall.

    Do not bind the inspector to 0.0.0.0 on an untrusted network. A client that reaches the inspector can run code inside the Node.js process.

  2. Start the target script with the inspector paused before user code.
    $ node --inspect-brk=127.0.0.1:9229 server.mjs
    Debugger listening on ws://127.0.0.1:9229/4d8a7b3e-9b22-4b2d-9f3d-6c41d2a8e717
    For help, see: https://nodejs.org/learn/getting-started/debugging

    Replace server.mjs with the application entry point. Use --inspect instead of --inspect-brk when the process should start immediately instead of stopping before user code.

  3. Attach the built-in CLI debugger from a second terminal.
    $ node inspect 127.0.0.1:9229
    connecting to 127.0.0.1:9229 ... ok
    debug> Break on start in server.mjs:1
    > 1 import http from "node:http";
      2 
      3 const server = http.createServer((request, response) => {
    debug>
  4. Continue the paused process from the debugger prompt.
    debug> cont

    The node inspect prompt also accepts debugger commands such as next, step, out, and repl after execution reaches code that needs inspection.

  5. Confirm the application still answers after continuing from the debugger.
    $ curl --silent http://127.0.0.1:3000/
    debug-ready

    Use the application's normal smoke test when the process is not an HTTP server or listens on a different local port.