# webgl2_limits

> 29 WebGL 2 limits and the WebGL 2 extension list, from a 1x1 WebGL 2 context released at once, as a digest. Reported, not in either id.

Source: https://whiskerjs.com/signals/webgl2-limits/ (last updated 2026-10-27)

**webgl2_limits at a glance (from the library code, signalsVersion 14)**

| Field | Value |
| --- | --- |
| Component name | `webgl2_limits` |
| In the visitorId | no (reported, kept out of both ids) |
| structuredId group | none |
| Hashing | always a digest (first 128 bits of SHA-256) |
| Excluded under | Brave (brave_farbling) |
| Inner timeout | 1000 ms |
| Added in | [signalsVersion 11](https://whiskerjs.com/whats-new/) |
| Collector revision | [1](https://whiskerjs.com/docs/api/#component) (reported as `revision` with every result) |

> **In plain words:**
>
> WebGL 2 is the newer version of the graphics interface that web pages use for 3D. Each graphics chip, driver and browser allows different maximum sizes: how big a 3D texture may be, how many render targets, how many samples for smooth edges. WhiskerJS asks for those limits and the list of WebGL 2 extensions and turns them into one short code.

## What it reads

From a 1x1 canvas with a `webgl2` context of its own (no antialiasing):

- `getParameter()` of 29 WebGL 2 limits, by their names on the context: `MAX_3D_TEXTURE_SIZE`, `MAX_ARRAY_TEXTURE_LAYERS`, `MAX_CLIENT_WAIT_TIMEOUT_WEBGL`, `MAX_COLOR_ATTACHMENTS`, `MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS`, `MAX_COMBINED_UNIFORM_BLOCKS`, `MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS`, `MAX_DRAW_BUFFERS`, `MAX_ELEMENT_INDEX`, `MAX_ELEMENTS_INDICES`, `MAX_ELEMENTS_VERTICES`, `MAX_FRAGMENT_INPUT_COMPONENTS`, `MAX_FRAGMENT_UNIFORM_BLOCKS`, `MAX_FRAGMENT_UNIFORM_COMPONENTS`, `MAX_PROGRAM_TEXEL_OFFSET`, `MAX_SAMPLES`, `MAX_SERVER_WAIT_TIMEOUT`, `MAX_TEXTURE_LOD_BIAS`, the three transform feedback limits, `MAX_UNIFORM_BLOCK_SIZE`, `MAX_UNIFORM_BUFFER_BINDINGS`, `MAX_VARYING_COMPONENTS`, `MAX_VERTEX_OUTPUT_COMPONENTS`, `MAX_VERTEX_UNIFORM_BLOCKS`, `MAX_VERTEX_UNIFORM_COMPONENTS`, `MIN_PROGRAM_TEXEL_OFFSET` and `UNIFORM_BUFFER_OFFSET_ALIGNMENT`.
- `getSupportedExtensions()`, sorted.

No drawing and no pixel readback. Since signalsVersion 13 (library PR #34) it also reads the context’s renderer string the way [`webgl_renderer`](https://whiskerjs.com/signals/webgl-renderer/) does (outside Firefox through the `WEBGL_debug_renderer_info` extension). That string is not reported and does not change the value: it serves only the [`gpu_inconsistent`](https://whiskerjs.com/docs/integrity/#gpu_inconsistent) check, which fires when the WebGL 1 and WebGL 2 renderers differ.

## How the technique works

The values are written as `NAME=value;...;ext=a,b,c` and always hashed. The context is released before the collector returns: with `WEBGL_lose_context` in Chromium and WebKit, and in Firefox by shrinking the canvas to 0x0, because Firefox prints a console line for every lost context. It is separate from the shared WebGL 1 context of the other WebGL components, so it does not change them.

## Why it helps

WebGL 2 limits follow the GPU, the driver and the browser’s graphics layer (for example ANGLE on Chromium), and the extension list differs between engines and drivers. It adds detail to the `gpu` picture without any rendering, so canvas and readback noise cannot touch it.

## Stability

Expected to be stable on one device until a driver or browser update changes a limit or an extension. It is reported outside both ids until measurement confirms that; it is a candidate for the `gpu` group. Added in library PR #29 (2026-10-27) at signalsVersion 11: it is outside both ids, so adding it changed no id and needed no version bump.

## Browser support and what blocks it

- In the hosted CI runs of PR #29 (Linux, no GPU) Chromium 153, Chrome 155 and WebKit reported `ok`, the same in every collection and on both runners; headless Firefox reported `unavailable` / `no_context` (no WebGL 2 context without a GPU there).
- `unavailable` / `no_context` wherever WebGL 2 is off or blocked (some enterprise policies, `webgl.disabled` in Firefox).
- [Brave](https://whiskerjs.com/browsers/brave/): `excluded` / `brave_farbling`, because Brave farbles WebGL parameters.

## Privacy

The limits describe the graphics stack, not the user. The value leaves the library only as a 32-character digest. No prompt, no request.

## How WhiskerJS handles noise and failures

| Status | ruleId | When |
| --- | --- | --- |
| `ok` |   | a digest |
| `unavailable` | `no_api` | no canvas `getContext` |
| `unavailable` | `no_document` | no `document` |
| `unavailable` | `no_context` | no WebGL 2 context |
| `unavailable` | `no_digest` | no Web Crypto |
| `blocked` | `threw`, `security_error` | a read threw |
| `excluded` | `brave_farbling`, `caller_excluded` | exclusion table or your `exclude` list |
| `timed_out` | `timeout`, `aborted` | budget or abort |

## Example value

```json
"webgl2_limits": { "status": "ok", "value": "3e8b51c07d2a9f46b1c5e0d83a7f6b92", "hashed": true, "durationMs": 1.8, "revision": 1 }
```

## Questions and answers

### Does webgl2_limits draw anything?

No. It only calls getParameter for 29 limits (and, since signalsVersion 13, for the renderer name, which is not reported) and getSupportedExtensions. Nothing is drawn and no pixels are read, so canvas noise does not affect it.

### Why is it excluded in Brave?

Brave farbles WebGL parameters per site and session, so the value would change between sessions. The exclusion table removes it there, as it does for webgl_params.

## Related pages

- [webgl_params](https://whiskerjs.com/signals/webgl-params/): The WebGL 1 parameters, in the id.
- [webgpu](https://whiskerjs.com/signals/webgpu/): The WebGPU adapter, in the id.
- [webgpu_limits](https://whiskerjs.com/signals/webgpu-limits/): Every WebGPU adapter limit.
