When you think of C# and web automation, your mind might first leap to Selenium. But what if I told you there's a headless browser automation tool with a slick, modern API, powered by the Chrome DevTools Protocol, and it's *blazingly fast*? Enter: PuppeteerSharp.
PuppeteerSharp is a .NET port of the Node.js-based Puppeteer library. In other words, it's a C#-friendly wrapper that lets you control headless (or headed) Chrome or Chromium browsers. Why would you want to use it? Well, PuppeteerSharp is ideal for: * Generating PDFs or screenshots of webpages * Crawling websites or extracting data * Automated testing of front-end code * Rendering JavaScript-heavy pages server-side (SSR) for SEO or previews * And any other scenario where you'd want to simulate a real browser Now imagine combining this power with the flexibility of an ASP.NET MVC application. Suddenly, your server-side app can moonlight as a front-end robot, churning out content with pixel-perfect rendering. Let's explore how to pull this off. Sometimes you just want to click a button and boom! — a PDF appears. This solution shows you how to trigger PuppeteerSharp to generate a PDF from a given URL right from your MVC controller. In this example, we'll integrate PuppeteerSharp into a controller action that renders a URL into a PDF and returns it as a file to the browser. * `BrowserFetcher().DownloadAsync(...)` ensures Chromium is downloaded. PuppeteerSharp doesn't come with Chromium out-of-the-box (probably to spare your SSD). * `LaunchAsync(...)` starts a new headless Chromium instance. * `NewPageAsync()` opens a new tab in the browser. * `GoToAsync(...)` navigates to the URL you want to render. * `PdfStreamAsync(...)` creates a PDF from the loaded page. * `File(...)` returns the PDF stream to the client browser as a downloadable file. Simple. Effective. Like having a personal PDF butler in your controller. Want to level up your architecture? This solution encapsulates PuppeteerSharp in a service class and registers it for dependency injection (DI). This is great for large apps where concerns need to be cleanly separated. * Promotes testability * Improves separation of concerns * Centralizes browser instance reuse (yay for performance!) In `Startup.cs` or wherever you configure DI: In your controller: * The service class encapsulates all Puppeteer logic. * `InitBrowserAsync()` downloads Chromium and launches a shared browser instance. * `GeneratePdfAsync()` navigates to a URL and returns the resulting PDF bytes. * In the controller, we inject and use the service just like any other dependency. The benefit? You don't need to re-launch the browser each time — great for scalability and speed. PDFs not your thing? Maybe you're more of a visual learner. Or maybe your app generates preview thumbnails of blog posts, reports, or memes. PuppeteerSharp has you covered. This example shows how to capture a screenshot of a page and return it as a PNG file. * `ScreenshotDataAsync(...)` is your golden ticket to PNG heaven. * The `FullPage = true` option ensures the entire webpage is captured — not just the visible viewport. * The file is returned to the client browser as an image. You could go fancier by setting viewport sizes or capturing only a specific DOM element. PuppeteerSharp is very flexible. * Chromium Download Size: PuppeteerSharp downloads Chromium (\~100MB) on first use. Consider packaging it with your app or pointing to a custom executable if deploying to multiple servers. * Headless = false: For debugging, launch with `Headless = false` and `Devtools = true`. Watching your automated browser do its thing is oddly satisfying. * Concurrency: Launching a new browser instance for every request is expensive. Reuse a singleton browser where possible. * Async/Await: All PuppeteerSharp methods are async. Your controller actions should be too. PuppeteerSharp unlocks powerful browser automation directly from your ASP.NET MVC app. Whether you're generating PDFs, screenshots, or scraping content from dynamic pages, it's a sharp tool (pun fully intended) that's production-ready and fun to work with. Whether you want quick-n-dirty PDF rendering or a clean, injectable service architecture, you've got options. Start small, play around, and before you know it, you'll be running a headless browser empire from your C# backend. Happy coding — may your PDFs be crisp and your DOMs forever loaded! Published on May 21, 2025 Tags: ASP.NET MVC and Web API Tutorial
| c#
| pdf
| puppeteersharp
Did you enjoy this article? If you did here are some more articles that I thought you will enjoy as they are very similar to the article
that you just finished reading.
No matter the programming language you're looking to learn, I've hopefully compiled an incredible set of tutorials for you to learn; whether you are beginner
or an expert, there is something for everyone to learn. Each topic I go in-depth and provide many examples throughout. I can't wait for you to dig in
and improve your skillset with any of the tutorials below.
What is PuppeteerSharp?
Option 1: Synchronous PDF Generation on Demand
What This Code Does
public async Task
Breakdown of the Code
Option 2: Background Rendering Service with Dependency Injection
Why Use a Service Class?
Step 1: Create a PuppeteerService
public interface IPuppeteerService
{
Task\
Step 2: Register and Use the Service
services.AddSingleton\
private readonly IPuppeteerService \_puppeteerService;
public HomeController(IPuppeteerService puppeteerService)
{
\_puppeteerService = puppeteerService;
}
public async Task
What's Happening Here?
Option 3: Screenshot Generation for Previews or Thumbnails
What This Code Does
public async Task
Explanation
Tips, Gotchas, and Miscellaneous Wizardry
Related Posts
Tutorials
Learn how to code in HTML, CSS, JavaScript, Python, Ruby, PHP, Java, C#, SQL, and more.