canPlayType behaves like a real codec parser (bogus + quoting)
Check id canplaytype-parser-traps
What an ordinary browser yields
A bogus codec returns "", and quoted and unquoted codecs params agree.
What a detector infers
A real canPlayType is an RFC-6381 parser, not a dictionary. This check exercises two properties only a parser has. First, it asks for video/mp4; codecs=bogus — an unknown codec, for which the spec requires the empty string; a lookup table keyed on literal MIME strings frequently misses the codecs parameter and answers "probably" for the mp4 container. Second, it checks that quoting is transparent, comparing audio/wav; codecs=1 against audio/wav; codecs="1" and video/mp4; codecs=avc1.42E01E against its quoted form: a parser tokenizes and strips the quotes, so both members of each pair must agree, while a string-keyed map sees two distinct keys and desyncs. Neither cell carries useful information about the host's real codec support, which is precisely why they discriminate — they probe implementation shape, not capability. Severity is critical because a mismatch is self-contained evidence that answers come from a table.
How to resolve it
Don't answer canPlayType from a map keyed on literal MIME strings. Either leave the native parser in place, or parse the type and codecs parameter properly — strip quoting, and return "" for any codec you don't actually claim. If a table is unavoidable, normalize the input through a real RFC-6381 tokenizer before lookup so both traps resolve consistently.
Read in the wild by
Kasada
Calls canPlayType with a deliberately invalid codec string, video/mp4; codecs=bogus, and carries the answer as its own slot in the fingerprint payload alongside valid MP4 codec probes.
Decompiled ips.js, 1.txt:44691 (func_02ebf0): `_6163.v.canPlayType("video/mp4; codecs=bogus")` — "bogus" is a literal in Kasada's own XOR'd __strTable (present in both script versions, 2.txt and 3.txt). The teardown labels this probe video_mp4_bogus (probes.txt:311) and places it at blog.txt batch 3 slot 56: `56:video_mp4_bogus(fn_41929)` of the 428-slot payload. Valid MP4 codec probes in the same matrix: 1.txt:48219 `canPlayType("video/mp4; codecs=\"avc1.42E01E\"")` (video_mp4_avc1, slot 230) and 1.txt:1123 `canPlayType("video/mp4; codecs=mp4a.40.2")` (video_mp4_mp4a, slot 295).
Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Environment & locale
- CSS feature support matches the engine (Blink for a Chrome UA)
css-engine-surfaceFor any UA containing 'Chrome/', this requires CSS.supports('-webkit-app-region', 'drag') to be true and the Gecko markers — MozAppearance… - every Intl constructor resolves the same locale
intl-locale-coherenceEvery Intl constructor — NumberFormat, DateTimeFormat, PluralRules, Collator — resolves its locale through the same underlying ICU data, so… - navigator.plugins is a real platform object (structured-clone probe)
plugins-structured-cloneThe structured-clone algorithm is implemented in C++ and interrogates objects about what they actually are, not what they claim. - canPlayType answers identically for <video>, <audio> and the prototype
canplaytype-element-agnosticcanPlayType is implemented exactly once, on HTMLMediaElement.prototype, so <video> and <audio> inherit the same C++ function. - AudioContext invariants + a deterministic offline render
audio-context-coherenceThe check constructs a live AudioContext and reads four invariants — sampleRate, baseLatency, the destination node's channelCount against… - the analyser byte spectrum is the defined quantisation of its float spectrum
audio-analyser-float-vs-byteAn AnalyserNode publishes the same spectrum twice. getFloatFrequencyData returns decibels, and getByteFrequencyData returns that spectrum… - speech synthesis voices (host OS speech engine)
speech-voicesspeechSynthesis.getVoices() enumerates the host operating system's speech engine — a resource stealth stacks essentially never touch, which… - the voice list arrives the way Chrome delivers it
speech-voices-async-pathspeech-voices reads WHAT is in the voice list. This reads HOW the list arrived, which is a separate fact and survives a roster whose every…
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 Environment & locale 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 Environment & locale — the family canplaytype-parser-traps belongs to.