File paths look different on Windows (C:\\Users\\me) than on macOS or Linux (/Users/me). The path module lets you build and inspect file paths in a way that works correctly on every operating system.
What Is the path Module?
path is a built-in Node.js module for working with file and directory paths. Instead of concatenating strings with / (which breaks on Windows) or \\ (which breaks everywhere else), you use path.join(), path.resolve(), and related helpers that handle platform differences automatically.
It also provides helpers to pull apart a path into useful pieces: the directory (dirname), the file name (basename), and the extension (extname), which are used constantly when working with uploads, logs, and static assets.
path.join() automatically inserts the correct separator (/ or \\) for the current operating system, so the same code works everywhere.
Core path Methods
path.join(...segments) // combine segments into one path
path.resolve(...segments) // combine into an absolute path
path.basename(p) // final segment, e.g. file name
path.dirname(p) // parent directory
path.extname(p) // file extension
path.join() combines segments but does not guarantee an absolute path.
path.resolve() always returns an absolute path, resolved against the current working directory if needed.
path.basename(p, ext) can optionally strip a known extension from the result.
path.sep gives the platform-specific separator (/ or \\) if you ever need it directly.
path Module Cheatsheet
The path helpers used in almost every file-handling Node.js script.
Method
Example Input
Example Output
path.join()
path.join('a', 'b', 'c.txt')
'a/b/c.txt'
path.resolve()
path.resolve('c.txt')
/current/working/dir/c.txt
path.basename()
path.basename('/a/b/c.txt')
'c.txt'
path.dirname()
path.dirname('/a/b/c.txt')
'/a/b'
path.extname()
path.extname('c.txt')
'.txt'
path.parse()
path.parse('/a/b/c.txt')
{ dir, base, ext, name }
join() vs resolve()
path.join() simply concatenates segments with the correct separator and normalizes ../. in the result, it does not care whether the final path is absolute or relative. path.resolve() always produces an absolute path, working right-to-left until it has built a complete path, using the current working directory as a starting point if none of the segments are already absolute.
A very common real-world pattern is joining __dirname (CommonJS) or a computed equivalent (ES modules) with a relative path, so file lookups work correctly no matter which directory the process was started from.
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const configPath = path.join(__dirname, 'config', 'default.json');
Common Mistakes
Building paths with manual string concatenation (dir + '/' + file) instead of path.join().
Assuming path.join() returns an absolute path when it may return a relative one.
Forgetting that path.resolve() uses the current working directory, which can differ from the script's own directory.
Using forward slashes hardcoded in path logic that later needs to run on Windows.
Key Takeaways
The path module builds and inspects file paths in a platform-independent way.
path.join() concatenates segments; path.resolve() always returns an absolute path.
basename, dirname, and extname extract specific pieces of a path.
Combining path.join() with __dirname (or its ESM equivalent) makes file lookups reliable regardless of the current working directory.
Pro Tip
Never hardcode / or \\ in path-building logic, always use path.join()/path.resolve(), even if you only ever plan to deploy to Linux. It costs nothing and prevents subtle bugs on any future Windows-based dev machine or CI runner.
You can now build file paths safely across operating systems. Next, explore the os module for reading system-level information.