Docs Β· Python SDK Β· JS SDK Β· Releases Β· The name π
Need help getting through a tough site?
Reach out β Arman Hossain on LinkedIn or at arman@bytetunnels.com
ChromiumFish is a fingerprint-hardened Chromium fork that presents one coherent browser identity. Because the spoofing happens down in the C++ engine instead of in injected JavaScript, there's nothing for "is this tampered with?" checks to catch.
This repo is the part that gets it onto your machine and into your script. It publishes the prebuilt browser as GitHub Release assets and ships matching pip and npm packages that grab the right build for your platform and launch it through Playwright β so if you already know Playwright, you already know how to drive it.
π Python
pip install chromiumfishfrom chromiumfish.sync_api import Chromiumfish
with Chromiumfish(persona_seed="alpha-7", headless=True) as browser:
page = browser.new_page()
page.goto("https://example.com")
page.screenshot(path="fingerprint.png")β¬’ Node
npm install chromiumfishimport { ChromiumFish } from "chromiumfish";
const browser = await ChromiumFish({ personaSeed: "alpha-7", headless: true });
const page = await browser.newPage();
await page.goto("https://example.com");
await browser.close();Beyond driving it yourself, hand the browser a plain-language task β its built-in agent perceives the page and acts (click, type, read, navigate) in a loop, driven by any OpenAI-compatible LLM.
The native agent clearing a bot-check and completing a four-step checkout from one plain-language task (4Γ speed).
from chromiumfish import launch_agent # JS: import { launchAgent } from "chromiumfish"
# the exact task behind the clip above
TASK = """Complete this shopping flow on the site, in order:
1. This is a "verify you are human" bot-check. Tick the checkbox and wait until it lets you through to the shop.
2. On the shop, open the first product and add it to the cart.
3. Go to /login and sign in with email demo@bytetunnels.test and password password123.
4. Go to /cart, check out, and fill the form (name "Demo User", address "1 Test Street", city "Testville"). Place the order.
5. Report the order confirmation number."""
with launch_agent() as agent: # OPENAI_API_* read from a nearby .env
result = agent.run_task(TASK, url="http://127.0.0.1:8000/verify#url=/shop")
print(result.final_text)See the AI Agent guide and runnable examples.
Prefer an external framework? Because it is Chromium, ChromiumFish speaks the same CDP every browser-agent already drives. Expose an endpoint with one command and point Hermes, OpenClaw, browser-use, Playwright, or Puppeteer at it β the agent inherits the persona/proxy/timezone you launched with, no special build required.
$ chromiumfish serve --persona-seed alice
ChromiumFish Chrome/149.0.7827.115 ready β CDP endpoint for external agents
HTTP : http://127.0.0.1:9222
# Hermes: ~/.hermes/config.yaml -> browser: { cdp_url: "http://127.0.0.1:9222" }Or run it as an MCP server β chromiumfish mcp exposes the browser as tools to Claude Code/Desktop, Cursor, and any MCP client (pip install "chromiumfish[mcp]").
See the External Agents guide.
I scrape the web at scale, and some sites fight back hard. I worked through most of the open-source stealth browsers and a couple of paid ones, and they kept failing the same way: they run on a Linux server and try to look like they aren't, but they do it with JavaScript patches. That's a bad place to hide. A JS patch leaves tampering marks right where the "has this been messed with?" checks are looking, and the detectors I cared about caught them every time. So I moved the spoofing down into the C++ engine, where there's nothing for a tampering probe to find, and started using it to unblock my own scrapers. It has since gotten me through a few sites that had blocked everything else I tried.
- 𧬠Spoofing in the engine, not in a script. UA, Client Hints, fonts, audio, screen, and WebRTC are spoofed inside Chromium itself.
navigator.webdriverstaysfalseeven under CDP, and there are nocdc_automation artifacts lying around. - π One seed, one persona. A single
persona_seed(any stable string id) gives you a stable, internally-consistent identity. Change it for a fresh, unlinkable one; reuse it for continuity across sessions. - π¨ Canvas & WebGL through an optional bridge. These are the hardest signals to fake from a headless Linux box, where SwiftShader gives you away. Point ChromiumFish at a small render bridge running on Windows and canvas/WebGL reads come back from a real machine instead. It's a separate, optional service, not bundled in the binary.
- π€ It's just Playwright. Because it is Chromium, everything you already do in Playwright works unchanged. The SDK is a thin wrapper over
chromium.launch(executablePath=β¦). - π€ Native AI agent. A perceive β think β act agent built into the browser process (not a Playwright puppeteer script). Hand it a plain-language task and point it at any OpenAI-compatible LLM. See the AI Agent guide.
- π¦ Install in one line.
pip install chromiumfishornpm i chromiumfish; the binary downloads and caches itself the first time you run it. - π₯οΈ Happy headless. Runs on GPU-less Linux via SwiftShader.
pip install chromiumfish
chromiumfish fetch # download + cache the browser buildnpm install chromiumfish
npx chromiumfish fetchBoth SDKs need Playwright (it's a peer dependency). On first use they pull the browser binary from this repo's Releases and cache it under ~/.cache/chromiumfish/<version>/, so you only pay the download once.
Platforms: prebuilt for macOS and Linux today. A Windows build is coming soon.
The browser is the Chromium fork that lives in this same repo β patches/ + assets/ applied over an upstream checkout, then built and published as a Release. The SDK does very little: figure out which asset matches your version and platform, check its SHA-256, unpack it, and hand the path to Playwright. The Quickstart walks through it.
It comes down to three pieces, each doing one thing:
| Piece | What it does | Why it matters |
|---|---|---|
| The browser | Hides you | UA, screen, fonts, audio and WebRTC are spoofed in the C++ engine β no extension, no injected script, so "is this tampered with?" probes find nothing. Canvas and WebGL can be routed through the optional Windows bridge for a real-GPU result. |
| The SDK | Runs it | pip install / npm i, then fetch β verify β cache β launch via Playwright. Zero fingerprinting logic, nothing to keep in sync. |
| The persona seed | Picks who you are | One number β one coherent identity, correlated like real hardware (8 cores β plausible RAM). Same seed = same person; new seed = a clean, unlinkable one. |
The full docs live at chromiumfish.com (built with Just the Docs from docs/):
- Introduction
- Installation Β· Quickstart Β· Personas
- AI Agent β the native in-browser agent Β· External Agents β drive it from Hermes, OpenClaw, browser-use, β¦
- Recipes Β· Canvas & WebGL bridge Β· Troubleshooting
- Python API Β· JavaScript API
It's a monorepo. The browser fork (just the source delta over upstream) and the things that ship it β the SDKs and docs β sit side by side.
chromiumfish/
βββ patches/ # the fork's source delta over upstream Chromium
βββ assets/ # binary build overlays (icons, fonts) rsync'd into src/
βββ apply.sh # apply patches/ + assets/ onto ./src/
βββ UPSTREAM_REVISION # exact upstream commit the fork is authored against
βββ packages/
β βββ python-sdk/ # `chromiumfish` on PyPI
β βββ js-sdk/ # `chromiumfish` on npm
βββ docs/ # Just the Docs site (+ docs/assets/ brand artwork)
βββ README.md
βββ LICENSE
The Chromium checkout (
src/) and build output (out/,dist/) aren't tracked β see.gitignore. You rebuild the fork by applyingpatches/+assets/onto a matching upstream checkout.
It's not about fish. The name is for the silverfish, a 400-million-year-old insect that has sat out four mass extinctions by simply never being noticed β no armor, no speed, no trail worth following. That's the whole idea behind a browser that would rather not be fingerprinted. The longer story is here.
ChromiumFish is provided for educational and authorized research purposes only β learning how browser fingerprinting works, testing the resilience of systems you own or are explicitly permitted to test, and privacy research.
You are solely responsible for how you use it. Use it only in compliance with all applicable laws and with the terms of service of any site or service you interact with. Do not use it for fraud, unauthorized access, evading security controls, or any other unlawful or abusive activity.
The software is provided "as is", without warranty of any kind, express or implied. To the maximum extent permitted by law, the author and contributors accept no liability for any claim, damage, or other loss arising from its use or misuse. By using ChromiumFish you accept full responsibility for your actions.
MIT Β© Arman Hossain. ChromiumFish is built on the Chromium project (BSD-3-Clause); the browser distribution bundles Chromium's license and credits. "Chromium" and "Google Chrome" are trademarks of Google LLC; ChromiumFish is an independent fork and is not affiliated with or endorsed by Google.
