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

For modern HTML, CSS and JavaScript, the most direct C# route is Microsoft Playwright with Chromium: load or construct the page, wait until it is ready, then call Page.PdfAsync. It renders using print CSS by default, so choose your print styles and PDF options deliberately. This guide shows a working pattern, explains deployment and common failure points, and compares alternatives for Windows desktop and library-oriented projects.

Generate a PDF from HTML with Playwright .NET

Playwright is a good default when the document depends on browser layout, modern CSS or JavaScript. Its .NET API exposes PDF generation directly on a page. The browser binaries are a separate deployment requirement: installing the NuGet package alone does not install Chromium.

Install the package and browser

In the project directory, add the Playwright package:

dotnet add package Microsoft.Playwright

Follow the official Playwright .NET library setup to build and run its generated browser-install script for your project. Do this in each deployment environment that needs to launch Chromium, or provide the browser installation through your deployment process. A machine with the package but without the corresponding browser binaries cannot launch the browser.

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

Runnable minimal example

This top-level C# example creates a small HTML document and writes an A4 PDF to the current working directory:

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();

await page.SetContentAsync("""
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body { font-family: sans-serif; margin: 24px; }
    h1 { color: #17324d; }
    @page { size: A4; margin: 18mm; }
  </style>
</head>
<body>
  <h1>Invoice</h1>
  <p>HTML rendered by Chromium and saved as PDF.</p>
</body>
</html>
""");

await page.PdfAsync(new PagePdfOptions
{
    Path = "invoice.pdf",
    Format = "A4",
    PrintBackground = true,
    PreferCSSPageSize = true
});

await browser.CloseAsync();

The raw string literal syntax shown requires C# 11 or later. For an older language version, pass an ordinary escaped string to SetContentAsync. The Path is resolved relative to the process working directory; use an absolute path if the output location must be unambiguous.

Render an existing URL or application page

For a page served by your application, navigate to its URL instead of calling SetContentAsync. Wait for an application-specific ready condition when content is populated asynchronously; a successful navigation does not necessarily mean that client-side rendering, images or fonts are finished.

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();

await page.GotoAsync("https://example.com/invoice/123");
await page.Locator("[data-pdf-ready='true']").WaitForAsync();

await page.PdfAsync(new PagePdfOptions
{
    Path = "invoice-123.pdf",
    Format = "A4",
    PrintBackground = true,
    PreferCSSPageSize = true
});

Replace the example URL and selector with values from your application. If there is no reliable ready marker, add one to the page when its data and layout are ready. Ensure the rendering process can reach all required stylesheets, fonts and images; inaccessible assets can make the PDF differ from the page you expected. The Page API documents PdfAsync and its options.

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

Choose print styles and page settings deliberately

PDF generation is not simply a screenshot saved with a different extension. Playwright’s PDF operation uses print CSS media by default. That means print-specific rules can change visibility, colors, layout and pagination compared with what a visitor sees on screen.

  • Screen styling: If the document must use screen media rules, call EmulateMediaAsync with screen media before generating the PDF. Otherwise, design and test the print stylesheet that the default PDF behavior uses.
  • Backgrounds: Set PrintBackground = true when background colors or images are meaningful to the document. Without it, those backgrounds may be omitted from the output.
  • Paper size: Set Format for a named paper format such as A4, or use the supported width and height options when a custom size is needed. Coordinate this with CSS @page rules.
  • CSS page size: PreferCSSPageSize = true gives CSS-defined page size priority. Use it when your stylesheet owns the paper dimensions; otherwise set the size through the PDF options.
  • Scale and page ranges: Scale changes the rendered sizing; PageRanges can restrict output to selected pages. Check the resulting pagination after changing either.
  • Headers and footers: The API supports header and footer templates. Their scripts are not evaluated, and page styles are not visible inside these templates, so do not rely on application JavaScript or your page’s CSS to populate or style them.

These options are documented in Playwright’s Page API. For a repeatable invoice or report, keep the HTML, print CSS and PDF options under version control and validate the output after changes to any of them.

Or skip the browser setup

If the job is capturing a live website rather than converting your own C#-generated HTML, ScreenshotNeo offers a website screenshot API and MCP server. Its API also supports PDF output, but the example below is the documented one-call screenshot request; it is not a C# HTML-to-PDF replacement or a PDF-specific request example.

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 API options. Before capture, it can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups and chat widgets; these steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.

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

