This document explains why Chromax's native Chromium fingerprint protection is superior to browser extensions and JavaScript injection methods.
How it works:
- Injects JavaScript into pages
- Overrides browser APIs using
Object.defineProperty() - Runs in content script context
Problems:
// Extensions leave traces
navigator.webdriver === true // ❌ Detectable
window.chrome.runtime.id // ❌ Extension ID exposed
// API overrides are detectable
const canvas = document.createElement('canvas');
const descriptor = Object.getOwnPropertyDescriptor(
HTMLCanvasElement.prototype, 'toDataURL'
);
descriptor.get.toString() // ❌ Shows it's been modifiedDetection methods:
- Check for
navigator.webdriver - Check for extension IDs in
window.chrome.runtime - Inspect property descriptors for modifications
- Check function
.toString()for native code - Look for timing anomalies in API calls
How it works:
- Injects JavaScript before page load
- Overrides APIs using
Object.defineProperty() - Runs via
Page.addScriptToEvaluateOnNewDocument()
Problems:
// Automation detection
navigator.webdriver === true // ❌ Still present
// Function modifications detectable
HTMLCanvasElement.prototype.toDataURL.toString()
// Returns: "function toDataURL() { [injected code] }"
// Instead of: "function toDataURL() { [native code] }"
// Timing anomalies
const start = performance.now();
canvas.toDataURL();
const end = performance.now();
// ❌ Injected code is slower than nativeDetection methods:
- Check
navigator.webdriver - Inspect function
.toString()for "[native code]" - Measure API call timing
- Check for iframe context mismatches
- Look for property descriptor inconsistencies
How it works:
- Modifies Chromium C++ source code
- Overrides APIs at the browser engine level
- Controlled via command-line flags
Advantages:
// No automation detection
navigator.webdriver === undefined // ✅ Not present
// Functions appear native
HTMLCanvasElement.prototype.toDataURL.toString()
// Returns: "function toDataURL() { [native code] }" // ✅ Perfect
// No timing anomalies
const start = performance.now();
canvas.toDataURL();
const end = performance.now();
// ✅ Native performance, no overhead
// No extension artifacts
window.chrome.runtime === undefined // ✅ CleanUndetectable:
- No
navigator.webdriver - No extension IDs
- Functions show "[native code]"
- Native performance
- No property descriptor modifications
- No iframe context issues
| Feature | Extensions | JS Injection | Native (Chromax) |
|---|---|---|---|
| Canvas Protection | ✅ Undetectable | ||
| WebGL Protection | ✅ Undetectable | ||
| Screen Override | ❌ Limited | ✅ Perfect | |
| User-Agent | ✅ Works | ✅ Works | ✅ Perfect |
| navigator.webdriver | ❌ Present | ❌ Present | ✅ Removed |
| Function .toString() | ❌ Modified | ❌ Modified | ✅ Native |
| Performance | ✅ Native Speed | ||
| Extension Artifacts | ❌ Present | ✅ None | ✅ None |
| Iframe Consistency | ✅ Perfect | ||
| Worker Support | ❌ Limited | ❌ Limited | ✅ Full |
| Automation Tools | ✅ Works | ✅ Works | ✅ Works |
Extensions/JS Injection:
const original = HTMLCanvasElement.prototype.toDataURL;
console.log(original.toString());
// Output: "function toDataURL() { /* injected code */ }"
// 🚨 DETECTED: Not native code!Native Chromium (Chromax):
const original = HTMLCanvasElement.prototype.toDataURL;
console.log(original.toString());
// Output: "function toDataURL() { [native code] }"
// ✅ UNDETECTED: Appears as native code!Extensions/JS Injection:
const descriptor = Object.getOwnPropertyDescriptor(
HTMLCanvasElement.prototype, 'toDataURL'
);
console.log(descriptor.value === descriptor.value);
// 🚨 DETECTED: Property has been redefined!Native Chromium (Chromax):
const descriptor = Object.getOwnPropertyDescriptor(
HTMLCanvasElement.prototype, 'toDataURL'
);
console.log(descriptor.value === descriptor.value);
// ✅ UNDETECTED: Original native property!Extensions/JS Injection:
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeCanvas = iframe.contentWindow.HTMLCanvasElement.prototype.toDataURL;
const mainCanvas = HTMLCanvasElement.prototype.toDataURL;
console.log(iframeCanvas === mainCanvas);
// 🚨 DETECTED: Different functions in different contexts!Native Chromium (Chromax):
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeCanvas = iframe.contentWindow.HTMLCanvasElement.prototype.toDataURL;
const mainCanvas = HTMLCanvasElement.prototype.toDataURL;
console.log(iframeCanvas === mainCanvas);
// ✅ UNDETECTED: Same native function everywhere!Extensions/JS Injection:
// In Web Worker
self.postMessage(HTMLCanvasElement.prototype.toDataURL.toString());
// 🚨 DETECTED: Worker context not protected!Native Chromium (Chromax):
// In Web Worker
self.postMessage(HTMLCanvasElement.prototype.toDataURL.toString());
// ✅ UNDETECTED: Native code in all contexts!Here's a comprehensive test that websites use to detect fingerprint protection:
// Test 1: navigator.webdriver
if (navigator.webdriver) {
console.log("🚨 DETECTED: Automation tool");
}
// Test 2: Function toString()
if (!HTMLCanvasElement.prototype.toDataURL.toString().includes('[native code]')) {
console.log("🚨 DETECTED: Canvas API modified");
}
// Test 3: Property descriptor
const descriptor = Object.getOwnPropertyDescriptor(
HTMLCanvasElement.prototype, 'toDataURL'
);
if (descriptor.writable !== true || descriptor.configurable !== true) {
console.log("🚨 DETECTED: Property descriptor modified");
}
// Test 4: Iframe consistency
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
if (iframe.contentWindow.HTMLCanvasElement.prototype.toDataURL !==
HTMLCanvasElement.prototype.toDataURL) {
console.log("🚨 DETECTED: Iframe context mismatch");
}
// Test 5: Timing analysis
const start = performance.now();
for (let i = 0; i < 1000; i++) {
document.createElement('canvas').toDataURL();
}
const end = performance.now();
if (end - start > 100) { // Native should be < 10ms
console.log("🚨 DETECTED: Timing anomaly");
}
// Test 6: Extension detection
if (window.chrome && window.chrome.runtime && window.chrome.runtime.id) {
console.log("🚨 DETECTED: Extension present");
}Results:
- Browser Extensions: Fails tests 1, 2, 3, 4, 5, 6
- JS Injection: Fails tests 1, 2, 3, 4, 5
- Chromax (Native Chromium): ✅ Passes ALL tests
- No JavaScript modifications
- No extension artifacts
- Functions show "[native code]"
- No timing anomalies
- Works in all contexts (main, iframe, worker)
- Same behavior across navigation
- No race conditions
- Native C++ performance
- No JavaScript overhead
- No runtime patching
- Can't be bypassed by websites
- No context isolation issues
- Works with strict CSP policies
- Covers all APIs (Canvas, WebGL, Screen, etc.)
- Works in Web Workers
- Works in Service Workers
- Works in all iframe contexts
// This is what extensions/injection do:
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function(...args) {
// Add noise or modify output
const result = originalToDataURL.apply(this, args);
return modifyCanvasData(result);
};Problems:
- Function is now a JavaScript function, not native
.toString()shows JavaScript code- Property descriptor is modified
- Slower performance (JavaScript overhead)
- Doesn't work in all contexts (workers, iframes)
// This is what native patches do (simplified):
// In chromium/src/third_party/blink/renderer/core/html/canvas/...
String HTMLCanvasElement::toDataURL(const String& type, ...) {
String result = OriginalToDataURL(type, ...);
// Check command-line flag
if (RuntimeEnabledFeatures::FingerprintCanvasModeEnabled()) {
String mode = GetFingerprintCanvasMode();
if (mode == "noise") {
result = AddCanvasNoise(result, GetFingerprintCanvasSeed());
}
}
return result;
}Advantages:
- Function remains native C++ code
.toString()shows "[native code]"- Property descriptor unchanged
- Native performance
- Works in ALL contexts automatically
Native Chromium fingerprint protection is the ONLY truly undetectable method.
- ✅ No JavaScript modifications
- ✅ No extension artifacts
- ✅ Native performance
- ✅ Works everywhere
- ✅ Future-proof
This is why professional anti-detect browsers (Multilogin, GoLogin, etc.) all use custom Chromium builds rather than extensions.
Ready to use it? Check out the Quick Start Guide!