Get started

How to convert Word to PDF

Convert DOCX to PDF for free using Microsoft Word, LibreOffice CLI, Python, Node.js, or Google Docs API. Includes batch conversion and formatting fixes.

benoitded9 min read

Converting a Word document (.docx) to PDF produces a fixed-layout file that looks the same on every device and cannot be accidentally edited. This guide covers five methods: Microsoft Word's built-in export, LibreOffice headless CLI, Python automation, Node.js automation, and the Google Docs API.

How to convert Word to PDF in Microsoft Word

Microsoft Word has a built-in PDF export that preserves fonts, images, hyperlinks, and the table of contents as clickable PDF links.

Windows:

  1. Open the .docx file in Word.
  2. Click File, then Save As.
  3. Choose PDF from the file type dropdown.
  4. Select "Standard (publishing online and printing)" for full quality, or "Minimum size" for a smaller file.
  5. Click Save.

macOS:

  1. Open the .docx file in Word.
  2. Click File, then Export to PDF (or Save As and pick PDF).
  3. Choose a location and click Export.

Word's export produces the most faithful PDF because it uses the same rendering engine that displays the document on screen. If your document uses custom fonts, Word embeds them automatically. This is the best option for one-off conversions when you have a Word license.

How to convert Word to PDF with LibreOffice (free, no license)

LibreOffice is a free, open-source office suite that reads .docx files and exports PDF from the command line without a GUI. It runs on Linux, macOS, and Windows.

Install LibreOffice

# macOS
brew install --cask libreoffice
 
# Ubuntu / Debian
sudo apt install libreoffice
 
# Windows (winget)
winget install LibreOffice

Convert a single file

libreoffice --headless --convert-to pdf document.docx

The --headless flag runs LibreOffice without opening a window. The output file document.pdf appears in the current directory.

Convert all .docx files in a directory

libreoffice --headless --convert-to pdf *.docx

Specify an output directory

libreoffice --headless --convert-to pdf --outdir ./pdfs *.docx

LibreOffice processes each file sequentially. On a 2024 MacBook Pro (M3), a 10-page document with images converts in about 2 seconds. A 200-page report takes 8 to 12 seconds.

LibreOffice substitutes missing fonts with metrically similar alternatives. If your .docx uses a commercial font like Calibri or Cambria, install the Microsoft core fonts on Linux to avoid layout shifts. On macOS and Windows, these fonts are typically already present.

How to convert Word to PDF in Python

Python has two practical approaches: the docx2pdf library for simple conversions, and subprocess with LibreOffice for server environments.

Using docx2pdf

docx2pdf wraps Microsoft Word on Windows and macOS (via COM automation and AppleScript), and falls back to LibreOffice on Linux.

pip install docx2pdf
import docx2pdf
 
# Single file
docx2pdf.convert("invoice.docx", "invoice.pdf")
 
# All .docx files in a directory
docx2pdf.convert("./documents/", "./pdfs/")

On Windows and macOS, docx2pdf produces output identical to Word's own export because it calls Word directly. On Linux, it calls LibreOffice under the hood.

Using subprocess with LibreOffice

For servers where installing Word is not an option, call LibreOffice directly:

import subprocess
from pathlib import Path
 
def docx_to_pdf(input_path: str, output_dir: str = ".") -> str:
    """Convert a .docx file to PDF using LibreOffice."""
    subprocess.run(
        ["libreoffice", "--headless", "--convert-to", "pdf",
         "--outdir", output_dir, input_path],
        check=True,
        timeout=60,
    )
    stem = Path(input_path).stem
    return str(Path(output_dir) / f"{stem}.pdf")
 
pdf_path = docx_to_pdf("report.docx", "./output")
print(f"Saved: {pdf_path}")

Batch convert a directory

from pathlib import Path
import subprocess
 
input_dir = Path("./documents")
output_dir = Path("./pdfs")
output_dir.mkdir(exist_ok=True)
 
docx_files = list(input_dir.glob("*.docx"))
 
for docx in docx_files:
    subprocess.run(
        ["libreoffice", "--headless", "--convert-to", "pdf",
         "--outdir", str(output_dir), str(docx)],
        check=True,
        timeout=120,
    )
 
print(f"Converted {len(docx_files)} files")

LibreOffice does not support concurrent conversions from the same installation directory. If you need parallel processing, use separate --user-install profiles or run conversions sequentially.

How to convert Word to PDF in Node.js

The libreoffice-convert npm package wraps the LibreOffice CLI and returns a Buffer.

npm install libreoffice-convert
import { readFileSync, writeFileSync } from "fs";
import { convert } from "libreoffice-convert";
import { promisify } from "util";
 
const convertAsync = promisify(convert);
 
async function docxToPdf(inputPath: string, outputPath: string) {
  const input = readFileSync(inputPath);
  const pdf = await convertAsync(input, ".pdf", undefined);
  writeFileSync(outputPath, pdf);
  console.log(`Saved: ${outputPath}`);
}
 
docxToPdf("contract.docx", "contract.pdf");

This requires LibreOffice installed on the system. The library spawns a LibreOffice process per conversion, so it is best suited for low-volume or batch workloads rather than high-throughput API endpoints.

Batch conversion in Node.js

import { readdirSync } from "fs";
import path from "path";
 
const inputDir = "./documents";
const outputDir = "./pdfs";
 
const files = readdirSync(inputDir).filter((f) => f.endsWith(".docx"));
 
for (const file of files) {
  await docxToPdf(
    path.join(inputDir, file),
    path.join(outputDir, file.replace(".docx", ".pdf"))
  );
}
 
console.log(`Converted ${files.length} files`);

How to convert Word to PDF with Google Docs API

