← back to blog

Signals that say you are inside a virtual machine

Run enough browser profiles across enough proxies and you start noticing a pattern: profiles that live on virtual machines get flagged more often than profiles that live on real hardware, even when the proxy, the cookies, and the fingerprint spoofing all look fine on paper. That’s not bad luck. Sites have gotten good at asking a browser “are you actually running on physical silicon, or on top of a hypervisor,” and the browser answers whether you want it to or not. Here’s what it’s actually reading.

Why virtual machines look different to begin with

A VM shares the host’s CPU cores, but it virtualizes almost everything else: the GPU, the network adapter, the clock, sometimes the sound card. Virtualization layers like VMware, VirtualBox, Hyper-V, and QEMU/KVM insert their own drivers to make that sharing possible. Those drivers have names, version strings, and behavior that don’t exist on consumer hardware. A browser running inside that VM inherits all of it, and a lot of that information is exposed to JavaScript through completely normal, non-exotic web APIs. No exploit needed. It’s just reading what the OS reports.

The GPU gives it away first

WebGL is the biggest leak. Call getParameter on the UNMASKED_RENDERER_WEBGL extension and you get back a string describing the actual graphics driver in use. On real hardware that string looks like an actual GPU model: an Nvidia RTX card, an Intel integrated chip, an AMD Radeon part. On a VM, it often comes back as something like “VMware SVGA 3D,” “VirtualBox Graphics Adapter,” “Microsoft Basic Render Driver,” or a software rasterizer like “llvmpipe” or “SwiftShader” if hardware passthrough isn’t configured. Any of those strings is close to a red flag by itself, because almost no real consumer ever browses the web on that hardware. Detection scripts don’t need to be clever here, they just need a lookup table of known virtual GPU signatures, and that table is not hard to build.

Canvas fingerprinting compounds this. The way a canvas element renders text and shapes depends on the GPU, the driver, and font rasterization, all of which differ on a virtualized graphics stack versus real hardware. Two machines with identical OS and browser versions will still produce slightly different canvas hashes if one is virtualized and one isn’t, because the actual pixel-level rendering path is different underneath.

CPU core count and the math that doesn’t add up

navigator.hardwareConcurrency reports the number of logical CPU cores the browser sees. VMs are frequently provisioned with round, deliberate numbers: 2, 4, 8 vCPUs, because that’s how cloud billing tiers work. Real consumer laptops and desktops have a much messier spread, and more importantly, the core count needs to be consistent with everything else the browser reports: the GPU tier, the screen resolution, the memory estimate from navigator.deviceMemory. A profile claiming to be a high-end gaming rig with only 2 logical cores and a software-rendered GPU doesn’t hold together, and fingerprinting scripts specifically check for that kind of internal inconsistency rather than any single value in isolation.

Timing and jitter give away the hypervisor

This is the harder one to fake. Virtualized CPUs handle timing instructions differently than bare metal, because the hypervisor has to intercept and emulate certain low-level operations. Running a tight timing loop with performance.now() and measuring the variance between iterations produces a different statistical signature on a VM than on physical hardware, because context switches into the hypervisor introduce jitter that isn’t there on bare metal. Detection scripts that run these micro-benchmarks aren’t reading a flag that says “virtual machine equals true,” they’re doing statistical analysis on timing noise, which makes it much harder to spoof with a simple override, since you’d have to fake the actual physics of instruction execution, not just a reported value.

Mouse and scroll behavior gets scrutinized the same way. Real human input has irregular acceleration, small overshoot and correction, and inconsistent timing between events. Automated or VM-driven input, especially anything programmatically generated rather than physically moved, tends to be too smooth or too mathematically regular. This isn’t strictly a “virtual machine” signal on its own, but it’s often bundled into the same risk score, because VMs are disproportionately used for automation.

Network and hardware ID leaks

WebRTC can leak local IP addresses even through a proxy, and VM network adapters often sit behind their own NAT layer with a locally-assigned IP that has a distinctive private-range pattern depending on the hypervisor’s default networking mode. On top of that, the network adapter’s MAC address has a vendor prefix (the OUI), and VMware, VirtualBox, and other hypervisors register their own OUI blocks. A MAC address starting with certain VMware or VirtualBox prefixes is a direct tell, though this one is mostly visible to native apps and some plugins rather than plain JavaScript, since browsers don’t expose raw MAC addresses to web pages.

The sensors and APIs that just aren’t there

Real phones and laptops carry a battery, an accelerometer, ambient light sensors, sometimes a gyroscope, and the Battery Status API or device orientation events will report real, fluctuating values from them. A desktop VM has none of that hardware, so those APIs either don’t exist, return null, or report static placeholder values that never change across a session. A profile pretending to be a mobile device that never once reports a battery level change, or a “laptop” whose battery API is simply absent, is inconsistent in a way that’s easy to check for.

Font enumeration works similarly. The set of fonts installed reflects the OS image, and a fresh VM template tends to have a narrower, more uniform font list than a real machine that’s accumulated software over years of use. A machine with a suspiciously clean, default font list is one more small signal added to the pile.

What anti-detect browsers actually do here

Tools like Multilogin, GoLogin, Kameleo, AdsPower, and Dolphin Anty exist specifically to intercept these API calls and return consistent, plausible values instead of the raw VM ones: a real GPU renderer string, a matching core count, a font list that looks lived-in, canvas noise that’s stable across a session but varies between profiles. That’s a legitimate and useful function if you’re managing many separate browser profiles for legitimate multi-account work, and in my own testing across several of these tools, the better ones do keep the values internally consistent with each other rather than just randomizing one field at a time, which is the part that actually matters.

What none of them do, and what none of them claim to do if you read past the marketing page, is fix the timing-based signals. Spoofing a GPU string is a matter of overriding a JavaScript return value. Spoofing the actual instruction-level timing behavior of bare-metal versus virtualized execution is a much deeper problem, closer to hypervisor engineering than browser fingerprinting, and it’s not something a browser extension or Chromium fork can fully solve. That’s why running anti-detect profiles on real physical hardware, or on dedicated hardware-passthrough setups rather than shared cloud VMs, tends to hold up better in practice than running the same tool on a generic cloud instance. It’s not that the anti-detect browser is worse in that scenario, it’s that the underlying host is handing over signals the browser layer can’t fully paper over.

The takeaway

None of this means every VM gets caught or every real machine sails through. Detection systems combine dozens of these signals into a risk score, not a single hard yes/no check, and any one inconsistency rarely triggers a ban on its own. But if you’re running multi-account work at any real scale, it’s worth knowing that the hardware underneath your browser profile is part of the fingerprint, not separate from it. The proxy and the cookies are the part everyone thinks about. The GPU string and the timing jitter are the part that quietly does you in.

If you want more of this kind of hands-on testing, breakdowns of specific anti-detect tools, and how browser fingerprinting actually works under the hood, check out the rest of the site here.

Get new guides and videos first — join the Telegram channel.

need infra for this today?