People who run fraud at scale don’t buy a laptop per identity. They run many browser profiles inside virtual machines, cloned from a template, each with a fresh disk and a different IP. Spinning up another VM is cheaper than any other way of looking like a new device, which is why VM detection keeps showing up in fraud tooling.
It is also a signal that is easy to over-use. Plenty of real people browse from virtual machines. This post covers what the browser can reveal about a VM, how Prynt’s virtualMachine signal works, and how to use it without punishing developers and corporate users.
What gives a VM away in the browser
JavaScript can’t ask “am I in a VM?” directly. It can read properties of the environment that VMs tend to get wrong or leave generic.
The graphics renderer
This is the strongest hint. Most VMs don’t pass a real GPU through to the guest. The browser falls back to a software rasteriser or a virtual display adapter, and WebGL tells you which:
const gl = document.createElement('canvas').getContext('webgl');
const ext = gl && gl.getExtension('WEBGL_debug_renderer_info');
const renderer = ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : null;
// e.g. "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero)), SwiftShader driver)"
// "llvmpipe (LLVM 15.0.7, 256 bits)"
// "VMware SVGA 3D"
Strings that commonly indicate virtualisation or software rendering include:
| Renderer contains | Usually means |
|---|---|
SwiftShader | Chrome’s software renderer: headless, no GPU, or GPU blocklisted |
llvmpipe, softpipe, Mesa offscreen | Mesa software rendering, common on Linux VMs and servers |
VirtualBox, VMware, Parallels | The hypervisor’s virtual display adapter |
Microsoft Basic Render | Windows with no proper GPU driver, typical of VMs and RDP sessions |
Some browsers now return a coarser or generic string to reduce fingerprinting, so a missing or vague renderer is not by itself evidence of anything. The WebGL fingerprinting guide covers what different browsers expose.
Hardware values that don’t add up
VMs are configured by hand or from templates, which produces round, low or inconsistent numbers:
navigator.hardwareConcurrencyof 1 or 2 on a desktop-class user agent.navigator.deviceMemoryat the low end alongside a desktop OS.- Many sessions from “different” devices with identical core count, memory, renderer and screen size.
Each of these is weak alone; real budget laptops have two cores too. They become useful in combination and across a population. See hardware concurrency and device memory signals for how much weight they deserve.
Screen and media hints
Default VM resolutions such as 800×600 or 1024×768, a colour depth that differs from the host, no touch support on an OS that usually has it, and missing media devices are all common. Again: hints, not proof.
Rendering output itself
Software renderers draw canvas and WebGL scenes slightly differently from GPU drivers. That makes their fingerprint output distinct, and it also means many VMs from one template produce identical rendering. Identical outputs across “different” visitors are a clustering signal, not a VM signal, but in practice they travel together.
The virtualMachine signal in Prynt
Prynt reports this as the virtualMachine Smart Signal on the event your server fetches:
const ev = await prynt.getEvent(requestId);
ev.smartSignals.virtualMachine;
// { result: true, renderer: "llvmpipe (LLVM 15.0.7, 256 bits)" }
The current browser check matches the WebGL renderer against known software and virtual adapters, the families in the table above. When it fires, the event carries the VIRTUAL_MACHINE reason code and the signal adds to the riskScore, but on its own it is not weighted to produce a block. That is deliberate.
On mobile, the Android SDK collects emulator tells (QEMU and goldfish images, Genymotion, missing sensors and similar), and the server reports the result under emulator, which also feeds virtualMachine, so a single rule covers both web and app.
You can use the signal in a console rule (virtualMachine eq true). Each rule tests one field, so combinations with other evidence belong either in the risk score, where the VM weight adds to whatever else fired, or in your own server code. Risk weights are editable per account if VMs are more or less meaningful for your traffic.
Weight, not verdict
Who runs a browser in a VM?
- Developers and QA engineers testing across operating systems.
- Employees on virtual desktop infrastructure, a very common corporate setup.
- Security researchers and privacy-conscious users who isolate browsing.
- Cloud-hosted browsers and remote-desktop services.
- And fraud operators running many profiles.
If you block every VM, you block the first four groups to catch the last one, and the B2B ones are often your best customers. The useful question isn’t “is this a VM?” but “is this a VM and something else?”
Combinations that do justify action:
| Combination | Likely story |
|---|---|
VIRTUAL_MACHINE + MULTI_ACCOUNT | Profiles in VMs opening repeat accounts |
VIRTUAL_MACHINE + DATACENTER | Browser in a cloud VM, uncommon for consumers |
VIRTUAL_MACHINE + BOT or TLS_AUTOMATION | Automated browser on a server |
VIRTUAL_MACHINE + TAMPERING | Anti-detect setup spoofing other values |
VIRTUAL_MACHINE alone on a corporate ASN | Probably a virtual desktop; leave it alone |
A practical rule set: tag VM sessions for visibility, step up (verify email or phone, or a proof-of-work challenge) when VM combines with account multiplicity, and block only when VM combines with automation. In Prynt’s console that starts with a tag rule on virtualMachine eq true. Because each console rule tests a single field, do the combinations on your server: read ev.smartSignals.virtualMachine.result next to ev.accountsOnDevice.count and the reason codes, and step up or block from there.
Where VMs fit in the bigger picture
VMs are one tool in a fraud operator’s kit, alongside anti-detect browsers, residential proxies and, on mobile, emulator farms and real-device farms. Each tool beats one kind of check. A good detection stack doesn’t try to win on any single signal; it looks for the combination that a legitimate user rarely produces.
If VMs are showing up as part of a larger operation, device farm detection covers the physical-device side, and fraud rings explains how linked devices and accounts surface as clusters. The full set of signals is on the device fingerprinting page.
Start by tagging VM sessions for a couple of weeks and looking at what else they have in common. You’ll probably find most of them are harmless, and the few that aren’t will be obvious from the company they keep.
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.