The Google Docs API can import a .docx file to Google Docs format, then export it as PDF. This approach works without any local software but requires a Google Cloud project with the Drive API enabled.

from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
import io
 
creds = Credentials.from_service_account_file(
    "service-account.json",
    scopes=["https://www.googleapis.com/auth/drive"],
)
drive = build("drive", "v3", credentials=creds)
 
# Upload .docx and convert to Google Docs format
file_metadata = {
    "name": "report",
    "mimeType": "application/vnd.google-apps.document",
}
media = MediaFileUpload("report.docx", mimetype=(
    "application/vnd.openxmlformats-officedocument"
    ".wordprocessingml.document"
))
uploaded = drive.files().create(
    body=file_metadata, media_body=media, fields="id"
).execute()
 
# Export as PDF
request = drive.files().export_media(
    fileId=uploaded["id"], mimeType="application/pdf"
)
buffer = io.BytesIO()
downloader = MediaIoBaseDownload(buffer, request)
done = False
while not done:
    _, done = downloader.next_chunk()
 
with open("report.pdf", "wb") as f:
    f.write(buffer.getvalue())
 
# Clean up the temporary Google Docs file
drive.files().delete(fileId=uploaded["id"]).execute()
print("Saved: report.pdf")

Google Docs handles most .docx formatting correctly, but complex features like SmartArt, embedded macros, and certain chart types may not convert.

Comparison: which method to use?

MethodRequires Word licenseRuns headlessFont fidelityBatch supportBest for
Microsoft WordYesNoExactNo (manual)One-off, highest fidelity
LibreOffice CLINoYesHigh (with fonts installed)YesServers, CI/CD, batch
Python (docx2pdf)Windows/macOS: yes; Linux: noYesDepends on backendYesScripts, mixed environments
Python (subprocess)NoYesHigh (with fonts installed)YesLinux servers
Node.js (libreoffice-convert)NoYesHigh (with fonts installed)YesNode.js backends
Google Docs APINoYes (cloud)GoodYes (with quota)No local install, cloud-first

For production systems that need the highest fidelity without a Word license, LibreOffice with the correct fonts installed is the standard choice. Microsoft Word's own export produces the most accurate PDF but requires a license and a GUI session (or COM automation on Windows).

Common formatting issues and fixes

Fonts shift or change. The number one cause of layout differences between the .docx and the PDF is missing fonts. LibreOffice and Google Docs substitute missing fonts with alternatives that have different character widths, which shifts line breaks and page breaks. Fix: install the exact fonts from the .docx on the conversion machine. On Linux, install ttf-mscorefonts-installer for Calibri, Cambria, and other Microsoft fonts.

Table columns resize. Complex tables with merged cells or auto-fit columns sometimes render with different column widths in LibreOffice. Fix: set explicit column widths in the Word document instead of relying on auto-fit. Alternatively, convert with Word on Windows via docx2pdf for exact table rendering.

Headers and footers misalign. Word and LibreOffice handle header/footer margins slightly differently. A header that sits 10mm from the top edge in Word may sit at 11mm in LibreOffice. Fix: use consistent margin values in the Word document's page setup, and verify the PDF output.

Embedded charts render differently. Word charts use the Office charting engine, which LibreOffice does not replicate exactly. Colors, axis labels, and legend positioning may shift. Fix: export charts as images in the Word document before converting, or accept minor visual differences.

File size is too large. Word documents with high-resolution images produce large PDFs. After conversion, run the PDF through the PDF4.dev compress tool to reduce the file size without visible quality loss. A typical 15 MB PDF with photos compresses to 2 to 4 MB.

When to use HTML-to-PDF instead of Word-to-PDF

Word-to-PDF conversion works well for documents authored by humans in Word. But for documents generated programmatically (invoices, receipts, reports, certificates), starting from a Word template and filling it with data is fragile. Font substitution, table resizing, and margin drift compound when you generate hundreds of documents per day.

PDF4.dev takes a different approach: you write an HTML template with CSS for pixel-exact layout, inject data via Handlebars variables, and render the PDF with a headless browser. The output is identical every time because the rendering engine (Chromium) is the same one that displays the template in the browser.

const response = await fetch("https://api.pdf4.dev/v1/render", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PDF4_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    template_id: "monthly-report",
    data: {
      company: "Acme Corp",
      month: "March 2026",
      revenue: "$142,000",
      expenses: "$98,500",
    },
  }),
});
 
const pdf = await response.arrayBuffer();

This produces a PDF with exact fonts, exact spacing, and zero conversion artifacts. For programmatic document generation at scale, HTML-to-PDF with PDF4.dev is more reliable than converting .docx files.

Try the free HTML to PDF toolTry it free

Summary

  • For one-off conversions with a Word license, use Word's built-in File, Save As PDF. It produces the most faithful output.
  • For free conversions without Word, install LibreOffice and run libreoffice --headless --convert-to pdf document.docx.
  • For Python automation, use docx2pdf (wraps Word on Windows/macOS, LibreOffice on Linux) or call LibreOffice via subprocess.
  • For Node.js, use the libreoffice-convert npm package, which wraps LibreOffice CLI.
  • For cloud-only workflows, use the Google Docs API to upload and export as PDF.
  • Install the exact fonts from your .docx files on the conversion machine to avoid layout shifts.
  • For documents you generate programmatically, skip Word entirely: use PDF4.dev to render PDFs directly from HTML templates with exact control over fonts, layout, and data.

Free tools mentioned:

Html To PdfTry it freeCompress PdfTry it freeMerge PdfTry it freeProtect PdfTry it freeWatermark PdfTry it free

Start generating PDFs

Build PDF templates with a visual editor. Render them via API from any language in ~300ms.