Self-hosted service
antibrow/antibrow avatar
antibrow/antibrow

AntiBrow: kernel-level antidetect browser profiles behind the standard Playwright API

Kernel-level antidetect browser with the Playwright API you already write. Python + Node SDKs, MCP-ready, unlimited local profiles. Linux x64 + arm64, macOS Intel + Apple Silicon, Windows x64.

526 stars0 forksTypeScriptNOASSERTION

At a glance

What is it?
AntiBrow ships open-source Python and Node SDKs that launch a patched Chromium with a coherent real-device fingerprint, so existing Playwright scripts keep working. The engine, the relay and the profile format are where the interesting trade-offs sit.
Who is it for?
Adopt AntiBrow if you already have Playwright scripts and need per-profile identities with proxies, or if you want Android-shaped profiles without a device farm. Skip it if you need a GUI profile manager for non-developers, or if your automation is not browser-based at all.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What AntiBrow solves, and who it is actually for

Automation against sites that fingerprint the browser has a specific failure shape. The script works, then the site starts returning captchas or empty pages, and the cause is not the request rate but the browser itself: a headless Chromium whose canvas, WebGL, audio and font metrics do not agree with the user agent it claims to be. AntiBrow's answer is to move the spoofing into Chromium's C++ layer rather than patching JavaScript objects at runtime. The README states that fingerprints are produced inside the engine, so there are no toString, prototype or stack-trace tells for a detector to find. That is a different class of change from the usual stealth plugin, which patches the page after the browser has already reported its real values.

The audience is narrow and identifiable. You write Playwright today, you need many identities on one machine, and you need each identity to look like a different real device. AntiBrow returns a normal BrowserContext over CDP, so the migration path is changing how the browser is launched rather than rewriting selectors and waits. If your work is a single logged-in session on your own account, none of this applies and the extra machinery is cost without benefit.

Coherent profiles instead of randomized parameters

The design decision that separates AntiBrow from randomizers is stated plainly in the README: a profile's values are sampled from one real machine, across 30+ categories and 500+ parameters, so canvas, WebGL, WebGPU, audio, fonts, WebRTC and the protocol layer agree with each other. Independently randomized values contradict each other, and contradiction is exactly what fingerprinting scripts look for. A GPU string that does not match the platform, or a font list that does not match the OS, is a stronger signal than a generic but consistent profile.

Two consequences follow. First, profiles are persistent identities: cookies, storage and passkeys survive restarts, and the README describes passkeys as captured and replayed through a per-profile virtual authenticator that is on by default. Second, profiles are portable. A profile can be exported to a single .fpprofile file holding identity, browser state and the passkey store, then imported on another machine. Both SDKs read the same on-disk format, so a profile created in Python is launchable from Node with the identical fingerprint.

The Android path is the most interesting part of this and the easiest to misread. Setting device_type="android" in Python or deviceType: 'android' in JS gives a profile a real phone's identity: mobile client hints, touch input, a portrait screen and a mobile GPU. The README says real phones ship inside both packages, so this works without a device farm and on the free tier. What it does not claim is that the profile is a phone. It is a desktop Chromium presenting a phone's identity, and the engine is doing the work of keeping that story consistent.

Installing the Python SDK and running a first profile

The Python package is on PyPI as antibrow. Install it, then launch a browser; the README notes the engine downloads on first run, so the first launch is slower than later ones and needs network access.

bash
pip install antibrow

The minimal script opens a page and closes the browser. There is no separate driver binary to manage and no custom context class to learn.

python
from antibrow import launch

browser = launch()
page = browser.new_page()
page.goto("https://example.com")
browser.close()

Once that runs, the next step is a profile with a proxy. The README gives the relay form as a proxy URL, and the same key parameter selects the encrypted protocol. Note that ?key= is the relay's 32-byte base64url pre-shared key; a malformed key is refused rather than downgraded to plaintext.

python
browser = launch(proxy="relay://alice:s3cret@relay.yourdomain.com?key=<relay key>")

If you would rather not assemble browser calls at all, the recipes layer takes a site name and returns structured data. The README shows run_recipe with temporary=True, which creates a throwaway profile for the call.

python
from antibrow import run_recipe, fanout_recipe

print(run_recipe("reddit/hot", temporary=True, args={"limit": 5}).value)

For the JavaScript side the install is two packages, anti-detect-browser and playwright-core, and the entry point is openProfile with a key and a profile name.

The relay transport and what it replaces

SOCKS5 and HTTP CONNECT put a fixed, recognizable handshake on the wire before any of your traffic moves. AntiBrow's relay:// scheme is an attempt to remove that signature. The engine opens a single WebSocket to the relay and speaks an AEAD-sealed frame protocol inside it: keys derived per connection with HKDF-SHA256, each frame sealed with AES-256-GCM under a counter nonce. The README states the target hostname travels inside the sealed frame, so there is no plaintext CONNECT line, no SOCKS5 handshake and no fixed-length header to match on. The relay server is MIT-licensed and self-hostable.

