native methods enforce their C++ receiver check
Check id native-brand-checks
What an ordinary browser yields
Both getParameter and canPlayType reject a bare-prototype receiver with a TypeError.
What a detector infers
Two native methods are invoked with their own bare prototype as the receiver: WebGLRenderingContext.prototype.getParameter.call(WebGLRenderingContext.prototype, 37445) and HTMLMediaElement.prototype.canPlayType.call(HTMLMediaElement.prototype, 'video/mp4'). The C++ implementations perform a brand check on the receiver — a bare prototype is not a real context or media element — so both must throw a TypeError. The check fails if either does not throw at all (the receiver check is gone, and the call returns a spoofed value such as a fake vendor string), or if it throws something other than a TypeError. A JS or Proxy replacement has no brand check to inherit, so this catches hooks that stringify convincingly and walk past toString-based probes. Only the error type is asserted, never the message wording, which varies by engine.
How to resolve it
Don't replace these methods with JS functions or Proxies. Faking Function.prototype.toString is not sufficient — the C++ receiver check is a hard invariant a JS replacement cannot reproduce. Apply WebGL and codec spoofing inside the engine so the native brand check stays intact.
Read in the wild by
CreepJS
CreepJS, an open-source fingerprinting research demo rather than a production detector, invokes native interface methods — including WebGLRenderingContext.prototype.getParameter — with their own bare prototype as the receiver, and records a lie when the call does not throw a TypeError.
src/lies/index.ts:170 — `['failed call interface error']: failsTypeError({ spawnErr: () => { new apiFunction(); apiFunction.call(proto) } })`, where `proto` is the interface prototype, together with `function isTypeError(err) { return err.constructor.name == 'TypeError' }` (:77) and `function failsTypeError({ spawnErr })` which returns true (a lie) when `spawnErr()` does not throw a TypeError (:79). Applied to getParameter via `searchLies(() => WebGLRenderingContext, { target: ['bufferData', 'getParameter', 'readPixels'] })` (:773, and WebGL2RenderingContext at :780). NOTE: the getter-only `['failed illegal error']: !!obj && failsTypeError({ spawnErr: () => obj.prototype[name] })` (:159) is NOT the supporting evidence — searchLies passes `obj: null` on the method path (:389), so it never fires for methods such as getParameter.
Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Native function integrity
- a fresh iframe (contentWindow) matches the main realm
iframe-coherenceThe check appends a hidden same-origin iframe to documentElement and reads its contentWindow — a brand-new JavaScript realm with its own… - Worker navigator matches the main thread
worker-navigator-coherenceA Blob-URL Worker is spawned and reports its own navigator.platform, navigator.hardwareConcurrency, navigator.webdriver and… - page-world natives that extensions commonly wrap
page-world-wrappersThis probe stringifies window.fetch and window.Request and asks whether each still renders as native code, then checks whether document… - nonexistent navigator properties return undefined
navigator-proxy-honeypotThis reads five navigator property names that exist on no browser — rml, ln, rnd, webdriverPatched and __clearcoteProbe — and additionally… - iframe srcdoc/src/contentWindow live on the prototype
iframe-srcdoc-placementA fresh <iframe> is created with document.createElement and inspected for own property descriptors on srcdoc, src and contentWindow. - Element.attachShadow untampered (shape + closed/open behaviour)
shadow-dom-integrityThe check reads Element.prototype.attachShadow four ways and asserts they agree: its name is "attachShadow", its length (declared parameter… - Math.random / crypto.getRandomValues native and high-entropy
rng-integrityThe check verifies that Math.random is the engine's native generator and that its output is high-entropy. - the global object still has every global a fresh realm has, in the same order
window-globals-vs-realmThe audit builds a fresh same-origin iframe and enumerates the own properties of both global objects, then asserts two things a browser…
Clearcote is a browser built for fingerprint coherence
It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.
This audit takes no position on how Clearcote scores on Native function integrity checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.
See the other checks in Native function integrity — the family native-brand-checks belongs to.