All articles Advanced signals

SpeechSynthesis Voices Fingerprinting: Reading the Installed Voice List

The browser can list every text-to-speech voice installed on a device, and that list quietly encodes the operating system, its version, the installed language packs, and sometimes third-party software. It is one of the more overlooked software-inventory signals available without a permission prompt.

How the signal works

The Web Speech API exposes speechSynthesis.getVoices(), which returns an array of voice objects. Each has a name, a lang code, a voiceURI, a localService flag, and a default marker. A device might report dozens of voices, from Microsoft David - English (United States) on Windows to Samantha and Alex on macOS to Google network voices in Chrome.

The combination of names, language codes, and ordering is characteristic of a platform and configuration. Windows, macOS, Android, iOS, and Linux each ship distinct default voice sets, and added language packs extend the list in user-specific ways.

What the voice list reveals

  • Operating system and version: default voice names map tightly to OS families and releases. New macOS versions rename or add voices; Windows ships its own set.
  • Installed language packs: extra languages mean extra voices, revealing multilingual configuration and hinting at region.
  • Browser engine: Chrome adds Google’s network-backed voices, while Safari and Firefox expose only local ones, so the mix reflects the browser too.
  • Local versus remote: the localService flag separates on-device voices from cloud voices, another distinguishing detail.

Taken together, the voice list is a moderate-entropy signal that strongly indicates OS and configuration, which makes it excellent for consistency checking.

The asynchronous gotcha

A practical wrinkle trips up naive implementations. In several browsers, getVoices() returns an empty array on first call and populates only after a voiceschanged event fires. A script that reads the list too early sees nothing and might wrongly conclude the device has no voices.

Prynt waits for the list to settle before recording it, and it treats a genuinely empty list, which is common in headless and stripped-down environments, as its own signal. An automation stack that never exposes any voices looks different from a real desktop that reports fifteen.

Consistency checking in practice

The voice list is most valuable as a cross-check. It should agree with the platform reported by User-Agent Client Hints, the font list, and the locale signals. A session claiming macOS through its user agent but reporting the Windows default voice set is contradicting itself, and that contradiction is a reliable tamper indicator.

Prynt folds voice data into its multi-signal model, where it corroborates the OS story told by fonts, canvas rendering, and platform hints. Because Prynt correlates these signals across its reputation network, a voice profile that appears across many accounts with mismatched platforms stands out as automation or a device farm rather than one legitimate user.

Privacy and restraint

Software-inventory signals like the voice list are powerful precisely because they describe the machine, so they must be handled with restraint. Prynt collects the aggregate list to derive OS and consistency features rather than to build an invasive profile of installed software, and it does not require this signal where a browser restricts it. As browsers continue tightening APIs, Prynt’s approach is to lean on signals that remain reliably and appropriately available rather than to chase every possible leak.

Cloud voices and browser differences

The voice list also quietly separates browsers in a way worth exploiting. Chrome supplements local voices with Google’s network-backed set, so a Chrome install typically reports more voices, several flagged as non-local, than Safari or Firefox on the same machine. That means the list reflects not just the operating system but the specific browser and its version, adding a second dimension to the signal. It also creates another consistency check: a session claiming to be Safari but reporting Google network voices is contradicting itself. Prynt uses these browser-specific patterns to corroborate the User-Agent Client Hints story, and it accounts for the fact that the same physical device can legitimately present different voice lists in different browsers, which is expected rather than suspicious.

Recommendations for teams

  • Wait for the voiceschanged event before reading the voice list to avoid false empties.
  • Derive OS and language features from the list rather than storing raw voice arrays indefinitely.
  • Cross-check the implied OS against user agent, fonts, and platform hints.
  • Treat a completely empty voice list as a signal of a headless or stripped environment, not a neutral default.

The installed voice list is a small window into the software behind the browser. Read carefully, waited for correctly, and cross-checked against everything else, it adds durable entropy and catches environments pretending to be something they are not.

Start free and see which signals your browser exposes in the live playground.

Try it free

Prynt is device intelligence with a free tier — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics, powered by a cross-site network. Start free.

Keep reading