Sign up for ScreenshotNeo’s free plan to try 1,000 screenshots a month with no card.

Alternatives: choose by application and rendering needs

Approach Best fit Trade-offs to evaluate
Playwright .NET with Chromium Modern HTML, CSS and JavaScript; browser-rendered output Browser deployment, startup and memory, CSS and JavaScript fidelity, print options
WebView2 Windows desktop applications already hosting Edge Windows scope, embedded runtime management, print settings and desktop integration
wkhtmltopdf Existing command-line pipelines and simpler HTML Separate process packaging, Qt WebKit rendering behavior, CSS and JavaScript coverage
iText pdfHTML Library-oriented reports and invoices or structured PDF workflows HTML/CSS support, PDF structure and accessibility needs, licensing and server deployment

WebView2 for an existing Windows desktop app

Microsoft documents PrintToPdf as silently printing the current top-level document to a PDF file with custom print settings in .NET/C#. It is a natural candidate when your Windows application already embeds Edge through WebView2, but it is not the same deployment model as a cross-platform Playwright browser process. See Microsoft’s WebView2 print-to-PDF guide.

wkhtmltopdf for established command-line workflows

wkhtmltopdf describes itself as an open-source LGPL command-line tool that renders HTML to PDF and image formats using Qt WebKit. It may suit an existing CLI pipeline, but its rendering engine and operational model differ from Chromium. Validate your own page’s CSS and JavaScript rather than assuming modern browser output will match.

iText pdfHTML for library-based document generation

iText pdfHTML is an add-on for converting HTML and CSS to PDF, with C#/.NET examples and report or invoice use cases. Its .NET repository includes a simple HTML-to-PDF example at github.com/itext/itext-dotnet. Review licensing and deployment requirements for your project before selecting it.

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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting PDF output

  • Chromium will not launch: Confirm that the Playwright browser-install step from the official setup has run in the environment executing the code. Installing Microsoft.Playwright does not by itself guarantee the browser binaries are present.
  • The PDF is missing recent page content: Navigation may have completed before the application finished rendering. Wait for a stable application selector or other explicit ready condition before calling PdfAsync.
  • Images, fonts or styles are missing: Check that the browser process can access the asset URLs and that the page references valid resources. The rendering process must be able to load the page’s stylesheets, images and fonts.
  • The PDF looks different from the screen: Print media is the default for PDF generation. Adjust print CSS, or explicitly emulate screen media if screen rules are required.
  • Colors or backgrounds disappear: Set PrintBackground = true when those elements should print, then inspect the rendered PDF.
  • Page size or breaks are wrong: Align Format or dimensions with CSS @page rules and decide whether PreferCSSPageSize should make CSS authoritative. Test long documents as well as a single page.
  • Header or footer styling does not apply: Templates do not inherit page styles, and scripts in them are not evaluated. Provide the template content and styling in the way supported by the PDF API.
  • The file is written somewhere unexpected: Path may be relative to the process working directory. Use an absolute path or verify the working directory and output permissions.

Performance, reliability and cost

There is no universal conversion speed or memory figure for this workload: document size, assets, JavaScript, browser startup and deployment environment all affect it. Measure with representative pages in the environment where the service will run. If generating many documents, test the lifecycle and concurrency model you plan to deploy, and make sure each PDF is produced only after its page is ready. Do not infer production capacity from a minimal example.

Playwright .NET and Chromium require browser installation and introduce a browser process into deployment. WebView2 depends on a Windows desktop/Edge embedding context; wkhtmltopdf runs as a separate CLI tool; iText pdfHTML is a library add-on with licensing and server deployment considerations. The cited product documentation does not establish comparable pricing or benchmark results across these choices, so evaluate commercial terms and operational cost for your own deployment rather than treating them as equivalent.

Frequently asked questions

Does Playwright create a PDF from an HTML string as well as a URL?

Yes. The example uses SetContentAsync for an HTML string; a URL-based page can instead be loaded with GotoAsync.

Can a PDF use screen CSS instead of print CSS?

Yes. Emulate screen media before calling PdfAsync when the output should use screen styles. Print media is the default.

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

Can I generate only selected pages?

The Page PDF options include PageRanges. Consult the API documentation for the supported option syntax and confirm the page numbering against the final rendered document.

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.