ScreenshotRender
← Back to blog
Tutorials

How to Screenshot a Website in C#: 3 Ways

Robert Belt·9 min read
Updated On :
Orange minimalist illustration of C# code turning a URL into a screenshot

C# can automate almost anything, but it cannot open a browser on its own, and a screenshot needs a browser. By the end of this you'll know the three ways to screenshot a website in C#, which one survives production, and how to do it in a single HTTP call with no Chromium anywhere near your server.

The three are Selenium (the WebDriver stack many .NET teams already have from testing), headless Chrome through Playwright for .NET or PuppeteerSharp (a real browser you launch and maintain yourself), and a single HTTP call to a screenshot API with no browser on your server at all. They run from most to least infrastructure, and each one fits a different job.

How do you take a screenshot of a website in C#?

The shortest path to a screenshot of a website in C# is one HTTP request to a screenshot API: send a URL, get back a hosted image, with no browser to install on your host. With ScreenshotRender the whole capture is one line: https://screenshotrender.com/api/v1/screenshot?apiKey=YOUR_API_KEY&url=https://dotnet.microsoft.com&fullPage=true. Call that from any C# HTTP client and the JSON response carries a hosted image URL at data.screenshot.

If you'd rather keep the rendering on your own machine, the Selenium and headless Chrome routes below stay local, at the cost of running and patching a browser yourself. The rest of this post shows all three, so you can pick by how much infrastructure you want to own.

Why is taking a screenshot in C# different from Node or Python?

Taking a screenshot in C# is different because the .NET ecosystem leans on ports and bindings of browser tools that were born in JavaScript, rather than a native one. Puppeteer is a Node library; the C# version, PuppeteerSharp, is a community port that mirrors its API. Playwright is the exception: Microsoft ships Playwright for .NET as a first-class library, which is why it tends to be the cleanest local option in 2026.

That leaves three shapes of solution. You can drive a full WebDriver browser with Selenium, which most teams already pulled in for end-to-end tests. You can launch headless Chrome directly through Playwright or PuppeteerSharp. Or you can hand the whole job to a remote service and just read back an image URL. The first two put a browser binary, a driver, and the patching that comes with them onto whatever runs your code, which is the constraint every method below works around.

How do you screenshot a website in C# with Selenium?

You screenshot a website in C# with Selenium by casting the driver to ITakesScreenshot and saving the result, after you've installed the Selenium.WebDriver package and a matching browser driver. With the page loaded, the capture is one chain: ((ITakesScreenshot)driver).GetScreenshot().SaveAsFile("dotnet.png");.

What just happened is that Selenium drove a real Chrome through WebDriver, took the browser's screenshot command, and wrote a PNG to disk. Because it is a real browser, modern JavaScript pages render correctly. The catch is that Selenium is a test-automation stack, not a screenshot tool, so you carry the whole WebDriver dependency for one method. There is a sharper limit too: in Chrome, GetScreenshot returns the visible viewport, not the full scrollable page. Full page in Selenium means dropping to the Chrome DevTools Protocol or switching to one of the libraries below.

How do you capture a screenshot with headless Chrome in C#?

You capture a screenshot with headless Chrome in C# by launching Chromium through Playwright for .NET or PuppeteerSharp and calling its screenshot method. With Playwright the capture is one call after the page loads: await page.ScreenshotAsync(new PageScreenshotOptions { Path = "dotnet.png", FullPage = true });, reached through Playwright.CreateAsync, Chromium.LaunchAsync, and page.GotoAsync(url).

PuppeteerSharp gets there the same way for anyone coming from Node. You pull a browser down once with await new BrowserFetcher().DownloadAsync();, launch it with Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });, then capture with await page.ScreenshotAsync("dotnet.png", new ScreenshotOptions { FullPage = true });. Both render modern pages correctly, both do full page in a single option, and if you're weighing the two engines our Puppeteer vs Playwright comparison breaks down where each one wins.

The cost is everything around that one call. You ship a Chromium binary with your .NET app, download it again in CI, give each concurrent capture enough memory, install the fonts the page expects, and absorb the version drift that turns a green deploy red after an unrelated upgrade. Chrome's own headless mode docs spell out the launch flags, but they don't pay your memory bill. On a box you fully control that is workable. Inside a slim container or a serverless function with a tight size limit, bundling a browser is frequently a non-starter.

Don't ship a browser with your .NET app.

Playwright and PuppeteerSharp mean a Chromium binary in your build, a CI download, and memory to babysit. ScreenshotRender renders the page for you and returns a hosted image, with cookie banners and ads already stripped. 100 free screenshots a month, no credit card.

Try a render

How do you screenshot a website in C# with a screenshot API?

