ScreenshotNeo

BlogHow-to

Installing Playwright with C#

Install Playwright in a C# test or console project, download matching browsers, configure CI and Docker, and fix common setup errors.

By the ScreenshotNeo team1 October 20267 min read

Short answer: add the Playwright NuGet package that matches your project, build the project, then run the generated playwright.ps1 install script. The script downloads browser binaries for the exact Playwright version in your project. For NUnit, MSTest, xUnit, and xUnit v3, use the matching framework package; for a console app or custom infrastructure, use Microsoft.Playwright.

Choose the right package

Project type NuGet package Use it when
NUnit tests Microsoft.Playwright.NUnit You want Playwright’s NUnit base classes and fixtures.
MSTest tests Microsoft.Playwright.MSTest You want the MSTest integration.
xUnit tests Microsoft.Playwright.Xunit You use the xUnit integration.
xUnit v3 tests Microsoft.Playwright.Xunit.v3 Your project uses xUnit v3.
Console app or custom test framework Microsoft.Playwright You manage browser and test infrastructure yourself.

Use the current Playwright .NET installation guide and system-requirements page when selecting a .NET runtime or operating system because supported versions can change.

Install Playwright in a test project

1. Create a project

dotnet new nunit -n PlaywrightTests
cd PlaywrightTests

For another supported runner, use one of these templates:

dotnet new mstest -n PlaywrightTests
dotnet new xunit -n PlaywrightTests
dotnet new xunit3 -n PlaywrightTests

2. Add the matching package

dotnet add package Microsoft.Playwright.NUnit

Replace the package name for MSTest, xUnit, or xUnit v3:

dotnet add package Microsoft.Playwright.MSTest
dotnet add package Microsoft.Playwright.Xunit
dotnet add package Microsoft.Playwright.Xunit.v3

3. Build before installing browsers

dotnet build

Building generates the Playwright PowerShell script inside the build output. The directory includes your actual target framework, such as net8.0. Do not assume that name if your project targets another framework.

4. Download browser binaries

pwsh bin/Debug/net8.0/playwright.ps1 install

Replace net8.0 with the target-framework directory produced by your build. This installs the default supported browser engines. Install one engine only when you do not need all of them:

pwsh bin/Debug/net8.0/playwright.ps1 install chromium
pwsh bin/Debug/net8.0/playwright.ps1 install firefox
pwsh bin/Debug/net8.0/playwright.ps1 install webkit

5. Run the tests

dotnet test

Install Playwright as a C# library

Use the base package for a console program, a scraper, or custom test infrastructure.

dotnet new console -n BrowserAutomation
cd BrowserAutomation
dotnet add package Microsoft.Playwright
dotnet build
pwsh bin/Debug/net8.0/playwright.ps1 install

A minimal runnable program looks like this:

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
    Headless = true
});

var page = await browser.NewPageAsync();
await page.GotoAsync("https://example.com");
Console.WriteLine(await page.TitleAsync());
await page.ScreenshotAsync(new PageScreenshotOptions
{
    Path = "example.png",
    FullPage = true
});

Run it with dotnet run. The generated script belongs to the built project, so run dotnet build again after changing the target framework or updating the package.

Browser installation details

Playwright packages target specific browser revisions. Installing or updating the NuGet package can therefore require another browser installation. Keep the package and downloaded browsers in sync.

Linux dependencies

Linux machines may need operating-system libraries in addition to the browser binaries. The browser guide documents both separate dependency installation and a combined command:

pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps

You can also install dependencies separately with the generated script’s install-deps command. Follow the current browser and system-dependency guidance for your distribution and architecture.

Browser cache location

Playwright stores browser binaries in an operating-system-specific cache by default. Set PLAYWRIGHT_BROWSERS_PATH to place them elsewhere, which is useful for shared CI caches or controlled build images.

PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers \
pwsh bin/Debug/net8.0/playwright.ps1 install

The browser tooling also supports listing installed revisions, uninstalling browsers, and removing stale versions. Use those commands when a machine has accumulated binaries from several package versions.

Proxies and custom certificates

Restricted networks can block browser downloads. Configure the documented HTTPS_PROXY, custom download host, or custom certificate authority settings before running the install script. A proxy that works for NuGet does not necessarily work for Playwright’s browser host.

Continuous integration

Build first, install browsers and Linux dependencies, then run the tests. A typical Linux CI sequence is:

