The library
Nullean.Cdp talks the DevTools Protocol to Chrome over one web socket. It has no dependencies beyond the BCL and is
native AOT and trim clean.
await using var browser = await Browser.LaunchAsync(new BrowserLaunchOptions
{
Headless = true,
ExecutablePath = null,
Arguments = ["--lang=nl"],
StartTimeout = TimeSpan.FromSeconds(30),
});
Console.WriteLine(await browser.VersionAsync());
- the default
- or a Chrome to use instead of the one found
- added to the launch switches
- Launching uses a temporary profile and
--remote-debugging-port=0, and reads the port Chrome chose from the profile, so no port is guessed. Background pages run at full speed, and headless scrollbars are hidden so pages lay out alike on every OS. If Chrome exits or never opens its port,BrowserLaunchExceptioncarries its last output. - Disposing closes Chrome, kills what is left after five seconds, and deletes the profile. A process that exits normally closes every Chrome it launched; the next launch cleans up after one that was killed. See Chrome.
- Connecting to a Chrome that is already running:
Browser.ConnectAsync(new Uri("ws://127.0.0.1:9222/devtools/browser/…")).
await using var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync("http://localhost:5000/");
- its own cookies, storage and cache
- waits for this document's load event
Contexts are isolated from each other, so tests share one browser and still run in parallel. Disposing a context closes its pages. Downloads are denied in every context.
| Page | |
|---|---|
GotoAsync, BackAsync, ForwardAsync, ReloadAsync |
navigate, waiting for load |
WaitForUrlAsync(glob), WaitForLoadStateAsync(state) |
|
SetViewportAsync, SetDeviceAsync, SetColorSchemeAsync, SetGeolocationAsync, SetOfflineAsync, SetExtraHeadersAsync |
emulation |
PressAsync(keys), ScrollAsync(dx, dy), Mouse, Keyboard |
input not tied to an element |
UrlAsync, TitleAsync, EvaluateAsync(expression) |
|
ActionTimeout (5 s), NavigationTimeout (30 s) |
how long actions and navigations wait |
GuardNetworkAsync(allow) |
refuse requests the predicate does not allow; see safety |
page.SendAsync(method, parameters) sends any DevTools command in the page's session, and browser.Connection reaches
the browser itself. Parameters are written with a Utf8JsonWriter; results come back as JsonElement.
var metrics = await page.SendAsync("Page.getLayoutMetrics");
await page.SendAsync("Emulation.setCPUThrottlingRate", w => w.WriteNumber("rate", 4));