This is a real architectural claim and it has a real cost. You need a relay server you control or trust, and the pre-shared key is a secret that has to be distributed to every client. The README also notes that leaving ?key= out means the URL refers to the older plaintext protocol, which a relay serves only if its operator enabled it. If you run the plaintext path, you have given up the property the relay exists for.

The proxy-auth design is the quieter improvement. HTTP, HTTPS and SOCKS5 credentials go inline on --proxy-server and the engine answers the challenge itself. No helper extension is loaded, so nothing appears in chrome://extensions. Extension-based proxy auth is a well-known tell, and removing it removes an entire category of detection surface.

Where AntiBrow is the wrong tool

The repository is the SDKs. The README is explicit that this repository holds the open-source SDKs and points to a separate licensing section for what is and is not open, and the repository root carries both LICENSE and BINARY-LICENSE.md. The engine is a binary, not source you can audit and rebuild. If your threat model requires reading the C++ that produces the fingerprint, or building the browser from source on your own toolchain, AntiBrow does not give you that. This is a genuine limitation, not a packaging detail.

There is also no GUI profile manager in this repository. Profiles are created and launched through Python, Node, the CLI or MCP server mode. Teams that expect a desktop application for non-technical operators to click through will not find one here, and the .fpprofile export is a file-moving workflow, not a management interface.

Recipes carry their own boundary. They are pinned by SHA-256, only reviewed ones run by default, and each may only reach the hosts it declares, with requests to any other host blocked. That is the right default, but it means a recipe is not a general scraper. If your target site has no recipe, you are writing browser automation yourself, and the README points to the recipes repository's GUIDE.md for the format.

Finally, the whole thing assumes browser automation. If the data you need is available from an API, or the site does not fingerprint at all, the engine download, the profile store and the proxy layer are overhead with no matching return.

How it compares to Puppeteer with a stealth plugin

The closest alternative for most teams is Puppeteer or Playwright plus a JavaScript stealth plugin. The difference is where the patch lands. A stealth plugin runs in the page context and overwrites navigator properties, WebGL getters and similar surfaces after the browser has already been initialized; the underlying values still exist, and the plugin's own modifications can be detected by inspecting function source or property descriptors. AntiBrow's README frames its approach as the opposite: fingerprints produced inside Chromium's C++ layer, so the values the page reads are the values the engine decided on, with no JavaScript layer to inspect.

That difference also changes what you maintain. A stealth plugin is a package you upgrade and whose patch list you track against each Chromium release. AntiBrow is an engine binary you download, with SDK packages on top. The trade is that you gain a consistent profile store, proxy handling and the relay transport, and you lose the ability to read and modify the spoofing code. For teams that need to justify every line that touches a target site, that trade goes the wrong way. For teams whose current problem is captchas on a script that otherwise works, it goes the right way.

Maintenance, releases and the licence split

The last push to the default branch was on 2026-09-11, and the Python SDK has a steady release cadence: python-v0.21.0 on 2026-09-01, python-v0.22.0 on 2026-09-08 and python-v0.23.0 on 2026-09-11. The repository is not archived. The version numbers are 0.x, which matters for upgrade planning: minor releases in a 0.x line are where breaking changes are allowed to land, so pinning a version and reading release notes before bumping is the sensible default rather than an excess of caution.

The licence situation needs reading rather than assuming. The README's badge says SDK license MIT, and the repository root contains LICENSE alongside a separate BINARY-LICENSE.md. The repository metadata reports the licence as NOASSERTION, which is what GitHub shows when it cannot map the files to a known identifier. The practical reading is that the SDKs and the engine binary are licensed differently, and the terms that apply to the engine are in BINARY-LICENSE.md. Whether that matters to you depends on how you distribute your own product; this is a file to read before shipping, not after.

The recipes live in a separate repository, antibrow/recipes, which the README describes as the place to add a site. That is a deliberate split: adding a site is a pull request there rather than a release of the SDKs. It keeps the SDK release cadence independent of site coverage, at the cost of one more repository to watch.

Editorial conclusion

Adopt AntiBrow if you already have Playwright scripts and need per-profile identities with proxies, or if you want Android-shaped profiles without a device farm. Skip it if you need a GUI profile manager for non-developers, or if your automation is not browser-based at all. Before committing, verify three things: the SDK licence split described in BINARY-LICENSE.md, whether the engine binary downloads cleanly on your target platform, and whether your sites have a recipe in antibrow/recipes or need one written from its GUIDE.md.

Frequently asked questions

How do I install AntiBrow?

The Python SDK installs from PyPI with pip install antibrow, and the JavaScript SDK installs with npm install anti-detect-browser playwright-core. The engine binary downloads on first run, so the initial launch needs network access and takes longer than subsequent ones.

Does AntiBrow work with the Playwright code I already have?

The README states you get a normal BrowserContext over CDP and that existing scripts port over by changing how the browser is launched. There is no proprietary API to learn.

Can AntiBrow create Android profiles on a desktop machine?

Yes. Setting device_type="android" in Python or deviceType: 'android' in JS gives a profile a real phone's identity, including mobile client hints, touch input, a portrait screen and a mobile GPU. The README says real phones ship inside both packages, so it works without a device farm and on the free tier.

Official sources

  1. antibrow/antibrow on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Community notes

Community notes