Read File in Node.js using the fs module

We can read a file in Node.js using the built-in fs module. The most common method is fs.readFile(), which reads the complete file asynchronously and gives the result to a callback function.

In this tutorial, we shall learn how to read a file in Node.js using Node FS, how the readFile() callback works, when to pass an encoding such as utf8, and when a stream is a better choice for large files.

A Node.js example program that uses readFile() function is also provided. The examples use CommonJS syntax with require(), which matches many beginner Node.js projects.

Steps to read a file in Node.js with fs.readFile()

Following is a step by step guide to read content of a File in Node.js :

Step 1 : Include File System built-in module to your Node.js program.

</>
Copy
var fs = require('fs');

Step 2 : Read file using readFile() function.

</>
Copy
fs.readFile('<fileName>',<callbackFunction>)

Callback function is provided as an argument to readFile function. When reading the file is completed (could be with or without error), call back function is called with err(if there is an error reading file) and data(if reading file is successful).

Step 3 : Create a sample file, say sample.html with some content in it. Place the sample file at the location of node.js example program, which is provided below.

Example 1 – Read File in Node.js

readFileExample.js

</>
Copy
// include file system module
var fs = require('fs');

// read file sample.html
fs.readFile('sample.html',
	// callback function that is called when reading file is done
	function(err, data) {		
		if (err) throw err;
		// data is a buffer containing file content
		console.log(data.toString('utf8'))
});

Open a terminal or command prompt and run the program using node command.

Output

$ node readFileExample.js
<html>
<body>
<h1>Header</h1>
<p>I have learnt to read a file in Node.js.</p>
</body>
</html>

What fs.readFile() returns in the Node.js callback

The callback passed to fs.readFile() follows the usual Node.js error-first callback pattern. The first argument contains an error object if the file cannot be read. The second argument contains the file data when the read operation succeeds.

  • err is usually checked first. If it is not null, handle the error and return from the callback.
  • data is a Buffer when you do not pass an encoding.
  • data is a string when you pass an encoding such as 'utf8'.

The example above reads the file as a buffer and then converts it using data.toString('utf8'). For a text file, you can also pass the encoding directly to readFile().

Read a text file in Node.js as a UTF-8 string

If you are reading a text, HTML, JSON, CSV, or log file and want a string result, pass 'utf8' as the second argument. This avoids manually converting the buffer after the file is read.

readTextFile.js

</>
Copy
const fs = require('fs');

fs.readFile('sample.txt', 'utf8', function (err, content) {
    if (err) {
        console.error('Could not read file:', err.message);
        return;
    }

    console.log(content);
});

Run the file from the terminal with the following command.

</>
Copy
node readTextFile.js

For example, if sample.txt contains two lines, the output will be printed as text.

Hello Node.js
Reading files with fs.readFile()

Read a file path safely with __dirname in Node.js

A common mistake is assuming that fs.readFile('sample.txt') always reads from the same folder as the JavaScript file. Relative file paths are resolved from the current working directory where the Node.js process is started. To build a path relative to the current script, use __dirname with the path module.

readWithPath.js

</>
Copy
const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'sample.html');

fs.readFile(filePath, 'utf8', function (err, content) {
    if (err) {
        console.error('File read failed:', err.message);
        return;
    }

    console.log(content);
});

This is useful when your script may be executed from a different directory, such as from an npm script, a scheduler, or another parent process.

Read a file in Node.js using fs.promises

Modern Node.js code often uses promises and async/await. The promise-based file system API is available from fs/promises. It reads the same file content, but lets you use try...catch instead of a callback.

readFilePromise.js

</>
Copy
const fs = require('fs/promises');

async function readFileContent() {
    try {
        const content = await fs.readFile('sample.html', 'utf8');
        console.log(content);
    } catch (err) {
        console.error('Could not read file:', err.message);
    }
}

readFileContent();

Use this style when the rest of your Node.js code is already written with promises or async/await.

Read a file synchronously in Node.js with fs.readFileSync()

fs.readFileSync() blocks the current Node.js thread until the file has been read. It is simple for small scripts, setup files, and command-line utilities, but it should be avoided in request handlers of web servers because it can block other work.