You screenshot a website in C# with a screenshot API by sending the URL to one HTTP endpoint and reading the image URL out of the JSON response, with no browser on your server. The full request is one copy-pasteable line: https://screenshotrender.com/api/v1/screenshot?apiKey=YOUR_API_KEY&url=https://dotnet.microsoft.com&fullPage=true.

From C# you fire that with the built-in HttpClient in a couple of lines: var res = await http.GetStringAsync(endpoint); then parse the body and read doc.RootElement.GetProperty("data").GetProperty("screenshot") with System.Text.Json. There is no SDK to install, so the same call works from a console app, an ASP.NET service, or an Azure Function without adding a dependency.

The parameters are the whole surface. url is the page to capture, fullPage=true grabs the entire scrollable document instead of the default 1280 by 720 viewport, wait takes a delay in seconds for pages that finish rendering after the initial load, and timeout caps how long a slow page can take. The response also carries the page title, description, and favicon, which is handy if you are building a link preview card.

The other thing you stop doing yourself is cleanup. Cookie consent banners, ad overlays, and chat widgets are removed automatically before every capture, on every plan including the free one, so the image is the page rather than the page plus three popups. Repeat captures of the same URL and options are served from an edge cache, so a dashboard that re-renders the same thumbnails does not pay for them twice.

When does C# website screenshot capture fail?

C# website screenshot capture fails in a few predictable ways, and the cause is rarely the C# code itself.

  • Bot protection. A vanilla headless browser gets served a challenge page on bot-protected sites, so the capture is the challenge, not the site. ScreenshotRender ships Stealth Mode on the Hobby plan and above; our guide to screenshotting Cloudflare-protected sites covers what changes.
  • Lazy loading and JS timing. Content that loads after the first paint, like images that appear on scroll or a view that swaps in late, is missing if you capture too early. A short wait lets the page settle before the shot.
  • Login walls. A URL-only API takes a URL, not a session cookie, so it cannot reach a page behind a sign-in. That is the one case where driving the browser yourself wins, because you can script the login first.
  • Driver and version drift. Selenium needs a driver that matches the installed browser, and a background Chrome update breaks that pairing without warning. Moving the render off your host removes the whole class of problem, since nothing browser-shaped runs on your side.

Most failures are timing, access, or version mismatch, not the capture itself. Match the fix to the cause and the image comes back clean.

Common questions about taking screenshots in C#

How do I take a full page screenshot in C#?

Capture the whole scrollable document instead of the visible viewport. With Playwright for .NET you set FullPage = true on PageScreenshotOptions, and with PuppeteerSharp you set the same flag on ScreenshotOptions. With a screenshot API you add fullPage=true to the request. Selenium's GetScreenshot grabs only the viewport in Chrome, so for full page you drop to the DevTools Protocol or switch libraries. The mechanics of the scroll-and-stitch are in our guide to screenshotting an entire webpage.

Can I take a screenshot with Playwright in C#?

Yes. Playwright for .NET is a first-class Microsoft library, not a port. You create a browser with Playwright.CreateAsync, open a page, call GotoAsync with the URL, then call ScreenshotAsync with a PageScreenshotOptions that sets the file Path and FullPage. It drives a real Chromium, so JavaScript runs and fonts load before the capture.

Does Selenium capture full page screenshots in C#?

Not by default. In Chrome, Selenium's GetScreenshot returns the visible viewport, not the full scrollable page. Full page in Selenium means calling the Chrome DevTools Protocol Page.captureScreenshot with captureBeyondViewport, or switching to Playwright, PuppeteerSharp, or a screenshot API that does full page in one option.

How do I screenshot a JavaScript-heavy page in C#?

Use a real browser. Playwright for .NET and PuppeteerSharp both run Chromium, so React, Vue, and Svelte pages render correctly rather than blank. Add a short wait so lazy-loaded images and late JavaScript content land before the capture. A screenshot API runs the same Chromium for you and takes a wait in seconds for the same reason.

Do I need to install Chrome to take screenshots in C#?

Only for the local routes. Selenium needs a browser and a matching driver, Playwright downloads browsers with its install step, and PuppeteerSharp pulls Chromium down through BrowserFetcher. A screenshot API needs no browser on your host at all, since the rendering happens on the service, which is exactly why it works inside slim containers and serverless functions.

The honest takeaway: match the method to the runtime. If your team already runs Selenium for tests, reusing it for a quick viewport shot is the least to add. For full control over a real browser and proper full page output, Playwright for .NET or PuppeteerSharp gives you Chromium and the bill that comes with it. And to turn any public URL into a clean image without putting a browser on your .NET host at all, the single HTTP call is the least to maintain.

Keep reading