PuppeteerSharpToolkit 0.1.0
dotnet add package PuppeteerSharpToolkit --version 0.1.0
NuGet\Install-Package PuppeteerSharpToolkit -Version 0.1.0
<PackageReference Include="PuppeteerSharpToolkit" Version="0.1.0" />
<PackageVersion Include="PuppeteerSharpToolkit" Version="0.1.0" />
<PackageReference Include="PuppeteerSharpToolkit" />
paket add PuppeteerSharpToolkit --version 0.1.0
#r "nuget: PuppeteerSharpToolkit, 0.1.0"
#:package PuppeteerSharpToolkit@0.1.0
#addin nuget:?package=PuppeteerSharpToolkit&version=0.1.0
#tool nuget:?package=PuppeteerSharpToolkit&version=0.1.0
PuppeteerSharpToolkit
PuppeteerSharpToolkit is a high-performance, AOT-friendly plugin toolkit for PuppeteerSharp. It’s a modern reimagining of the PuppeteerExtraSharp pattern with a new entry point (PluginManager), focused on trimming- and AOT-safe code, reduced allocations, and startup speed. It is not a drop-in replacement for PuppeteerExtraSharp
; APIs and behaviors have been redesigned for performance and clarity.
Why this package exists
- Updated core: Bumps PuppeteerSharp dependencies to a more modern stack.
- .NET 9 support: Targets .NET 9, unlocking ahead-of-time (AOT) compilation and aggressive trimming for small, fast binaries.
- Performance-first design: Rewritten internals to avoid reflection and embedded DLL tricks; optimized for minimal allocations and startup cost.
- Dropped RestSharp: No longer depends on RestSharp.
- Dropped NewtonSoftJson: No longer uses NewtonSoft -
System.Text.Json
is the new king.
Quickstart
// Initialize the plugin manager
var manager = new PluginManager();
// Register plugins (dependencies first)
manager.Register(new AnonymizeUaPlugin());
// Launch the browser with plugins wired
await using var browser = await manager.LaunchAsync(new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.GoToAsync("https://example.com");
await page.ScreenshotAsync("example.png");
Plugin list
- Stealth Plugins – Various evasion techniques to make headless detection harder.
- Anonymize UA Plugin – Anonymizes the user-agent on all pages.
- ReCAPTCHA Plugin – Solves reCAPTCHAs automatically.
- Block Resources Plugin – Blocks images, documents, and other resource types to speed up navigation.
API
Stealth Plugins
Stealth related plugins are made for evading detection, usually by injecting scripts at specific times at which websites try to detect bots.
The available evasion plugins are the following: ChromeAppPlugin, ChromeSciPlugin, CodecPlugin, ContentWindowPlugin, EvasionPlugin, HardwareConcurrencyPlugin, LanguagesPlugin, LoadTimesPlugin, OutDimensionsPlugin, PermissionsPlugin, StackTracePlugin, UserAgentPlugin, VendorPlugin, WebDriverPlugin, WebGLPlugin.
In this example we'll use ChromeSciPlugin which patches "chrome.app" and some other chrome APIs that are used by bot detection scripts.
var manager = new PluginManager();
manager.Register(new ChromeSciPlugin());
// Continue with browser and page
To make life a bit easier, Stealth is a static class that provides some static methods:
PuppeteerPlugin[] GetStandardEvasions(params PuppeteerPlugin[] pluginOverride);
// Which returns an array of most stealth plugins.
// The override allows you to initialize any that you with custom arguments
// Any override that you supply will be used instead of calling the default plugin ctor
Task RegisterUtilsAsync(IPage page);
// This function register `utils.js` on a page, it is required by some scripts
// You could also use it if you implement your own plugin, which injects a script
// ... that can rely on `utils.js`
So in essence you could register a suite of stealth plugins in one go:
var manager = new PluginManager();
manager.Register(Stealth.GetStandardEvasions());
AnonymizeUaPlugin
AnonymizeUaPlugin is used to transform the user agent on any page as soon as it launches.
// Initialize the plugin manager
var manager = new PluginManager();
// Initialize the plugin
var plugin = new AnonymizeUaPlugin();
// Register the plugin
manager.Register(plugin);
// by default it will replace headless with regular chrome
// and set platform to windows
// you can also add your own custom transformation at any time by changing the function
plugin.UserAgentTransformer = ua => "whatever";
// Initialize browser and page + continue with whatever else
RecaptchaPlugin
Anti-Captcha
provider is disabled pending better solution for their requirement to get recaptcha key.2Captcha
provider is disabled pending tests using their API to ensure stability.
RecaptchaPlugin is used in conjunction with Recaptcha solving providers, at this state AntiCaptchaProvider and TwoCaptchaProvider are supported, but this is extensible so you add your own.
The following is an example with AntiCaptcha
// have HttpClient instance ready (it is used to send the requests)
using var client = new HttpClient(); // initialization as example
// best practices will use a factory/singleton
// Initialize the plugin manager
var manager = new PluginManager();
// Initialize the provider (HttpClient, userKey, ProviderOptions)
var provider = new AntiCaptchaProvider(client, "sampleKey", ProviderOptions.Default);
// Default provider options can be used or inferred if omitted.
// Initialize plugin
var plugin = new RecaptchaPlugin(provider);
// Register the plugin
manager.Register(plugin);
// Initialize browser and page
await using var browser = await manager.LaunchAsync();
await using var page = await browser.NewPageAsync();
// go to page with captcha
await page.GoToAsync("https://patrickhlauke.github.io/recaptcha/");
// now solve captcha at page
await plugin.SolveCaptchaAsync(page); // Also accepts proxyStr and cancellationToken.
For 2captcha simply use the TwoCaptchaProvider instead.
BlockResourcesPlugin
This plugin is used to blocks page resources in Puppeteer requests (img, documents etc.)
// Initialize the plugin manager
var manager = new PluginManager();
// Initialize the plugin
var plugin = new BlockResourcesPlugin();
// Register the plugin
manager.Register(plugin);
// Initialize browser and page
await using var browser = await manager.LaunchAsync();
await using var page = await browser.NewPageAsync();
// Create a rule
var blockGoogle = new BlockRule() {
SitePattern = new Regex("google"), // SitePattern applies only to specific urls by pattern
// You can also point it to a GeneratedRegex
IPage = page, // it will affect this instance of the page
ResourceType = ResourceType.Scripts // Block scripts
};
// Add rule
plugin.AddRule(blockGoogle);
You can also inspect rules on the plugin, as well as add or remove rules at any point. removing rules uses a Func<BlockRule, bool>
predicate to select the rules to remove.
Core API
- Plugin registration: PluginManager.Register(params PuppeteerPlugin[] plugins)
- Launch: await PluginManager.LaunchAsync(LaunchOptions options)
- Connect: await PluginManager.ConnectAsync(ConnectOptions options)
Caveats / Testing
RecaptchaPlugin is a clean abstraction, and the tests are mainly testing the specific providers, these tests require having API keys for said providers.
To set the API keys, dotnet
user secrets is used, it must be configured when inside the test project directory:
dotnet user-secrets set [secretName] [secretValue]
- For AntiCaptchaProvider:
secretName = "AntiCaptchaKey"
- For TwoCaptchaProvider:
secretName = "TwoCaptchaKey"
All Recaptcha tests are marked as Explicit
and will not execute when running the full test suite (unless specifically asked for), this is to avoid burning API usage.
If you do want to run them use:
dotnet run --explicit on/only
Also, each provider test will be skipped automatically if the required API key wasn't found in user secrets, so if for example you only have an API key for AntiCaptcha
- only the tests related to this provider will run.
Contribution
Patches, performance improvements, and fixes are welcome. Focus is on keeping the core lean and compatible with modern .NET publishing scenarios.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net9.0
- PuppeteerSharp (>= 20.2.2)
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 |
---|---|---|
0.1.0 | 133 | 8/13/2025 |
0.1.0-rc.2 | 115 | 8/13/2025 |
0.1.0-rc.1 | 120 | 8/13/2025 |
- Initial release