DOCX to PDF API
High-speed DOC/DOCX to PDF API with pixel-perfect accuracy. Enterprise security, advanced parameters, no MS Office required.
Converting Word documents to PDF is one of the most common file processing tasks in .NET applications. Whether you're building a document management system, generating reports, or automating workflows, you need a reliable way to handle DOCX to PDF conversion in C#.
In this guide, we'll walk through four different approaches - from free built-in options to cloud APIs - with working code examples, performance benchmarks, and guidance on which method fits your use case.
| Feature | Interop | Open XML + PdfSharp | ConvertAPI | Aspose.Words |
|---|---|---|---|---|
| Cost | Free (requires Office) | Free | Free tier + paid plans | ~$2,999+/year |
| Output quality | Excellent | Poor on complex docs | Excellent | Good |
| Server dependencies | Word installed | None | None | None |
| Cross-platform | Windows only | Yes | Yes | Yes |
| Async support | No | Manual | Built-in | Manual |
| Complex tables & charts | Yes | No | Yes | Yes |
| Font support | Requires install | None | Full library built-in | Manual config |
| Setup time | ~30 min | ~2 hours | ~5 min | ~15 min |
| Lines of code needed | ~30 | ~80+ | ~4 | ~8 |
This approach uses the Microsoft Word application itself to perform the conversion. It produces pixel-perfect results because Word is doing the rendering.
Install the Interop NuGet package:
Install-Package Microsoft.Office.Interop.Wordusing Microsoft.Office.Interop.Word;
using System;
using System.IO;
public class InteropConverter
{
public static void ConvertDocxToPdf(string inputPath, string outputPath)
{
Application word = null;
Document doc = null;
try
{
word = new Application { Visible = false };
doc = word.Documents.Open(Path.GetFullPath(inputPath));
doc.SaveAs2(
Path.GetFullPath(outputPath),
WdSaveFormat.wdFormatPDF
);
Console.WriteLine($"PDF saved to {outputPath}");
}
catch (Exception ex)
{
Console.WriteLine($"Conversion failed: {ex.Message}");
throw;
}
finally
{
doc?.Close(WdSaveOptions.wdDoNotSaveChanges);
word?.Quit();
// Release COM objects to avoid memory leaks
if (doc != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
if (word != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(word);
}
}
}This method is ideal if you're building a desktop application where Microsoft Word is already installed. The output quality is perfect because Word itself handles the rendering.
If you want a free, server-safe solution, you can read the DOCX file using the Open XML SDK and render it to PDF using a library like PdfSharp. This approach has no server dependencies.
Install-Package DocumentFormat.OpenXml
Install-Package PdfSharpCoreThis is a simplified example that extracts text content and writes it to a PDF. For full formatting support, you'll need to handle styles, tables, and images manually.
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using System.Linq;
using System.Text;
public class OpenXmlConverter
{
public static void ConvertDocxToPdf(string inputPath, string outputPath)
{
// Extract text from DOCX
string content = ExtractText(inputPath);
// Create PDF
var document = new PdfDocument();
var page = document.AddPage();
var gfx = XGraphics.FromPdfPage(page);
var font = new XFont("Arial", 12);
double yPosition = 40;
double margin = 40;
double maxWidth = page.Width - (margin * 2);
foreach (var line in content.Split('\n'))
{
if (yPosition > page.Height - margin)
{
page = document.AddPage();
gfx = XGraphics.FromPdfPage(page);
yPosition = margin;
}
gfx.DrawString(
line,
font,
XBrushes.Black,
new XRect(margin, yPosition, maxWidth, 20),
XStringFormats.TopLeft
);
yPosition += 20;
}
document.Save(outputPath);
}
private static string ExtractText(string filePath)
{
var sb = new StringBuilder();
using (var doc = WordprocessingDocument.Open(filePath, false))
{
var body = doc.MainDocumentPart?.Document?.Body;
if (body == null) return string.Empty;
foreach (var paragraph in body.Elements<Paragraph>())
{
var text = paragraph
.Elements<Run>()
.SelectMany(r => r.Elements<Text>())
.Select(t => t.Text);
sb.AppendLine(string.Join("", text));
}
}
return sb.ToString();
}
}Good for simple, text-only documents where you need a completely free, cross-platform solution. If your documents are basically plain text with minimal formatting, this can work.
ConvertAPI offloads conversion to a dedicated cloud service that uses the actual Word rendering engine. This means you get pixel-perfect output with zero server dependencies - no Office installation, no heavy libraries, no platform restrictions.
Step 1: Create a free account at convertapi.com - you get free conversion seconds to test with, no credit card required.
Step 2: Copy your API secret key from the dashboard.
Step 3: Install the NuGet package:
Install-Package ConvertApi
That's it. You're ready to convert.
using ConvertApiDotNet;
var convertApi = new ConvertApi("YOUR_SECRET_KEY");
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(inputPath)
);
await result.SaveFilesAsync(outputPath);
Compare that to 30+ lines for Interop or 80+ lines for Open XML. Less code means fewer bugs and faster time to production.
Convert an entire folder of documents concurrently:
using ConvertApiDotNet;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
public class BatchConverter
{
private static readonly ConvertApi convertApi = new ConvertApi("YOUR_SECRET_KEY");
public static async Task ConvertFolder(string inputFolder, string outputFolder)
{
Directory.CreateDirectory(outputFolder);
var docxFiles = Directory.GetFiles(inputFolder, "*.docx");
Console.WriteLine($"Converting {docxFiles.Length} files...");
var tasks = docxFiles.Select(async file =>
{
var outputPath = Path.Combine(
outputFolder,
Path.GetFileNameWithoutExtension(file) + ".pdf"
);
try
{
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(file)
);
await result.SaveFilesAsync(outputPath);
Console.WriteLine($" ✓ {Path.GetFileName(file)}");
}
catch (ConvertApiException ex)
{
Console.WriteLine($" ✗ {Path.GetFileName(file)}: {ex.Message}");
}
});
await Task.WhenAll(tasks);
Console.WriteLine("Batch conversion complete.");
}
}
Unlike Interop, this handles concurrent conversions without COM threading issues. Each conversion runs independently.
Skip the download step entirely and convert documents directly from a URL:
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(new Uri("https://example.com/report.docx"))
);
await result.SaveFilesAsync("report.pdf");
This is particularly useful when documents are stored in S3, Azure Blob Storage, or any cloud storage - you pass the URL and ConvertAPI handles the rest.
Here's how to add DOCX to PDF conversion to an ASP.NET Core API endpoint:
using ConvertApiDotNet;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ConvertController : ControllerBase
{
private readonly ConvertApi _convertApi;
public ConvertController()
{
_convertApi = new ConvertApi("YOUR_SECRET_KEY");
}
[HttpPost("docx-to-pdf")]
public async Task<IActionResult> ConvertDocxToPdf(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded.");
// Save uploaded file to temp location
var tempInput = Path.GetTempFileName();
var tempOutput = Path.ChangeExtension(tempInput, ".pdf");
try
{
using (var stream = new FileStream(tempInput, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var result = await _convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(tempInput)
);
await result.SaveFilesAsync(tempOutput);
var pdfBytes = await System.IO.File.ReadAllBytesAsync(tempOutput);
return File(pdfBytes, "application/pdf", "converted.pdf");
}
finally
{
if (System.IO.File.Exists(tempInput)) System.IO.File.Delete(tempInput);
if (System.IO.File.Exists(tempOutput)) System.IO.File.Delete(tempOutput);
}
}
}Fine-tune the PDF output with conversion parameters:
// Convert specific pages only
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(inputPath),
new ConvertApiParam("PageRange", "1-5")
);
// Landscape orientation with high DPI
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(inputPath),
new ConvertApiParam("PageOrientation", "landscape"),
new ConvertApiParam("PdfResolution", "300")
);
// Password-protected DOCX
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(inputPath),
new ConvertApiParam("Password", "document-password")
);
// PDF/A output for archival compliance
var result = await convertApi.ConvertAsync("docx", "pdfa",
new ConvertApiFileParam(inputPath)
);One of the biggest frustrations with DOCX to PDF conversion is discovering that your solution breaks on real-world documents. Here's what ConvertAPI handles automatically:
Complex tables and merged cells - Nested tables, cells spanning multiple rows/columns, and tables with mixed content render correctly because ConvertAPI uses the actual Word rendering engine.
Embedded fonts and typography - If the document uses custom fonts, ConvertAPI has access to a comprehensive font library. No more fallback font surprises in production.
Headers, footers, and page numbers - These render exactly as they appear in Word, including different first-page headers and odd/even page layouts.
Charts and SmartArt - Embedded Excel charts, SmartArt diagrams, and other OLE objects convert with full fidelity.
Track changes and comments - You can choose to render the document with or without tracked changes visible.
ConvertAPI is the best fit for web applications, microservices, serverless functions, and any server-side scenario where you need reliable, high-quality conversion without managing dependencies. It's also the fastest way to get from zero to working conversion in production - most developers have it running in under 10 minutes.
Aspose.Words is a commercial .NET library that handles DOCX to PDF conversion entirely on-premise with high fidelity.
Install-Package Aspose.Wordsusing Aspose.Words;
public class AsposeConverter
{
public static void ConvertDocxToPdf(string inputPath, string outputPath)
{
var doc = new Document(inputPath);
var saveOptions = new Aspose.Words.Saving.PdfSaveOptions
{
Compliance = Aspose.Words.Saving.PdfCompliance.PdfA1a,
EmbedFullFonts = true,
OptimizeOutput = true
};
doc.Save(outputPath, saveOptions);
}
}Decent for enterprise environments where regulatory requirements prevent data from leaving your network and budget isn't a constraint.
We tested all four methods on a set of 10 real-world documents (a mix of invoices, reports with tables, documents with images, and multi-page contracts). Here's what we found:
| Metric | Interop | Open XML + PdfSharp | ConvertAPI | Aspose |
|---|---|---|---|---|
| Avg. time per file | 3.2s | 0.8s | 1.4s | 1.1s |
| Handles complex tables | Yes | No | Yes | Yes |
| Handles embedded images | Yes | No | Yes | Yes |
| Handles headers/footers | Yes | No | Yes | Yes |
| Concurrent conversions | Crashes | Yes | Yes | Yes |
| Memory usage (10 files) | ~800MB | ~120MB | ~15MB | ~350MB |
Key takeaways: Open XML is fast but produces broken output on anything beyond simple text. Interop is accurate but resource-hungry and can't handle concurrency. ConvertAPI delivers Interop-level quality with minimal memory usage since the heavy processing happens server-side. Aspose is solid but comes with a steep price tag for comparable results.
Theory is one thing - let's see what actually happens when each method converts the same document. We created a stress-test DOCX file designed to expose common conversion failures: Windows-specific fonts (Aptos Display, Bahnschrift SemiCondensed, Segoe UI Variable), fixed-width tables that break when font metrics change, emoji/symbol characters, a transparent PNG with fine detail, and a landscape page with precise margin alignment.
Here's the original document open in Microsoft Word:


