What is speech synthesis fingerprinting?
Speech synthesis fingerprinting reads speechSynthesis.getVoices(), which enumerates the text-to-speech voices the host operating system has installed. Each entry carries a name, a BCP-47 lang tag, a localService flag and a default marker. Nothing is ever spoken aloud — the list alone is the signal.
The list is interesting because it is not really a browser property. The browser is a window onto the platform's speech engine, so the returned set reflects the OS and which locale packs are installed on it: a Windows host tends to surface Microsoft-prefixed voices, a macOS host surfaces its own, and the distinct lang tags across the set describe which language packs the machine actually carries. It is also a surface that browser-level spoofing stacks essentially never touch, which is what makes it a read on the real environment underneath a configured browser.
That gives it a coherence role rather than an identification one. A session presenting a macOS platform claim while enumerating a Windows voice set is a contradiction — two signals sourced from the same machine that disagree about what that machine is. The same reasoning applies to locale: a voice set carrying only one language pack sits awkwardly under a persona claiming a different region, in the same family of mismatch as a timezone/IP mismatch or a font set that doesn't match the OS it claims.
The limits matter more than the signal. An empty voice list is ordinary: Linux hosts without speech-dispatcher return nothing, so do VDI sessions, Windows N editions, and offline machines — and on a real desktop the list is frequently just not loaded yet at probe time, since voices populate asynchronously and the first synchronous getVoices() call often returns an empty array before the voiceschanged event fires. Emptiness therefore has too many innocent causes to attribute to anything.
This is why the Clearcote audit's speech-voices check is info severity and contributes nothing to the score. A non-empty list reports true and records the voice count, the number of distinct languages, and which voice is marked default; an empty list reports N/A rather than a failure. Scoring it would fail ordinary desktops for having a normal configuration.
It is a useful worked example of a signal that is informative but too environment-dependent to fail a browser on. Read the cell as a description of the host, not a verdict: compare the voice set and its languages against the platform and locale you intend to present, and treat a disagreement as something to resolve at the source. See anatomy of a browser fingerprint for where this sits among the other signals.