Requirements

EggPdf targets netstandard2.0 through net10.0, so it works with any modern .NET project:

  • .NET 6, 7, 8, 9, or 10
  • .NET Framework 4.6.1+ (via netstandard2.0)
  • No additional system libraries, fonts, or browser runtimes required
ℹ️
EggPdf ships with built-in font metrics and does not require system fonts to be installed. Custom fonts can be loaded from bytes or file paths.

Installation

Add EggPdf to your project using the .NET CLI:

dotnet add package EggPdf

Or via the NuGet Package Manager in Visual Studio — search for EggPdf. You can also add it directly to your .csproj:

YourProject.csproj
<PackageReference Include="EggPdf" Version="2.0.8" />

Your First PDF

The entire public API is one static method: HtmlToPdf.RenderAsync. It accepts an HTML string and returns a byte[] containing the PDF document.

Program.cs
using EggPdf;

var html = """
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        h1   { color: #2563eb; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { padding: 8px 12px; border: 1px solid #e2e8f0; }
        th { background: #f8fafc; font-weight: 600; }
      </style>
    </head>
    <body>
      <h1>Invoice #1001</h1>
      <table>
        <thead><tr><th>Item</th><th>Qty</th><th>Price</th></tr></thead>
        <tbody>
          <tr><td>Widget A</td><td>3</td><td>$9.99</td></tr>
          <tr><td>Widget B</td><td>1</td><td>$24.99</td></tr>
        </tbody>
      </table>
    </body>
    </html>
    """;

var pdf = await HtmlToPdf.RenderAsync(html);
await File.WriteAllBytesAsync("invoice.pdf", pdf);

Console.WriteLine($"PDF written: {pdf.Length:N0} bytes");

Render Options

Page size, margins, orientation, and running headers/footers are all set with regular CSS: @page for size/margin, and @page margin boxes such as @bottom-center (with counter(page)/counter(pages) for page numbers) for content that repeats in the margins of every page. See Page Layout and Headers & Footers for the full reference.

Program.cs
using EggPdf;

var html = """
    <html><head><style>
      @page {
        size: A4; margin: 40px 50px;
        @bottom-center { content: "Page " counter(page) " of " counter(pages); }
      }
    </style></head>
    <body><h1>My Document</h1></body></html>
    """;

var pdf = await HtmlToPdf.RenderAsync(html);

Prefer C# properties for the page size/margins? Pass a PdfRenderOptions instead — it's translated into the equivalent @page rule internally:

var pdf = await HtmlToPdf.RenderAsync(html, new PdfRenderOptions
{
    PageSize = "Letter",
    MarginTop = 40, MarginBottom = 40,
    Title = "My Document",
});

ASP.NET Core Integration

Call EggPdf directly from a controller action to serve a PDF, no DI registration required for plain HTML rendering.

InvoiceController.cs
using EggPdf;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
    [HttpGet("{id}")]
    public async Task<IActionResult> GetPdf(int id)
    {
        var html = await BuildInvoiceHtmlAsync(id);
        var pdf = await HtmlToPdf.RenderAsync(html);

        return File(pdf, "application/pdf", $"invoice-{id}.pdf");
    }
}

Or install the EggPdf.AspNetCore package for a ready-made PdfResult action result: return new PdfResult(html, $"invoice-{id}.pdf");

Minimal API (ASP.NET Core 6+)

Program.cs
using EggPdf;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/pdf", async (RenderRequest req) =>
{
    var pdf = await HtmlToPdf.RenderAsync(req.Html);
    return Results.File(pdf, "application/pdf");
});

app.Run();

record RenderRequest(string Html);

Next Steps