Meziantou.Framework.WebPlatform.Playwright
1.0.0
Prefix Reserved
dotnet add package Meziantou.Framework.WebPlatform.Playwright --version 1.0.0
NuGet\Install-Package Meziantou.Framework.WebPlatform.Playwright -Version 1.0.0
<PackageReference Include="Meziantou.Framework.WebPlatform.Playwright" Version="1.0.0" />
<PackageVersion Include="Meziantou.Framework.WebPlatform.Playwright" Version="1.0.0" />
<PackageReference Include="Meziantou.Framework.WebPlatform.Playwright" />
paket add Meziantou.Framework.WebPlatform.Playwright --version 1.0.0
#r "nuget: Meziantou.Framework.WebPlatform.Playwright, 1.0.0"
#:package Meziantou.Framework.WebPlatform.Playwright@1.0.0
#addin nuget:?package=Meziantou.Framework.WebPlatform.Playwright&version=1.0.0
#tool nuget:?package=Meziantou.Framework.WebPlatform.Playwright&version=1.0.0
Meziantou.Framework.WebPlatform.Playwright
A Playwright server whose browser is the managed browser engine of
Meziantou.Framework.WebPlatform. The Playwright clients (.NET, Node.js,
Python, Java) connect to it with BrowserType.ConnectAsync (browserType.connect() in Node.js), as to a server started with
npx playwright run-server, and automate its pages with the API of Playwright: navigation, locators, actions, assertions,
evaluation, screenshots, PDF, network interception, cookies and storage state, emulation, dialogs, popups and frames.
The pages run in the process of the server, without native browser: the documents are parsed, styled, laid out and painted by Meziantou.Framework.WebPlatform, their scripts run with Meziantou.Framework.WebPlatform.JavaScript, the screenshots are drawn by Meziantou.Framework.WebPlatform.Imaging, and the PDF are printed by Meziantou.Framework.WebPlatform.PdfRendering.
Examples
Start a server, and automate a page with the Playwright client for .NET (Microsoft.Playwright):
await using var server = new PlaywrightServer(); // no DocumentLoader: the pages use page.SetContentAsync() and the routes
await server.StartAsync();
using var playwright = await Microsoft.Playwright.Playwright.CreateAsync();
await using var browser = await playwright.Chromium.ConnectAsync(server.WsEndpoint.ToString());
var page = await browser.NewPageAsync();
await page.SetContentAsync("""
<label for=name>Name</label><input id=name>
<button onclick="document.querySelector('output').textContent = 'Hello ' + document.querySelector('input').value">Greet</button>
<output></output>
""");
await page.GetByLabel("Name").FillAsync("World");
await page.GetByRole(AriaRole.Button, new() { Name = "Greet" }).ClickAsync();
await Assertions.Expect(page.Locator("output")).ToHaveTextAsync("Hello World");
var screenshot = await page.ScreenshotAsync();
By default, nothing is fetched from the network: the pages can only use the content of page.SetContentAsync() and the
responses of the routes (page.RouteAsync()). Set PlaywrightServerOptions.DocumentLoader to let the pages load documents
and resources (see the document loader to
filter the requests):
await using var server = new PlaywrightServer(new PlaywrightServerOptions
{
DocumentLoader = DocumentLoader.Create(), // the pages can load any URL
});
await server.StartAsync();
using var playwright = await Microsoft.Playwright.Playwright.CreateAsync();
await using var browser = await playwright.Chromium.ConnectAsync(server.WsEndpoint.ToString());
var page = await browser.NewPageAsync();
await page.GotoAsync("https://example.com/");
await Assertions.Expect(page.GetByRole(AriaRole.Heading, new() { Level = 1 })).ToHaveTextAsync("Example Domain");
await page.ScreenshotAsync(new() { Path = "example.png", FullPage = true });
PlaywrightServer listens on its own TCP port (PlaywrightServerOptions.BindAddress, Port and Path). An application
can also give it the WebSockets it accepts, e.g. in ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
await using var server = new PlaywrightServer(new PlaywrightServerOptions { DocumentLoader = DocumentLoader.Create() });
app.UseWebSockets();
app.Map("/playwright", async context =>
{
// The protocol changes with each minor version of Playwright: the clients must use the version of the server
if (!context.WebSockets.IsWebSocketRequest || !PlaywrightServer.IsCompatibleClient(context.Request.Headers.UserAgent))
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
return;
}
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
await server.HandleConnectionAsync(webSocket, context.RequestAborted);
});
await app.RunAsync();
The Meziantou.Framework.WebPlatform.Playwright.Tool .NET tool runs a server from the command line.
Versions
The protocol of Playwright changes with each minor version: the clients must have the major and minor versions of
PlaywrightServer.PlaywrightVersion (1.64). As the Playwright server, the server rejects the other clients with an HTTP 428
response (see PlaywrightServerOptions.AllowAnyClientVersion).
How it works
Each connection gets a browser (the preLaunchedBrowser of the protocol), reported as chromium by default
(PlaywrightServerOptions.BrowserName). Each browser context runs its pages on its own thread, with its own script engine,
cookies and local storage; each page is a top-level BrowsingContext, and each frame a nested browsing context.
The selectors (getByRole(), getByText(), frameLocator()...), the actionability checks, the assertions (expect()) and
the aria snapshots are evaluated by the scripts of Playwright, injected in the pages as Playwright does (see
Scripts/README.md), so they behave as in the browsers. The rest of the logic of the Playwright server
(the auto-waiting and the retries, the clickable points and the hit target checks, the keyboard, the navigation lifecycle,
the network events and the routes) is ported to C#.
Limitations
- Engine. The pages are rendered by Meziantou.Framework.WebPlatform: see its limitations (no media decoding, no downloads...).
- Not supported: video recording, tracing (the traces are empty), HAR recording and replay, downloads, the workers and the
service workers of the protocol, the clock (
page.clock), the locator handlers (page.addLocatorHandler()),toMatchAriaSnapshot(), the WebSocket routes, CDP sessions, Android and Electron, the WebP screenshots, theany-frameselectors, and the files given by path tosetInputFiles()(give their content instead, asFilePayload). - Ignored: geolocation and permissions (there is no Geolocation API),
ignoreHTTPSErrorsandproxy(they are options of theDocumentLoader),bypassCSP, theanimations: "disabled"option of the screenshots. - Network. The requests of the pages go through
PlaywrightServerOptions.DocumentLoader: thedata:andblob:URLs are not reported to the clients, and the bodies of the responses are buffered. - Security. The scripts of the pages run in the process (see the
threat model of the script engine), and a client can make
the server request any URL the
DocumentLoaderallows: expose the server to trusted clients only (the defaultBindAddressis the loopback address).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. net11.0 is compatible. |
-
net10.0
- Meziantou.Framework.WebPlatform (>= 1.0.3)
- Meziantou.Framework.WebPlatform.Imaging (>= 1.0.2)
- Meziantou.Framework.WebPlatform.JavaScript (>= 1.0.3)
- Meziantou.Framework.WebPlatform.PdfRendering (>= 1.0.1)
-
net11.0
- Meziantou.Framework.WebPlatform (>= 1.0.3)
- Meziantou.Framework.WebPlatform.Imaging (>= 1.0.2)
- Meziantou.Framework.WebPlatform.JavaScript (>= 1.0.3)
- Meziantou.Framework.WebPlatform.PdfRendering (>= 1.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 59 | 10/25/2026 |