# WebGPU adapter info: vendor and architecture, no prompt

> WebGPU's adapter info gives any page the GPU vendor and architecture with no prompt. A WebGL renderer that says otherwise is a contradiction, not a disguise.

Source: https://mosaicbrowser.com/blog/webgpu-adapter-info

## What navigator.gpu.requestAdapter tells a page without asking

WebGPU's adapter info gives any page the GPU vendor and architecture with no prompt. A WebGL renderer that says otherwise is a contradiction, not a disguise.

![metal-3: Two routes to one GPU, read in one document](https://mosaicbrowser.com/covers/webgpu-adapter-info.webp)

Any page can call `navigator.gpu.requestAdapter()` and read the GPU's vendor and architecture from `adapter.info`, with no permission prompt. The WebGPU specification chose to expose that much on purpose: enough for a developer to work around a driver bug, coarse enough that it does not name the exact card. The side effect is a second, independent answer to "which GPU is this", beside the WebGL renderer string a page has been reading for years. When the two disagree, nothing is hidden. There are just two GPUs where there should be one.

## What WebGPU adapter info contains: vendor and architecture

The adapter info object has four strings. In Chrome on a normal machine, two of them carry something and two are empty:

| Field | Example on an Apple Silicon Mac | Example on a Windows PC |
| --- | --- | --- |
| `vendor` | `apple` | `nvidia` |
| `architecture` | `metal-3` | `ada-lovelace` |
| `device` | empty | empty |
| `description` | empty | empty |

The vendor is a short, lowercase, normalised name rather than the driver's own string. The architecture is a family: `metal-3` is shared by every Apple Silicon chip, and `ada-lovelace` by a whole generation of NVIDIA cards. The specification lets a browser leave any of these empty, or round them down further, and expects code to cope with an empty string. Chrome's default is the middle setting, vendor and family but no model.

So, on its own, WebGPU's architecture field is a weak fingerprint. A few dozen values cover most of the machines on the web. What makes it worth a page's time is what it can be compared against.

Mosaic is a desktop app

Email yourself the link and open it on your computer.

[How it works: Machines that exist](https://mosaicbrowser.com/features/real-fingerprints)

## Why requestAdapter needs no permission

There is no prompt because the information was judged coarse enough not to need one, and because a prompt before every game or 3D viewer would be absurd. The call needs a secure context and nothing else. It also works in a dedicated worker, which has its own `navigator.gpu`. That matters for anything that tries to change the answer from page JavaScript: a worker asks the browser directly, and an override installed in the page is not there.

## The WebGL renderer and WebGPU, side by side

WebGL has its own GPU answer, and it is far more specific. The unmasked renderer from `WEBGL_debug_renderer_info` is the string ANGLE builds from the driver:

```
WebGL    ANGLE (Apple, ANGLE Metal Renderer: Apple M2, Unspecified Version)
WebGPU   vendor: apple   architecture: metal-3

```

Those agree. The vendor inside the WebGL string is Apple, the WebGPU vendor is `apple`, and `metal-3` is what any Apple Silicon chip reports. Now take a browser that rewrites the WebGL string to claim an NVIDIA card and leaves WebGPU alone:

```
WebGL    ANGLE (NVIDIA, NVIDIA GeForce RTX 4060 Laptop GPU (0x000028E0) Direct3D11 vs_5_0 ps_5_0, D3D11)
WebGPU   vendor: apple   architecture: metal-3

```

No real computer produces that pair. The page did not need to know which answer was true; it only had to read both. This is the general rule behind a lot of what consistency scanners do: a changed value is not a problem by itself, but a value that disagrees with another route to the same fact is.

We measured exactly this on one of our own profiles, before the engine moved WebGPU. The WebGL renderer answered the chip the profile claimed, and `requestAdapter()` answered the host's real one, in the same document. The renderer strings themselves have to be right too, and we once had 41 of 45 Windows rows wrong, in [the renderer strings we wrote by hand](https://mosaicbrowser.com/blog/hand-written-renderer-strings). How ANGLE assembles that string is in [what ANGLE means in a WebGL renderer](https://mosaicbrowser.com/blog/angle-in-webgl-renderer).

## How a detector checks it

BrowserLeaks has a WebGPU page that prints the adapter's info, its limits and its feature list. Our detection runner reads it and passes the row only when the WebGPU vendor matches the vendor named inside the WebGL renderer, or when WebGPU is absent on a device where that is plausible. On a Mac profile it reads `apple` beside an Apple renderer, and passes.

The limits and features on that page are worth a sentence too. They come from the real adapter, and they differ between GPU vendors and generations. That is one reason a sensible profile does not claim a vendor the machine does not have.

## What Mosaic does with the adapter

Mosaic sets the WebGPU answer in the engine, not in the page. One patch in Tesseract Chrome, Mosaic's own Chromium, changes Chromium's WebGPU adapter code so that the vendor, architecture, device and description come from launch switches, and the switches come from the same hardware record as the WebGL renderer. Every record in our device catalogue carries both, and the Android records derive their WebGPU values from the phone's renderer through Dawn's own GPU table (`qualcomm` and `adreno-7xx` for an Adreno 740). Because the change is in C++, a worker reads the same answer as the page. The reasons we do this below JavaScript rather than in it are in [C++, not JavaScript](https://mosaicbrowser.com/blog/cpp-not-javascript).

Two details in that patch follow from the contradiction above. If no switch is given, the real adapter is left alone, because a half-claimed adapter (a changed vendor beside a true architecture) is the very mismatch the patch exists to remove. And the GPU vendor a profile claims stays the computer's own, so the limits and features under it are a real GPU's of the same kind. A Mac profile is an Apple GPU in both places. More on which values a page reads and how they combine is in the [browser fingerprint glossary entry](https://mosaicbrowser.com/glossary/browser-fingerprint).

## Questions

### What is in WebGPU's GPUAdapterInfo?

Four strings: vendor, architecture, device and description. Chrome fills in a short vendor name such as apple, nvidia or intel and an architecture family such as metal-3 or ada-lovelace, and normally leaves device and description empty.

### Does a page need permission to read the WebGPU adapter?

No. Calling navigator.gpu.requestAdapter() in a secure context returns an adapter without any prompt, and its info property carries the vendor and architecture.

### Can the WebGPU vendor contradict the WebGL renderer?

Yes, if only one of them is changed. WebGL's unmasked renderer names the chip, for example ANGLE with Apple M2, and WebGPU names the vendor. A browser that changes the first and not the second shows two different GPUs to one page.

### Does Mosaic change the WebGPU adapter?

Yes, inside the engine. A patch to Chromium's WebGPU adapter code sets the vendor and architecture from the same hardware record as the WebGL renderer, so both answers name the same GPU in every page, frame and worker.

## Related

[What ANGLE means in your WebGL renderer string](https://mosaicbrowser.com/blog/angle-in-webgl-renderer): ANGLE is the layer Chrome uses to turn WebGL into Direct3D, Metal or OpenGL. The backend it names in the renderer string tells a site your operating system.

[41 of 45 hand-written Windows renderer strings were wrong](https://mosaicbrowser.com/blog/hand-written-renderer-strings): Chrome's ANGLE Direct3D11 renderer string carries the GPU's PCI device id. Our hand-typed Windows rows left it out, a string no real driver produces.

[Why we change fingerprints in C++, not JavaScript](https://mosaicbrowser.com/blog/cpp-not-javascript): A JavaScript spoof is one realm deep. An iframe read the real source of 33 of our patched functions; the same values changed in C++ agree everywhere.

[Browser fingerprint: what a site can read about your machine](https://mosaicbrowser.com/glossary/browser-fingerprint): A browser fingerprint is the set of values a site reads about your browser and computer, which together recognize you without cookies. What goes into one.

[Why every Mac's Chrome says Mac OS X 10_15_7](https://mosaicbrowser.com/blog/mac-os-x-10-15-7): Chrome froze the macOS version in its User-Agent, so every Mac claims 10.15.7. The real one is in Sec-CH-UA-Platform-Version, a hint sites must ask for.

[Why the User-Agent says Windows 10 on Windows 11](https://mosaicbrowser.com/blog/windows-11-user-agent-windows-10): Windows 11 and 10 both send Windows NT 10.0 in the User-Agent. Only the platformVersion client hint, 13 or higher, says Windows 11.

[Why Chrome's User-Agent says 0.0.0](https://mosaicbrowser.com/blog/chrome-user-agent-0-0-0): Chrome zeroes everything after the major, so the User-Agent says 0.0.0 and the build moves to Sec-CH-UA-Full-Version-List. A real build in the UA is a tell.

[Privacy Sandbox is retired, and its APIs are a version tell](https://mosaicbrowser.com/blog/privacy-sandbox-apis-removed): Chrome is removing Topics and Protected Audience release by release, so whether runAdAuction exists tells a page which Chrome you really are.

## Mosaic, on your own computer

The browser this blog is about: its own Chromium, fingerprints from real machines and a proxy exit per profile. Free holds 3 profiles. Pro is $49 a month for any number.

Mosaic is a desktop app

Email yourself the link and open it on your computer.
