Soenneker.Playwrights.Extensions.Stealth
11.0.191
Prefix Reserved
dotnet add package Soenneker.Playwrights.Extensions.Stealth --version 11.0.191
NuGet\Install-Package Soenneker.Playwrights.Extensions.Stealth -Version 11.0.191
<PackageReference Include="Soenneker.Playwrights.Extensions.Stealth" Version="11.0.191" />
<PackageVersion Include="Soenneker.Playwrights.Extensions.Stealth" Version="11.0.191" />
<PackageReference Include="Soenneker.Playwrights.Extensions.Stealth" />
paket add Soenneker.Playwrights.Extensions.Stealth --version 11.0.191
#r "nuget: Soenneker.Playwrights.Extensions.Stealth, 11.0.191"
#:package Soenneker.Playwrights.Extensions.Stealth@11.0.191
#addin nuget:?package=Soenneker.Playwrights.Extensions.Stealth&version=11.0.191
#tool nuget:?package=Soenneker.Playwrights.Extensions.Stealth&version=11.0.191
Soenneker.Playwrights.Extensions.Stealth
A .NET extension library for Microsoft Playwright that makes browser automation harder to detect. It applies launch-argument hardening, context shaping, and init-script evasions so Chromium sessions look more like normal user sessions.
Related Repos
You might also be interested in:
- soenneker.playwrights.crawler for crawling and mirroring sites to disk with Playwright.
- soenneker.playwrights.installation for ensuring Playwright browsers are installed before first use.
Installation
dotnet add package Soenneker.Playwrights.Extensions.Stealth
Quick start
- Launch Chromium with stealth defaults:
Playwright.LaunchStealthChromium(). - Create a stealth browser context:
browser.CreateStealthContext(). - Use the context as usual to create pages and run automation.
using Microsoft.Playwright;
using Soenneker.Playwrights.Extensions.Stealth;
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.LaunchStealthChromium(new BrowserTypeLaunchOptions
{
Headless = true,
Channel = "chromium"
});
var browserContext = await browser.CreateStealthContext();
var page = await browserContext.NewPageAsync();
Connecting to a remote Playwright sidecar
If Chromium is already running remotely, for example in a Docker sidecar, connect with the endpoint overload:
using Microsoft.Playwright;
using Soenneker.Playwrights.Extensions.Stealth;
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.LaunchStealthChromium(
"ws://playwright:3000/",
new BrowserTypeConnectOptions());
var context = await browser.CreateStealthContext();
var page = await context.NewPageAsync();
In endpoint mode, stealth launch arguments are not applied because the remote browser is already running. Stealth still applies at the browser-context level via CreateStealthContext().
With proxy
Pass an optional proxy into CreateStealthContext:
var context = await browser.CreateStealthContext(new Proxy
{
Server = "http://proxy.example.com:8080",
Username = "user",
Password = "secret"
});
Customizing launch and context
The defaults are recommended, but if you want to tune options further:
using Microsoft.Playwright;
using Soenneker.Playwrights.Extensions.Stealth;
using Soenneker.Playwrights.Extensions.Stealth.Options;
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.LaunchStealthChromium(
new BrowserTypeLaunchOptions { Headless = true },
new StealthLaunchOptions
{
Channel = "chrome",
IncludeNoSandboxArgument = false,
IgnoreDetectableDefaultArguments = true,
AdditionalIgnoredDefaultArguments = ["--disable-features=DialMediaRouteProvider"],
AdditionalArguments = ["--disable-features=Translate"]
});
var context = await browser.CreateStealthContext(
new BrowserNewContextOptions
{
// Optionally specify a UserAgent
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36"
},
new StealthContextOptions
{
NormalizeDocumentHeaders = true,
InjectClientHintHeaders = true,
WarmupSpeechVoices = true,
PatchFunctionToString = false,
EnableCdpDomainHardening = true,
DisableConsoleDomain = true,
DisableRuntimeDomain = false,
Surfaces = new StealthSurfaceOptions
{
NavigatorProfile = StealthSurfaceMode.Native,
NavigatorPlugins = StealthSurfaceMode.Native,
Screen = StealthSurfaceMode.Native,
Battery = StealthSurfaceMode.Native,
UserAgentData = StealthSurfaceMode.Native,
PermissionsQuery = StealthSurfaceMode.Native,
DocumentFonts = StealthSurfaceMode.Native,
Canvas = StealthSurfaceMode.Native,
MediaDevices = StealthSurfaceMode.Native
},
AdditionalHttpHeaders = new Dictionary<string, string>
{
["DNT"] = "1"
}
});
Applying stealth to an existing context
You can apply the same stealth behavior to a context you already created:
var context = await browser.NewContextAsync();
await context.ApplyStealthAsync();
Features
| Area | Description |
|---|---|
| Launch options | Normalizes Chromium args with stealth-oriented defaults: ensures --disable-blink-features=AutomationControlled, forces --headless=new when headless, and can strip detectable Playwright default args via IgnoreDefaultArgs. |
| Channel selection | If BrowserTypeLaunchOptions.Channel is unset, StealthLaunchOptions.Channel is used (default chromium). Set Channel = "chrome" (or pass BrowserTypeLaunchOptions.Channel) when you want the installed Google Chrome channel. |
| Hardware profile | Each context gets a random but internally consistent Windows/Chrome profile: CPU cores, memory, viewport, DPR, Chrome version, timezone, locale/languages, and WebGL identity. Randomized geolocation is available as an explicit opt-in. |
| Context shaping | Sets coherent User-Agent, language headers, timezone, viewport, DPR, and color scheme from the same generated profile. Generated Chromium User-Agents follow UA reduction (Chrome/<major>.0.0.0>), and a caller-supplied BrowserNewContextOptions.UserAgent is propagated into the derived Client Hints fields when header injection is enabled. Fingerprint surfaces such as navigator profile getters, plugins/mimeTypes, screen values, battery, navigator.userAgentData, navigator.permissions.query(), document.fonts, canvas, and media devices can each be left native, spoofed, or disabled. |
| Speech voices | The injected init script can warm up native speechSynthesis voices before page scripts run, reducing the chance that a site observes an empty or not-yet-populated voice list. |
| Request shaping | Registers early context routing so top-level document navigations get normalized navigation headers before the first page load. |
| CDP hardening (optional) | Can disable selected Chromium CDP domains (e.g. Console, optionally Runtime) per page to reduce protocol surface. |
| Init script | Injected before page load to reduce automation signals: hides navigator.webdriver; aligns navigator/screen/window (e.g. hardwareConcurrency, deviceMemory, platform, vendor, languages, plugins, dimensions, DPR); Client Hints and navigator.userAgentData; window.chrome; permissions/connection/battery/media/geolocation shims; timezone via Intl; canvas noise; WebGL vendor/renderer spoofing; WebRTC host-candidate stripping. |
Options reference
- StealthLaunchOptions — Controls how launch arguments are normalized (
Channel,RemoveDetectableArguments,IncludeNoSandboxArgument,IgnoreDetectableDefaultArguments,AdditionalArguments,AdditionalIgnoredDefaultArguments). - StealthContextOptions — Controls context and request behavior (
Proxy,AdditionalHttpHeaders,InjectClientHintHeaders,NormalizeDocumentHeaders,AlignColorScheme,RandomizeGeolocation,WarmupSpeechVoices,PatchFunctionToString,Surfaces,EnableCdpDomainHardening,DisableConsoleDomain,DisableRuntimeDomain). - StealthSurfaceOptions — Controls per-surface behavior with
StealthSurfaceMode(Native,Spoofed,Disabled) forNavigatorProfile,NavigatorPlugins,Screen,Battery,UserAgentData,PermissionsQuery,DocumentFonts,Canvas,MediaDevices, andWebGl.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net11.0 is compatible. |
-
net11.0
- Microsoft.Playwright (>= 1.64.1)
- Soenneker.Asyncs.Semaphores (>= 11.0.36)
- Soenneker.Extensions.String (>= 4.0.800)
- Soenneker.Extensions.Task (>= 11.0.141)
- Soenneker.Extensions.ValueTask (>= 4.0.133)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Soenneker.Playwrights.Extensions.Stealth:
| Package | Downloads |
|---|---|
|
Soenneker.Cloudflare.Downloader
Allows for navigating and downloading from Cloudflare sites in under-attack mode |
|
|
Soenneker.Playwrights.Crawler
A configurable Playwright crawler with rich stealth and control options. |
|
|
Soenneker.Firmware.SeaPilot
Seagate firmware discovery and downloads using OpenSeaChest and stealth browser automation. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 11.0.191 | 152 | 10/26/2026 |
| 11.0.190 | 91 | 10/26/2026 |
| 11.0.189 | 45 | 10/26/2026 |
| 11.0.188 | 91 | 10/26/2026 |
| 4.0.187 | 795 | 10/23/2026 |
| 4.0.186 | 174 | 10/22/2026 |
| 4.0.185 | 138 | 10/21/2026 |
| 4.0.184 | 305 | 10/18/2026 |
| 4.0.182 | 644 | 10/15/2026 |
| 4.0.181 | 88 | 10/15/2026 |
| 4.0.180 | 117 | 10/14/2026 |
| 4.0.179 | 106 | 10/14/2026 |
| 4.0.177 | 244 | 10/14/2026 |
| 4.0.176 | 135 | 10/14/2026 |
| 4.0.175 | 89 | 10/14/2026 |
| 4.0.168 | 192 | 10/13/2026 |
| 4.0.167 | 93 | 10/13/2026 |
| 4.0.164 | 351 | 10/12/2026 |
| 4.0.163 | 96 | 10/12/2026 |
| 4.0.162 | 205 | 10/12/2026 |
Updated Multiple NuGet packages