Skip to content

Capture

Joël Deffner edited this page Sep 3, 2026 · 1 revision

Capture

Since v0.5.0. steam.capture is the curated layer over ISteamScreenshots: take screenshots, add existing images to the user's Steam screenshot library, tag them, and hook Steam's own screenshot key. It is called capture because the generated ISteamScreenshots class already owns steam.screenshots.

Nothing here is async. Every call goes to the local Steam client and answers at once; the finished file arrives later on onReady.

A screenshot lands durably in the user's Steam library. addFromFile, writeRgb and addVr are not reversible from this API, and there is no delete call, so the user has to remove one by hand. Treat them the way you would treat a post.

The Capture instance is created lazily and cached on the Steam object.

trigger

trigger(): void

Asks Steam to take a screenshot of the game window.

What happens next depends on hook. With hooking off, Steam takes the screenshot itself and fires ScreenshotReady_t. With hooking on, Steam fires ScreenshotRequested_t instead and expects the game to write the image with writeRgb or addFromFile.

import { init } from 'steamwand.js';

const steam = init({ appId: 480 });
const off = steam.capture.onReady((s) => console.log(s.handle, s.result));
steam.capture.trigger();
// later: off(); steam.close();

addFromFile

addFromFile(path: string, width: number, height: number): number

Adds an image file on disk to the library and returns its screenshot handle. Steam copies the file, so it may be deleted afterwards, and Steam builds the thumbnail itself.

The image must be a JPEG, TGA or PNG, at most 16000 pixels per side and within a 4:1 aspect ratio. path is absolute.

const handle = steam.capture.addFromFile('C:/shots/win.png', 1920, 1080);
steam.capture.setLocation(handle, 'Final boss');

Throws Error: steamwand: AddScreenshotToLibrary rejected '<path>' (<w>x<h>) when Steam refuses the image, usually a wrong path or a size outside those limits.

writeRgb

writeRgb(rgb: Buffer, width: number, height: number): number

Writes raw RGB pixels to the library and returns the screenshot handle. The buffer holds one byte per channel, three channels per pixel, rows top to bottom with no padding, which is exactly width * height * 3 bytes.

The length is checked here before the call, because a short buffer would let Steam read past its end and crash the process rather than throw.

Throws Error: steamwand: writeRgb needs <n> bytes for <w>x<h>, got <m> on a length mismatch, and Error: steamwand: WriteScreenshot rejected a <w>x<h> image when Steam refuses it.

addVr

addVr(type: number, path: string, vrPath: string): number

Adds a VR screenshot and returns its handle. path is the flat 2D image shown in the library, vrPath the VR data whose format type names: EVRScreenshotType 1 mono, 2 stereo, 3 mono cubemap, 4 mono panorama, 5 stereo panorama. Valve takes no size here, because the dimensions come from the files themselves.

Throws Error: steamwand: AddVRScreenshotToLibrary rejected '<path>' / '<vrPath>'.

setLocation

setLocation(handle: number, location: string): void

Sets the place a screenshot was taken in, shown next to it in the library. location is free text of at most 255 UTF-8 bytes, for example a level name. The handle comes from addFromFile, writeRgb, addVr or onReady.

Throws Error: steamwand: SetLocation returned false (...) for an unknown handle or text over the cap.

tagUser

tagUser(handle: number, steamId: bigint): void

Tags a user who appears in a screenshot. Steam allows at most 32 tags per screenshot, users and workshop items together.

Throws Error: steamwand: TagUser returned false (...) for an unknown handle or a screenshot that is already full.

tagPublishedFile

tagPublishedFile(handle: number, fileId: bigint): void

Tags a workshop item that appears in a screenshot, against the same limit of 32. fileId is a published file id, so a bigint.

hook

hook(enabled: boolean): void

Takes Steam's screenshot key over, or hands it back. While hooked, the key fires ScreenshotRequested_t instead of writing a file, so the game renders its own image and calls writeRgb or addFromFile. Steam forgets the hook when the app exits.

isHooked

isHooked(): boolean

Whether the screenshot key is currently hooked by this app.

onRequested

onRequested(listener: () => void): () => void

Subscribes to the hooked screenshot key and returns an unsubscribe function. Only fires while hook(true) is in effect. The callback carries nothing: it means the user pressed the key and the app should write an image now.

steam.capture.hook(true);
const off = steam.capture.onRequested(() => {
  steam.capture.writeRgb(renderToRgb(), 1920, 1080);
});
// later: off(); steam.capture.hook(false);

onReady

onReady(listener: (screenshot: ScreenshotReady) => void): () => void

Subscribes to finished screenshots and returns an unsubscribe function. It fires both for screenshots Steam took itself and for the ones this app added, which is where the handle for setLocation and the tag calls comes from when Steam took the shot.

Types

ScreenshotReady

Handed to an onReady listener.

Field Type Meaning
handle number Handle of the screenshot Steam just wrote.
result number The EResult Steam finished with. k_EResultOK means the file is in the library.

result is a field, not a thrown error: a failed screenshot arrives through the same listener as a successful one, so check it before using the handle.

Errors

Shape When
Error: steamwand: AddScreenshotToLibrary rejected '<path>' (<w>x<h>) Steam returned the invalid handle for a file add. Wrong path, unsupported format, or a size outside Steam's limits.
Error: steamwand: WriteScreenshot rejected a <w>x<h> image The same for raw pixels.
Error: steamwand: AddVRScreenshotToLibrary rejected '<path>' / '<vrPath>' The same for a VR pair.
Error: steamwand: writeRgb needs <n> bytes for <w>x<h>, got <m> The buffer length does not match the size. Checked before the call, so Steam never sees the short buffer.
Error: steamwand: <call> returned false (invalid handle or argument?) SetLocation, TagUser or TagPublishedFile was refused: unknown handle, text over 255 bytes, or 32 tags already set.

No SteamResultError here. The one EResult this interface produces arrives inside onReady instead of being thrown.

What this layer does not do

ISteamScreenshots is small and this layer covers all of it except SetLocation's VR-only companion. What is left on the raw generated steam.screenshots:

  • AddScreenshotToLibrary with an explicit thumbnail path. This layer always passes NULL so Steam builds one, which is what Valve recommends.

Everything else on the interface is wrapped above.

Next: Workshop, which takes the same screenshot files as item previews.

Clone this wiki locally