readFileSyncExample.js

</>
Copy
const fs = require('fs');

try {
    const content = fs.readFileSync('sample.html', 'utf8');
    console.log(content);
} catch (err) {
    console.error('Could not read file:', err.message);
}

Use createReadStream() for large files in Node.js

fs.readFile() loads the whole file into memory before the callback runs. This is fine for small and medium-sized files. For large files, such as big logs, exports, videos, or uploads, use fs.createReadStream() so that Node.js can process the file in chunks.

readLargeFileStream.js

</>
Copy
const fs = require('fs');

const stream = fs.createReadStream('large-log.txt', { encoding: 'utf8' });

stream.on('data', function (chunk) {
    console.log('Received chunk:', chunk.length);
});

stream.on('error', function (err) {
    console.error('Stream error:', err.message);
});

stream.on('end', function () {
    console.log('Finished reading file');
});

Choose readFile() when you need the complete content at once. Choose streams when you want lower memory usage or want to pipe data to another destination.

Common Node.js fs.readFile() errors and fixes

Error or symptomLikely reasonPractical fix
ENOENT: no such file or directoryThe file path is wrong, or the process is running from a different directory.Check the filename and use path.join(__dirname, 'file-name') when needed.
EACCES: permission deniedThe Node.js process does not have permission to read the file.Update file permissions or run the process with the correct user.
Output shows numbers or unreadable contentThe result is a Buffer, or the file is not plain text.Pass 'utf8' for text files, or keep the buffer for binary files.
Application becomes slow while reading a large fileThe full file is loaded into memory.Use fs.createReadStream() for large files.

Node.js readFile(), readFileSync(), and createReadStream() comparison

MethodHow it worksBest use case
fs.readFile()Asynchronously reads the complete file and calls a callback.Most beginner and application-level file reads where the file size is manageable.
fs.promises.readFile()Asynchronously reads the complete file and returns a promise.Projects that use async/await.
fs.readFileSync()Synchronously reads the complete file and blocks execution until finished.Small scripts, configuration loading, and simple command-line tools.
fs.createReadStream()Reads the file in chunks using a stream.Large files or data that should be processed progressively.

FAQs on reading files in Node.js using fs

How to read file in Node.js using Node fs?

Use the built-in fs module and call fs.readFile(filePath, encoding, callback). For a text file, pass 'utf8' as the encoding and handle both err and data inside the callback.

Why does fs.readFile() return a Buffer in Node.js?

fs.readFile() returns a Buffer when no encoding is provided. A buffer is suitable for binary data. For text data, pass an encoding such as 'utf8' or call data.toString('utf8').

Should I use fs.readFile() or fs.readFileSync()?

Use fs.readFile() or fs.promises.readFile() for most application code because they do not block the event loop while the file is being read. Use fs.readFileSync() only when blocking is acceptable, such as in a small script or startup configuration step.

How do I fix ENOENT while reading a file in Node.js?

ENOENT usually means Node.js cannot find the file at the given path. Check the filename, extension, and folder. If the file should be relative to the script, build the path with path.join(__dirname, 'file-name').

Is fs.readFile() good for large files in Node.js?

fs.readFile() reads the whole file into memory, so it is not the best choice for very large files. Use fs.createReadStream() when you need to process large files in chunks.

Editorial QA checklist for this Node.js read file tutorial

  • Confirm that the tutorial explains both callback-based fs.readFile() and the effect of passing 'utf8'.
  • Check that every Node.js file reading example handles the error case before using the file content.
  • Verify that examples distinguish between buffer output, string output, synchronous reads, promise-based reads, and streams.
  • Ensure the path guidance explains current working directory issues and the use of __dirname.
  • Keep large-file guidance practical by recommending fs.createReadStream() instead of loading the whole file into memory.

Summary: reading files in Node.js with Node FS

In this Node.js TutorialNode FS, we have learnt to read a File in Node.js using File System built-in module. Node.js example program has been provided that uses readFile() function.

For text files, pass 'utf8' to get a string directly. For modern asynchronous code, use fs/promises with async/await. For large files, prefer fs.createReadStream() so the file is handled in chunks instead of being loaded completely into memory.