Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use HtmlRenderer.PdfSharp to turn an HTML string into a PDFsharp document, then save it with pdf.Save("document.pdf"). The smallest working path is PdfGenerator.GeneratePdf(html, PageSize.A4). Install the NuGet package, choose a page configuration that matches your template, generate the document, and inspect pagination, fonts, images and page breaks before putting the result into production.

Install HtmlRenderer.PdfSharp

At the time of writing, NuGet lists HtmlRenderer.PdfSharp 1.6.1. Its package metadata lists .NET Standard 2.0 and .NET 8.0 targets, and records an update date of July 29, 2026. Package metadata and compatibility targets can change, so check the package listing when you create or update a project.

From a directory containing your .NET project, run:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
dotnet add package HtmlRenderer.PdfSharp --version 1.6.1

Alternatively, add the reference to the project file:

<PackageReference Include="HtmlRenderer.PdfSharp" Version="1.6.1" />

Let NuGet resolve a coherent dependency graph. The current PdfSharp project source references PDFsharp 6.2.4. Avoid copying an old blog post’s manually pinned PDFsharp version into a current project: an historical issue reported incompatibility between an older HtmlRenderer build and PDFsharp 6.x, while the later migration work is marked complete.

Minimal HTML-to-PDF example

Create a console application, install the package, and replace its entry point with this code:

using PdfSharp;
using PdfSharp.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;

class Program
{
    private static void Main(string[] args)
    {
        string html = "<p><h1>Hello World</h1>This is html rendered text</p>";

        PdfDocument pdf = PdfGenerator.GeneratePdf(html, PageSize.A4);
        pdf.Save("document.pdf");
    }
}

Run the project with dotnet run. The call returns a PdfDocument; Save writes the bytes to the specified path. Use an absolute path or create the destination directory yourself when the process may run from a service, container or scheduled task, because the working directory might not be the directory you expect.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The example follows the package’s documented quick-start shape. Resolve the package version first and keep the using directives and API types that your project actually exposes; this article does not claim to have compiled the snippet against every target framework.

Build a maintainable HTML template

Keep the document self-contained while you prototype

Start with a small representative template rather than a whole production site. Put the styles required for the test in a <style> element, use ordinary HTML elements, and include the images that the real document needs. Generate a PDF and check line wrapping, image resolution, page breaks and font fallback before adding more markup.

Use CSS that matches the renderer’s stated scope

The project describes managed C# rendering with extensive HTML 4.01 and CSS level 2 support, separate stylesheets, malformed-HTML handling and PDF output from HTML snippets. That description is not a promise of full modern-browser equivalence. The roadmap lists expanded HTML parsing and CSS support as future work, so test any contemporary layout, advanced CSS, web font or browser-only behavior with your actual template.

Decide how assets are supplied

Templates often depend on stylesheets, images and fonts. HtmlRenderer.PdfSharp exposes stylesheet and image load event handlers, parsed CSS data support, and custom-font-directory registration. Use those hooks when the default resource resolution is not appropriate, and verify that every required asset is available in the process’s deployment environment. Do not assume that a browser-only URL, a remote font or a JavaScript-generated image will render identically.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set page size, orientation and margins

The two-argument overload is useful for a quick A4 document. For invoices, reports or landscape tables, use a PdfGenerateConfig object so the page geometry is explicit:

using PdfSharp;
using PdfSharp.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;

class Program
{
    static void Main()
    {
        const string html = @"
<html>
  <head>
    <style>
      body { font-family: Arial; font-size: 11pt; }
      h1 { margin: 0 0 12pt 0; }
      table { width: 100%; border-collapse: collapse; }
      th, td { border: 0.5pt solid #999; padding: 5pt; }
    </style>
  </head>
  <body>
    <h1>Monthly report</h1>
    <table>
      <tr><th>Item</th><th>Amount</th></tr>
      <tr><td>Example</td><td>100</td></tr>
    </table>
  </body>
</html>";

        var config = new PdfGenerateConfig
        {
            PageSize = PageSize.A4,
            MarginTop = 36,
            MarginRight = 36,
            MarginBottom = 36,
            MarginLeft = 36
        };

        PdfDocument pdf = PdfGenerator.GeneratePdf(html, config);
        pdf.Save("monthly-report.pdf");
    }
}

Margins are points in PDFsharp’s measurement system. Choose values that leave enough printable space for headers, footers and long words. The configuration API also exposes orientation; set it when a wide table should be landscape rather than forcing content to wrap into unreadable columns. The exact property names and available enum members should be confirmed against the resolved package version in your IDE.

There is also a page-size overload that accepts a margin argument. Use it for a simple, uniform margin; use PdfGenerateConfig when you need separate margins, orientation or other generation settings.

Stylesheets, images and fonts

CSS data and stylesheet loading

PdfGenerator accepts optional parsed CSS data and stylesheet-load handling. This lets an application provide CSS separately from the HTML or control how a referenced stylesheet is resolved. Keep the CSS used for a PDF close to the template and test it as a unit: a stylesheet that depends on browser defaults or unsupported selectors can change pagination without producing an obvious exception.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Image loading

An image-load handler is available for cases where an image needs custom resolution. Use it to supply the bytes or a stream from your application rather than relying on a URL that is unavailable in production. Test large images for memory use and inspect the generated PDF for sharpness and unexpected scaling.

Custom fonts

The library exposes RegisterCustomFontDirectory. Register the directory containing the fonts before generation when the template depends on a typeface that is not available through the normal environment. Deploy the font files with the application and verify licensing separately. Always open the resulting PDF on a machine that does not have your development fonts installed; that reveals fallback that might otherwise be missed.

Append generated pages to an existing document

Besides returning a new document, the API exposes AddPdfPages for appending pages generated from HTML to an existing PdfDocument. This is useful when a workflow combines a cover page, prebuilt PDF pages and an HTML-rendered section. Treat page numbering, bookmarks and resource collisions as integration concerns and inspect the combined file, not just the HTML portion.

Understand rendering limits before production

