← Chrome 147 reference
v147 · web api · origin trial
WebNN
The Web Neural Network API lets web apps and frameworks run neural network inference against the device's hardware accelerators — CPU, GPU, or a dedicated NPU — without tying the code to any platform-specific backend. navigator.ml is the entry point; the rest is a graph builder API that compiles to whatever hardware is available.
Experimental
WebNN is in an origin trial phase. The API surface has evolved substantially through 2026 (over 100 spec changes since April 2024). Field names, operator lists, and the MLTensor buffer-sharing API are still stabilising. Check the spec before shipping anything.
why it exists
Neural network inference on the web has historically meant one of two things: a heavyweight WASM runtime that can't touch the GPU, or WebGL/WebGPU compute shaders that require hand-rolling matrix math and shader strings. Neither path can reach a device's Neural Processing Unit. WebNN is a hardware-agnostic graph API — the browser maps it onto Windows DirectML, macOS ML Compute, Android NNAPI, or whatever native stack is present. The Chromium implementation is a three-way collaboration between Google, Intel, and Microsoft; Edge ships WebNN at the same time as Chrome from the same code.
Source: chromestatus motivation and the WebNN explainer §1 ("Background").
shape of the API
Four core interfaces; the workflow is always: create a context → build a graph → compile → compute.
navigator.ml → ML
navigator.ml.createContext(options?) | Returns Promise<MLContext>. Options can specify a device preference ("cpu", "gpu", "npu") and a power preference ("high-performance", "low-power", "default"). |
MLContext
compute(graph, inputs, outputs) | Runs a compiled MLGraph. inputs and outputs are plain objects keyed by operand name; values are ArrayBufferView. Returns Promise<MLComputeResult>. |
createTensor(descriptor, writable?, readable?) | Allocates a device-side MLTensor for zero-copy buffer sharing between the graph and WebGPU (if available). |
dispatch(graph, inputs, outputs) | Fire-and-forget version of compute for MLTensor-backed buffers; does not transfer data back to JS until readTensor() is called. |
MLGraphBuilder
new MLGraphBuilder(context) | Constructor. Binds the builder to a context. |
input(name, descriptor) | Declares an input operand. Descriptor: { dataType, dimensions }. |
constant(descriptor, data) | Embeds a constant (e.g. model weights) into the graph at build time. |
| Operators | add, mul, matMul, conv2d, relu, sigmoid, softmax, transpose, reshape, gather, layerNormalization, gru, lstm, and ~70 more. Each returns an MLOperand. |
build(outputs) | Compiles the graph. outputs is an object mapping output names to MLOperand. Returns Promise<MLGraph>. |
MLGraph
Opaque compiled representation. Pass to context.compute() or context.dispatch(). Immutable after construction. | |
Source: WebNN explainer §3–§6 and webnn.io API reference. Operator count as of January 2026 Candidate Recommendation snapshot.
example: add two matrices
const context = await navigator.ml.createContext({ deviceType: 'gpu' });
const builder = new MLGraphBuilder(context);
// Declare two 2×2 float32 inputs
const A = builder.input('A', { dataType: 'float32', dimensions: [2, 2] });
const B = builder.input('B', { dataType: 'float32', dimensions: [2, 2] });
// Build a computation: C = A + B
const C = builder.add(A, B);
const graph = await builder.build({ C });
// Run inference
const inputs = {
A: new Float32Array([1, 2, 3, 4]),
B: new Float32Array([5, 6, 7, 8]),
};
const outputs = { C: new Float32Array(4) };
await context.compute(graph, inputs, outputs);
// outputs.C → [6, 8, 10, 12]
example: softmax classifier (weights as constants)
const context = await navigator.ml.createContext();
const builder = new MLGraphBuilder(context);
// Embed weights and bias as graph constants
const W = builder.constant(
{ dataType: 'float32', dimensions: [4, 128] },
Float32Array.from(modelWeights) // pre-loaded Uint8Array / Float32Array
);
const b = builder.constant(
{ dataType: 'float32', dimensions: [4] },
Float32Array.from(modelBias)
);
// Single input: a 128-d feature vector
const x = builder.input('x', { dataType: 'float32', dimensions: [128] });
// Linear layer + softmax
const logits = builder.add(builder.matMul(x, builder.transpose(W)), b);
const probs = builder.softmax(logits, 0);
const graph = await builder.build({ probs });
// Reuse the graph for every prediction — graph compilation is the slow step
async function predict(featureVector) {
const out = { probs: new Float32Array(4) };
await context.compute(graph, { x: featureVector }, out);
return out.probs;
}
browser support
| Chrome | Origin trial in 147 (Google + Intel + Microsoft collaboration) |
| Edge | Launches alongside Chrome (same Chromium code) |
| Firefox | Positive — Mozilla standards position #1215 |
| Safari | No signal (Apple active in W3C WebML Working Group) |
Source: chromestatus browser views and Mozilla standards-positions issue #1215, May 2026.