# Manual Injection
[Overview](../README.md) . [Inspect](inspect.md) . [Capture](capture.md) . [Record](record.md)
* [Adding the Script](#adding-the-script)
* [Viewing What It Records](#viewing-what-it-records)
* [Local Capture API](#local-capture-api)
* [Loading the Script from JavaScript / TypeScript](#loading-the-script-from-javascript--typescript)
* [Inside a Web Worker](#inside-a-web-worker)
* [TypeScript Types](#typescript-types)
If the WebGPU Inspector's automatic injection isn't working to inspect the page (workers inside of
iframes can cause trouble), you can include `webgpu_inspector.js` directly in a page. This also lets
you drive capture from the page itself, with no DevTools panel and no browser extension.
## Adding the Script
Add the script tag to your page **before** any code that uses WebGPU, so the inspector can patch the
WebGPU API before it's used:
```html
```
To pin to a specific release instead of tracking `main`, replace `@main` with a version tag, for
example:
```html
```
When loaded this way, the script wraps the page's WebGPU API and exposes the inspector instance as
`webgpuInspector` on the global (i.e. `window.webgpuInspector` in a page context,
`self.webgpuInspector` in a worker context).
## Viewing What It Records
Once the inspector is loaded, you have two ways to view what it records:
1. Open the WebGPU Inspector DevTools panel from the browser extension. The DevTools panel must be
open when the page is loaded (refreshing the page may be necessary) in order to receive all of the
WebGPU data from the beginning of the page's execution.
2. Drive capture from the page itself with the [Local Capture API](#local-capture-api) — no DevTools
panel required.
## Local Capture API
The manually-injected script exposes a small JavaScript API that lets the page record one or more
frames of WebGPU activity entirely on the page side and save the result as a capture file. The file
is in the same format as **Save Capture** in the DevTools Capture panel produces, so it can be opened
with **Load Capture** in the [Capture panel](capture.md) for inspection.
```js
// 1. Turn on the local capture store. Must be called BEFORE any WebGPU object
// is created — the inspector does not retroactively replay
// descriptors for objects that existed before this call.
webgpuInspector.initialize();
// 2. Wrap one frame's worth of WebGPU work between
// begin/end. Repeat the pair as many times as you want;
// each pair appends another frame's commands (and the
// textures/buffers they reference) to the export.
webgpuInspector.beginFrameCapture();
renderOneFrame(); // your normal WebGPU rendering code
webgpuInspector.endFrameCapture();
// (optional) capture more frames
webgpuInspector.beginFrameCapture();
renderOneFrame();
webgpuInspector.endFrameCapture();
// 3. Wait for any in-flight texture/buffer readbacks,
// build the capture, and trigger a browser download.
// The filename argument is optional.
await webgpuInspector.saveCaptureData("my_capture.wgpuc");
```
`saveCaptureData()` returns a `Promise` that resolves once the download is initiated. The capture is
split into small metadata plus out-of-band payload byte blobs, and the resolved value is
`{ metadata, payloads }`:
- `metadata` — the capture object (objects, command list, validation errors). Buffer/texture bytes
appear as lightweight `{ __payloadId, __typedArray, __length, __byteLength }` references instead of
inline data.
- `payloads` — an array of `{ id, typedArray, bytes }` (the actual `Uint8Array` byte blobs).
The downloaded file is the **WGPUCAP binary container**: an ASCII header line and the metadata JSON
(readable in a text editor), followed by the raw payload bytes, so nothing is base64-inflated. It is
loadable via DevTools "Load Capture" and the plugin's `load_capture_file` tool, which also still
accept the older NDJSON and single-object `.json` captures. To serialize it yourself, use
`encodeCaptureBinaryParts({ metadata, payloads })` from `src/utils/capture_binary.js`.
After `saveCaptureData()` resolves, captured commands are cleared. You can call `beginFrameCapture()`
/ `endFrameCapture()` again to record more frames and `saveCaptureData()` again to produce another
file. Object descriptors that were created earlier remain in the store so they continue to be
available in subsequent captures.
## Loading the Script from JavaScript / TypeScript
The snippets above assume `webgpu_inspector.js` was added with a `