ConvertAPI produces a pixel-perfect conversion. All three pages render correctly: the fixed-width table keeps its column alignment, fonts match the original, emoji characters (☑ ⚠ 📌 📎) display properly, the transparent PNG retains its fine detail and translucent panels, and the landscape page preserves its two-column layout with text ending exactly where it should. Headers and footers are present on every page.
This is identical to what you'd get printing directly from Microsoft Word.


Aspose produces a recognizable conversion, but with noticeable differences. The title font weight renders differently than the original - "DOCX to PDF Renderer Failure Bait" appears bolder. Font metrics have shifted slightly, causing subtle changes in line breaks and spacing. The evaluation version also stamps every page with a red "Created with an evaluation copy of Aspose.Words" header and a large "ASPOSE - Your File Format APIs" watermark across the content area, making it impossible to properly evaluate output quality without purchasing a license.

This is where the free approach falls apart completely. The entire document - originally three formatted pages - collapses into a single page of plain text. Every table is gone. Every image is missing. Emoji characters render as empty squares (□). Text is clipped on the right edge because there's no proper margin or line-wrap handling. Headers, footers, and page numbers are absent. The landscape page doesn't exist. Bold and italic formatting is stripped. Font choices are ignored entirely.
This is the output you get when you "build your own renderer" with Open XML SDK - and it's why developers who start with this approach inevitably switch to a dedicated solution.
The gap between these outputs is not subtle. If your documents contain anything beyond plain paragraphs - tables, images, custom fonts, mixed page orientations - the choice matters enormously. ConvertAPI matches Word's own rendering because it uses the same engine. Aspose gets close but shows font differences and requires an expensive license just to test properly. Open XML produces output that would be unacceptable in any professional context.
Don't take our word for it. Download the stress-test document and each converter's output, or run the DOCX through your own tools:
The source document uses Windows-specific fonts (Aptos Display, Bahnschrift SemiCondensed, Segoe UI Variable), fixed-width tables, emoji characters, a transparent PNG with fine detail, and mixed page orientations. It's designed to expose exactly the kind of rendering failures you'll encounter in production.
This is the #1 cause of "it looked fine on my machine but wrong in production." If your documents use custom fonts that aren't installed on the server, the PDF will use fallback fonts and look different.
Interop requires the fonts installed on the server. Open XML has no font support at all. Aspose lets you specify font folders but uses its own rendering. ConvertAPI handles this automatically with its comprehensive server-side font library - you don't need to install anything.
Documents over 50MB can cause Interop to hang and Aspose to consume gigabytes of memory. ConvertAPI handles large files server-side, keeping your application's memory footprint minimal regardless of file size. This is especially important in containerized environments where memory limits are strict.
If your app processes multiple conversions simultaneously (e.g., a web app where multiple users upload documents at the same time), Interop will crash due to COM threading issues. ConvertAPI's async API handles this naturally - each conversion is an independent HTTP request.
Choose Microsoft Interop if you're building a Windows desktop app and Word is guaranteed to be installed. It's free and produces perfect output, but it's a dead end for anything server-side.
Choose Open XML + PdfSharp only if your documents are simple text with minimal formatting and you need a zero-cost, zero-dependency solution. Be prepared to rewrite this later when you encounter complex documents.
Choose ConvertAPI if you want the best balance of output quality, simplicity, and cost. It takes 5 minutes to set up, handles every edge case Word can throw at it, works on any platform, and scales from a side project to thousands of daily conversions. The free tier lets you test with your actual documents before committing.
Choose Aspose.Words if corporate policy mandates that no data leaves your network and you have budget for enterprise licensing.
For most developers and teams, ConvertAPI is the fastest path to reliable, production-ready conversion - without the maintenance burden of Interop, the limitations of Open XML, or the cost of Aspose.
Here's a full console application you can copy, paste, and run in under 2 minutes:
using ConvertApiDotNet;
using System;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Usage: DocxToPdf <input.docx> [output.pdf]");
return;
}
string inputPath = args[0];
string outputPath = args.Length > 1
? args[1]
: Path.ChangeExtension(inputPath, ".pdf");
if (!File.Exists(inputPath))
{
Console.WriteLine($"File not found: {inputPath}");
return;
}
try
{
// Get your free API Token at https://www.convertapi.com/a
var convertApi = new ConvertApi("YOUR_API_TOKEN");
Console.WriteLine($"Converting {Path.GetFileName(inputPath)}...");
var result = await convertApi.ConvertAsync("docx", "pdf",
new ConvertApiFileParam(inputPath)
);
await result.SaveFilesAsync(outputPath);
Console.WriteLine($"Done! PDF saved to {outputPath}");
}
catch (ConvertApiException ex)
{
Console.WriteLine($"Conversion error: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
}
}
}Yes. ConvertAPI, Aspose, and Open XML all work with .NET Core and .NET 6+. Microsoft Interop requires .NET Framework on Windows. If you're on modern .NET, ConvertAPI is the easiest option since there are no platform-specific dependencies.
Use ConvertAPI for the best quality without Office. It uses Word's rendering engine server-side, so you get the same output quality as Interop without installing anything locally. Aspose and Open XML also work without Office, but with trade-offs in cost and quality respectively.
ConvertAPI supports this with a simple Password parameter. Aspose supports it through the Document constructor. Interop supports it via the Open method's optional password parameter.
Yes. ConvertAPI supports PDF/A output by converting to the pdfa format type. Aspose.Words supports PDF/A through PdfSaveOptions. This is important for legal, medical, and government document archival.
Never use Microsoft Interop in web applications - Microsoft explicitly advises against this and it will crash under concurrent load. ConvertAPI is purpose-built for this scenario with async methods that integrate cleanly into ASP.NET Core controllers. See the ASP.NET Core code example above.
ConvertAPI works perfectly in containers since it's just HTTP calls - no system dependencies needed. Your Docker image stays small and clean. Interop doesn't work in containers at all, and Aspose adds significant image size.
ConvertAPI produces output identical to printing from Microsoft Word because it uses the same rendering engine. We've tested it with documents containing complex tables, embedded charts, custom fonts, RTL text, and mixed media - all render correctly.