  • It is not a browser engine. The project’s stated support is centered on HTML 4.01 and CSS level 2, not every current HTML or CSS feature.
  • JavaScript is not a dependable layout step. If your page requires client-side code to create the content, generate that content in C# first or use a rendering system designed to run a browser.
  • External resources need a deployment plan. Network access, relative paths, authentication and custom fonts can behave differently on a developer workstation and in a service.
  • Pagination must be tested with real data. A short sample can hide orphaned headings, split rows, clipped images and unexpected blank pages.

The safest acceptance test contains the longest headings, the largest table, missing optional fields, multiple images, non-ASCII text and the fonts used by production. Compare page count and visual output after every package or template change.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot common failures

The namespace or type cannot be found

Confirm that the project restored HtmlRenderer.PdfSharp, that the target framework is supported by the resolved package, and that the source includes using TheArtOfDev.HtmlRenderer.PdfSharp; plus the PDFsharp namespaces. Clean and restore after changing package references. Do not solve the error by adding an unrelated, older PDFsharp package.

The PDF is blank or missing part of the page

Reduce the HTML to a heading and paragraph, then add sections back one at a time. Check malformed nesting, unsupported CSS and assets that cannot be resolved in the running environment. If the content is produced by JavaScript in a browser, produce the final HTML before calling the renderer.

Images do not appear

Use a path or resource that the process can actually read, and provide an image-load handler when the default resolver cannot reach the asset. Verify file permissions, relative-path assumptions and the image format. A successful PDF call does not prove that every referenced image was loaded.

Fonts look different

Register the required font directory before generation, deploy the files with the application and check the PDF on a clean machine. If a font is unavailable or unsupported, the renderer may fall back to another typeface and alter line breaks.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Pages break in the wrong places

Inspect margins, explicit spacing and table widths first. Replace a complex layout with a minimal reproduction to identify the HTML or CSS construct that triggers the break. Keep a regression document containing the problematic case so a package upgrade can be evaluated consistently.

An old sample fails after a package upgrade

Review the resolved dependency graph and the current package documentation. Historical HtmlRenderer/PDFsharp 6 compatibility reports referred to older builds; they should not be generalized to 1.6.1. Use matching current packages rather than forcing an old transitive dependency.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability and operational choices

Control input size

Generate only the HTML needed for the document. Very large tables and high-resolution images increase memory pressure, so process large jobs in a controlled worker and dispose the returned PdfDocument when your application is finished with it. Measure your own templates; no reliable speed or throughput figure is established here.

Make output deterministic

Pin the package version in the project, keep templates and CSS under source control, and run a representative PDF regression set after upgrades. Store generated files using unique names when multiple requests can run concurrently, and write to a location for which the service account has permission.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Protect untrusted HTML

Do not pass arbitrary user HTML to a process with unrestricted access to local files or internal services. Sanitize input and constrain resource loading according to your application’s security model. Treat images, stylesheets and font files as inputs that require the same review as the HTML itself.

When a different renderer is a better fit

Choose alternatives by testing the exact HTML/CSS features your templates require, pagination and layout controls, image and font behavior, .NET target and deployment requirements, and licensing. There is no justified apples-to-apples benchmark here, so a “best” alternative cannot be named without your documents and constraints. If browser-level fidelity, JavaScript execution or modern CSS is non-negotiable, evaluate a browser-based or commercial .NET renderer against a representative test suite instead of assuming HtmlRenderer.PdfSharp will match a browser.

Or skip the browser setup

If your input is a public URL and you need a clean capture or PDF workflow without maintaining browser automation, ScreenshotNeo provides a website screenshot API and MCP server. A single request can capture a URL; its cleanup step accepts consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets, with each step switchable. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing status in headers.

For an image capture, the documented cURL form is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for PDF options, full-page captures, element selectors, custom CSS and JavaScript, click and wait actions, blocked requests, headers and cookies, device and viewport settings, geolocation, timezone, resizing, caching, signed links, asynchronous jobs, bulk capture and usage reporting. The service also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Equivalent Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Equivalent Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account when this URL-based workflow fits your project.

Recommended implementation checklist

  1. Install the current HtmlRenderer.PdfSharp package version and let NuGet resolve compatible PDFsharp dependencies.
  2. Generate a minimal HTML string with PdfGenerator.GeneratePdf and save the returned PdfDocument.
  3. Choose page size, orientation and margins with PdfGenerateConfig when defaults are insufficient.
  4. Provide CSS, stylesheet and image handling, and register custom fonts where the template requires them.
  5. Test real content for pagination, images, fonts, malformed markup and unsupported browser-oriented features.
  6. Run the same representative documents after every package, runtime or template change.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.