Node.js DOCX-to-PDF conversion: Production-ready implementation guide
Table of contents
High-fidelity DOCX-to-PDF conversion through Nutrient DWS - start with 50 free credits.
To convert Word documents to PDF in Node.js, read a DOCX file, pass its bytes to a conversion engine, and write the returned PDF to disk. Use libreoffice-convert(opens in a new tab) with a separate LibreOffice installation, or Nutrient Node.js SDK without installing Microsoft Office or LibreOffice. Jump to the complete LibreOffice example or the Nutrient example.
Both examples below convert a local DOCX file to PDF. The main deployment difference is the conversion engine: libreoffice-convert starts a LibreOffice process, while Nutrient uses its own engine. Test representative documents with the fonts your application needs before choosing either approach.
Requirements
Before you begin, make sure you have the following installed:
- Node.js(opens in a new tab) — It’s best to use the latest long-term support (LTS) version or a stable version.
- npm(opens in a new tab) — Node Package Manager comes bundled with Node.js, so it’ll be installed by default.
Verify your Node.js and npm installations by running these commands in your terminal:
node -vnpm -vDOCX-to-PDF conversion with Nutrient Node.js SDK
Nutrient Node.js SDK converts Office documents without a separate Office or LibreOffice installation. Its Office-to-PDF guide documents the load() and exportPDF() methods used below. Refer to the getting started guide for setup requirements.
Integrating Nutrient Node.js SDK
Initialize a new Node.js project:
Terminal window npm init -yThis command creates a
package.jsonfile in your project directory, which is essential for managing your project’s dependencies.Install the Nutrient Node.js SDK package:
Terminal window npm install @nutrient-sdk/nodePlace your DOCX document (e.g.
sample.docx) in your project directory.Create a new JavaScript file named
index.cjsin your project directory. This script will handle the conversion process:const { load } = require('@nutrient-sdk/node');const fs = require('node:fs/promises');async function convertDOCXToPDF() {const docx = await fs.readFile('sample.docx');const instance = await load({ document: docx });try {const buffer = await instance.exportPDF();await fs.writeFile('converted.pdf', Buffer.from(buffer));} finally {await instance.close();}}convertDOCXToPDF().catch((error) => {console.error('DOCX to PDF conversion failed:', error.message);process.exitCode = 1;});The
finallyblock closes the document even if export or saving fails. Missing fonts may be substituted; supply font files through thefontsoption as described in the custom font example.By default, the resulting PDF will include a Nutrient watermark. To exclude the watermark, you can specify the
licenseproperty with akeyandappNamewhen calling theload()function. For details on obtaining a trial license key, contact Sales.Execute the script in your terminal to initiate the conversion process:
Terminal window node index.cjs
Once executed, the script will convert the DOCX document to PDF and save the resulting PDF as converted.pdf in your project directory.
Converting DOCX documents using libreoffice-convert
The libreoffice-convert package wraps LibreOffice’s command-line converter. Installing the npm package alone isn’t enough: LibreOffice must also be installed on the machine that runs Node.js.
Install LibreOffice and the npm package
Follow the package’s installation instructions(opens in a new tab) for your operating system:
- macOS — Install LibreOffice in
/Applications. - Linux — Install LibreOffice with your distribution’s package manager, including Writer support for DOCX files.
- Windows — Install LibreOffice with its installer and ensure the
PROGRAMFILESenvironment variable points to the program files directory.
Verify that LibreOffice runs before debugging the Node.js script. For a standard macOS installation, run:
/Applications/LibreOffice.app/Contents/MacOS/soffice --versionOn Linux, use libreoffice --version. On Windows, run soffice.exe --version from the LibreOffice program directory. Install the document’s fonts on the conversion host and make sure the Node.js process can write temporary files.
In a new project directory, initialize npm and install the wrapper:
npm init -ynpm install libreoffice-convertComplete conversion example
Save the following as convert.cjs and place example.docx beside it. The .cjs extension makes the CommonJS imports work even if your project uses ES modules.
const path = require('node:path');const fs = require('node:fs/promises');const { promisify } = require('node:util');const libre = require('libreoffice-convert');const convert = promisify(libre.convert);
async function main() { const inputPath = path.join(__dirname, 'example.docx'); const outputPath = path.join(__dirname, 'example.pdf'); const docx = await fs.readFile(inputPath); const pdf = await convert(docx, 'pdf', undefined); await fs.writeFile(outputPath, pdf); console.log(`Saved ${outputPath}`);}
main().catch((error) => { console.error('DOCX to PDF conversion failed:', error.message); process.exitCode = 1;});Run the script to create example.pdf:
node convert.cjsThe example uses the package’s callback-based convert() API through Node.js promisify(). It reads the entire input and output into memory, so set workload-specific resource limits before exposing it as an upload service.
Troubleshooting LibreOffice conversion
- Could not find soffice binary — Check that LibreOffice is installed in a location the wrapper searches. Being able to run a shell alias isn’t sufficient; the package needs an executable path.
- Missing fonts or changed page breaks — Install the required fonts and compare the output with the source document. Font substitution can change wrapping and pagination.
- Permission errors — Ensure the service account can read the input, write the output, and create temporary files.
- Slow or failed conversions under load — Limit concurrent conversions and test memory use with your largest expected documents.
Nutrient Node.js SDK vs. libreoffice-convert: Complete comparison
Both approaches can serve production workflows when you validate output and manage resource limits. Compare their deployment requirements with your application’s needs.
| Consideration | Nutrient Node.js SDK | libreoffice-convert |
|---|---|---|
| Conversion engine | Included in the SDK | Separate LibreOffice installation |
| Node.js integration | Load a document, export PDF, close the instance | Read a file and call the wrapper’s conversion function |
| Fonts | Supply custom font files when needed | Install fonts on the conversion host |
| Deployment checks | Test runtime, memory, and package size on your target host | Also package LibreOffice and verify executable discovery |
| Support | Commercial SDK support | Community-maintained wrapper and LibreOffice |
Choose Nutrient when you want an integrated document SDK and commercial support. Choose libreoffice-convert when an open source converter fits your needs and you can maintain LibreOffice on the host. Neither choice guarantees identical Word pagination or a particular throughput without testing your documents.
Production considerations for DOCX-to-PDF conversion
Production deployments require careful consideration of memory usage, error handling, and scalability. Test both approaches thoroughly with your expected document types and volumes.
When deploying DOCX-to-PDF conversion in production environments, consider the following important factors.
File validation and security
The following checks reject oversized files and obvious format mismatches. The size limit is an example policy, not a guarantee of safe memory use. A ZIP signature doesn’t prove that a file is a valid or safe DOCX document; other ZIP files share it. Process untrusted uploads in an isolated worker with time and resource limits.
const fs = require('fs').promises;const path = require('path');
async function validateDOCXFile(filePath) { const stats = await fs.stat(filePath);
// Apply an example 100 MB input limit. if (stats.size > 100 * 1024 * 1024) { throw new Error('DOCX file exceeds maximum size limit'); }
// Verify file extension. if (path.extname(filePath).toLowerCase() !== '.docx') { throw new Error('Invalid file format - only DOCX files allowed'); }
// Check the ZIP signature; this does not validate DOCX contents. const buffer = await fs.readFile(filePath); const isProbablyDOCX = buffer.slice(0, 2).toString() === 'PK'; // DOCX uses a ZIP container.
if (!isProbablyDOCX) { throw new Error('File does not appear to be a valid DOCX document'); }}Error handling and logging
- Comprehensive error handling — Implement detailed error catching for network issues, file corruption, and conversion failures
- Logging — Log conversion attempts, processing times, and errors for monitoring and debugging
- Graceful degradation — Provide fallback options when conversion fails
- User feedback — Return meaningful error messages to users
Performance optimization
- Queue systems — Use job queues (Redis, Bull) for high-volume DOCX-to-PDF conversion
- Resource limits — Set memory and CPU limits for conversion processes
- Caching — Cache frequently converted DOCX files to reduce processing load
- Load balancing — Distribute conversion tasks across multiple server instances
Scaling considerations
- Microservices architecture — Isolate DOCX conversion logic in dedicated services
- Container deployment — Use Docker containers for consistent deployment environments
- Monitoring — Implement health checks and performance monitoring
- Auto-scaling — Configure automatic scaling based on conversion queue length
Conclusion
Use the complete LibreOffice example when you can install and maintain its system dependencies. Use the Nutrient example when you need an SDK with its own Office conversion engine. In either case, compare fonts, tables, images, and page breaks against your source documents. Start a free trial to evaluate Nutrient with your own files.
Related reading
- How to convert Word to PDF using JavaScript — The same conversion in the browser rather than on a server
- How to convert PDF to Word — The reverse conversion, including layout and formatting caveats
- How to convert Excel to PDF in Node.js — The same Node.js approach applied to spreadsheets
FAQ
libreoffice-convert is a Node.js library that uses LibreOffice for DOCX-to-PDF conversion. It provides a simple API to convert DOCX documents to PDF by reading the input file and using LibreOffice’s conversion engine to process and output high-quality PDFs.
To convert DOCX documents to PDF with libreoffice-convert:
- Install LibreOffice on the host, initialize a Node.js project, and install the
libreoffice-convertpackage. - Create a script that imports the required modules, reads the DOCX document, and converts it to PDF using
promisify(libre.convert). - Implement error handling and file validation for robust DOCX-to-PDF conversion.
- Save the converted PDF to your desired location.
Nutrient Node.js SDK converts DOCX files using its own engine, without Microsoft Office or LibreOffice. It also provides document editing and custom font options. Validate the output with your application’s documents and fonts.
To convert DOCX documents to PDF with Nutrient Node.js SDK:
- Initialize a Node.js project and install the
@nutrient-sdk/nodepackage. - Create a script that loads the DOCX document using Nutrient’s API and exports it as a PDF.
- Configure licensing for production use to remove watermarks from converted PDFs.
- Execute the script to perform high-quality DOCX-to-PDF conversion and save the resulting file.
Nutrient includes its conversion engine and offers commercial support. The libreoffice-convert package starts a separately installed LibreOffice process. Both require output checks and resource management; custom fonts must be provided to the SDK or installed on the LibreOffice host.
DOCX stores document data in an XML-based ZIP package; DOC is an older binary format. These examples use DOCX. Check your converter’s supported file types before processing DOC files; renaming .doc to .docx doesn’t convert the format.
Set input limits based on measured memory use and conversion time. Queue jobs, limit concurrency, and isolate workers so one conversion can’t exhaust the application’s resources. These examples use buffers, so they don’t stream the conversion itself.