dotnet restore
dotnet build --configuration Release
pwsh bin/Release/net8.0/playwright.ps1 install --with-deps
dotnet test --configuration Release

Use the framework and output directory produced by your project. Cache the browser directory only when the cache key includes the Playwright package version; otherwise an older revision can be restored after a package update.

  • Pin the .NET SDK and operating-system image used by CI.
  • Run the browser installation step in every clean worker, or restore a versioned browser cache.
  • Prefer --with-deps on Linux workers that do not already contain the required libraries.
  • Keep headed execution out of minimal CI images unless you also provide a display server.

See the official Playwright .NET CI guide for runner-specific examples.

Docker setup

If you use the official Playwright container, match its version with the Playwright package in your project. A package and image mismatch can leave the expected browser executable unavailable.

dotnet add package Microsoft.Playwright --version <matching-version>

Pin the container tag to the same Playwright release rather than using an unpinned latest tag. The Docker documentation explains the compatibility requirement and image options.

Useful runtime choices

Headless versus headed

await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
    Headless = false
});

Headless mode is the normal choice for CI. Headed mode helps diagnose selectors and page behavior locally but requires a graphical environment.

Choose a browser explicitly

await using var browser = await playwright.Firefox.LaunchAsync();

Install the engine you launch. Installing Chromium does not make Firefox or WebKit available.

Use a deterministic browser context

var context = await browser.NewContextAsync(new BrowserNewContextOptions
{
    ViewportSize = new ViewportSize { Width = 1440, Height = 900 },
    Locale = "en-US",
    TimezoneId = "UTC"
});
var page = await context.NewPageAsync();

Set viewport, locale, timezone, and other context values explicitly when screenshots or tests must be repeatable.

Common errors and fixes

Error or symptom Cause Fix
playwright.ps1 is missing The project was not built, or the framework directory is wrong. Run dotnet build, inspect bin/Debug or bin/Release, and use the generated target-framework folder.
pwsh is not found or reports TypeNotFound PowerShell is unavailable or outdated. Install or update PowerShell. The .NET guide gives dotnet tool update --global PowerShell as one option.
Browser executable does not exist after a package update The package now expects a different browser revision. Run the generated script’s install command again using the updated project output.
Linux launch fails with missing shared libraries Operating-system dependencies are absent. Run install-deps or install --with-deps on a supported Linux image.
Browser download times out or is blocked Proxy, certificate, firewall, or download-host restrictions. Configure HTTPS_PROXY, the approved download host, or the required CA certificate.
Docker cannot find a browser The container image and NuGet package versions do not match. Pin both to compatible Playwright versions.
Tests pass locally but fail in CI Different browser revisions, OS libraries, environment variables, or target frameworks. Print the build output path, install browsers in CI, use --with-deps on Linux, and pin versions and cache keys.

Performance, reliability, and cost notes

  • Browser installation is separate from package restore. Cache the browser directory in CI, keyed by the Playwright version.
  • Reuse a browser process when running many tests, while creating isolated contexts for test data and cookies.
  • Use one browser engine when cross-browser coverage is unnecessary; it reduces download and startup work.
  • Make waits explicit and prefer locator-based readiness checks over arbitrary long delays.
  • Keep screenshots and traces as CI artifacts only when needed; large artifacts increase storage and transfer time.
  • For a self-managed setup, browser downloads, CI minutes, and maintenance are your costs. A hosted screenshot API can remove that browser setup when you only need rendered images or PDFs.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. Send one GET request to receive a PNG, JPEG, WebP, or PDF. It removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response includes X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

See the ScreenshotNeo API documentation for all options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every plan includes the feature set. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Do I install Playwright globally?

No. Add the NuGet package to each project and use that project’s generated script so the browser revision matches the package.

Which package should a console application use?

Use Microsoft.Playwright. The NUnit, MSTest, xUnit, and xUnit v3 packages are for their corresponding test integrations.

Can I install only Chromium?

Yes. Pass chromium to the generated install script. Install Firefox or WebKit separately if your code launches them.

Why does updating NuGet sometimes break launches?

The updated package may target a new browser revision. Re-run the generated browser installation command after upgrading.

Is Playwright suitable for taking one-off website screenshots?

Yes, but you must maintain the .NET runtime, browser binaries, OS dependencies, and CI environment. A hosted API such as ScreenshotNeo is simpler when you do not need direct browser control.