sandbox_shot
Takes a screenshot of the box's display, of its front window, of a URL opened in a fresh browser or of a tab already open in a browser on the box, captures several pages at once, or records the display to mp4.
| Input | Output |
|---|---|
id, target (screen, window, url or tab), url, urls, width, height, deviceScaleFactor, mobile, fullPage, tab, port, reset, waitFor, stableMs, record (start or stop) |
the screenshot inline plus url (valid 1 hour; https://api.parallelsandbox.com/v1/files/…, which redirects to storage when opened), bytes, expiresAt, capturedAt, path, and as they apply window, windows, clipped, viewport, tab, waitFor, stable, loadError, pageErrors, takeover; with urls, no picture but files[] (each page's url, path, bytes, capturedAt, and pageErrors when the page reported any); record: "stop" returns the mp4's url (the same kind, valid 1 hour) |
- No
record: a screenshot, returned inline and as a URL valid for one hour, withcapturedAt, the moment it was taken.pathis a copy of it in the box, under/work/.sbx/shots/(relative to/work; the newest 100 are kept): fetch it withsandbox_pullorsandbox_getto keep the picture itself or hand it on. - While a person has taken the box over,
target: "screen","window"and"url"still capture, and the result carriestakeover: true: the picture is what they are looking at.target: "tab"waits, likesandbox_exec, because it changes the tab they may be using. target: "screen"(default) captures the virtual display, 390 × 844 portrait unless the box was started withorientation: "landscape"(1280 × 800).target: "window"captures only the front window, without the desktop, and addswindowto the result: itsx,y,width,heighton the screen (such as"100,80,900,600"), so add x and y to coordinates on the image before clicking; a window larger than the screen is cut to the part on it, andclippedsays so.windowslists every window on the screen, the captured one first, each withid,name,x,y,width,heightand thepidthat opened it when the program reports one: a window stays until its program ends, and this is how to check that none of yours is left before you finish (sandbox_procsstopends one you started withbackground: true;xdotool windowkill <id>closes any one). With either,stableMs(100 to 10000) captures once the picture has not changed for that long, so a page transition or an animation is not caught half way; it gives up after 20 seconds and returns the last frame withstable.settled: false.target: "url"opensurlin a fresh, signed-out headless Chromium and captures it.widthandheightset the viewport in CSS pixels (by default the box's screen size: 390 × 844 portrait, 1280 × 800 landscape;widthalone keeps the screen's height), and the page lays out at exactly that width, below Chromium's 500-pixel window minimum too: this is how to look at a phone or tablet layout (width: 390, height: 844).deviceScaleFactor(0.5 to 4, such as 3 for an iPhone) makes the image that many times the viewport, andmobile: trueemulates a phone with touch, so nothing hovers and a page without<meta name=viewport>lays out 980 pixels wide, as on a real phone.fullPage: truecaptures the whole page rather than the viewport (heightis then ignored). A page that does not load comes back withloadError.urlscaptures several pages in one call (pages of the same size share one browser): the pictures are not in the result but written in the box under/work/.sbx/shots/, andfiles[]lists each page'surl,path(relative to/work),bytesandcapturedAt; fetch the ones you want withsandbox_get(pathstakes several). Such a batch is recorded as one step (summarylike2 urls) with no pictures: the person does not see them in the app,/mediadoes not have them, and they go with/workwhen the box is stopped.target: "tab"captures a page already open in a browser on the box, still signed in, as it is: it does not scroll or move the pointer, so hover states stay in the picture. That browser must have been started with--remote-debugging-port=9222(Electron takes the same flag);portnames its port when several browsers on the box have one, and a browser that is still starting is waited for, up to 45 seconds, so nosleepis needed after launching it.tabpicks the tab by its id or a piece of its URL or title (default: the tab whose viewport is held, else the most recently used one), and the result'stabsays which was captured.widthgives that tab a viewport that wide, withheight(default: the window's own height),deviceScaleFactorandmobileas above, and the box keeps it untilreset: true, the tab closes or the browser exits, so a phone layout holds while you keep clicking and typing in the tab (anEmulation.setDeviceMetricsOverridefrom your own CDP script is undone when its connection closes). Each call withwidth,height,deviceScaleFactorormobilereplaces the whole emulated viewport, and one tab is held at a time;viewportin the result is what the page saw.waitFor, withtarget: "url"or"tab": capture once this CSS selector matches a visible element, or, prefixed withjs:, once this JavaScript expression is truthy (it may await). It waits up to 30 seconds; if the condition never holds you still get the screenshot, withwaitFor.met: false, and a condition that cannot be evaluated is an error.pageErrors, withtarget: "url"or"tab", is what the page itself reported:console(console.error, failedconsole.assert, uncaught exceptions with their script and line, and what the browser blocked, such as a Content Security Policy violation) andfailedRequests(each resource that did not load, its URL followed by why:net::ERR_NAME_NOT_RESOLVED,the server responded with a status of 404 (Not Found)). The first 10 of each are listed, each cut to 300 characters, andmorecounts the rest; a page that reported nothing has nopageErrors. It covers the page now shown, from its last navigation: fortarget: "tab"that includes what happened before the call, so a page stuck on its loading screen shows why.
sandbox_exec { "id": "<id>", "cmd": "chromium --no-sandbox --remote-debugging-port=9222 --user-data-dir=/tmp/chrome http://localhost:5173/", "background": true, "note": "open the app in a browser on the box" }
sandbox_shot { "id": "<id>", "target": "tab", "width": 390, "height": 844, "mobile": true, "deviceScaleFactor": 3, "waitFor": "nav [aria-label='Menu']" }
sandbox_shot { "id": "<id>", "target": "tab", "waitFor": "js:document.querySelectorAll('.order').length > 0" }
sandbox_shot { "id": "<id>", "target": "tab", "reset": true }
- To keep a page on the box's screen yourself (a Chromium you keep driving), start Chromium with the flags for the screen's orientation; see Browsers on the box's screen in
sandbox_exec. record: "start"begins recording the display to mp4;record: "stop"ends it and returns its download URL, valid for an hour. A recording keeps the box from freezing, but only until a full hour has passed since the box's last use (the end of a tool call that acts on it, or a wake; see Box states), the same point a background command keeps it awake until; if the last use was a foreground command, that hour counts from when the command ended. How long the recording has run does not matter. After that, once nothing else keeps the box awake (a foreground command, a takeover and the rest in Box states), ParallelSandbox stops the recording without uploading it, and the box freezes as usual; the mp4 stays in the box at/work/.sbx/rec/rec-<unix time>.mp4; fetch it withsandbox_get, which wakes the box itself if it is frozen. A recording stopped automatically does not become a step: neither the app nor/mediashows it, and unless you fetch it, it goes with/workwhen the box is stopped. A copy fetched withsandbox_getis a temporary transfer, automatically removed after about one day and not billed as stored files (see Credits). Download it before stopping the box; after the box stops, a new download URL cannot be requested.- One frame out of a recording, as a single image:
ffmpeg -ss 5 -i in.mp4 -frames:v 1 -update 1 out.png(-update 1writes one file instead of expecting a numbered pattern such asout%03d.png). ffmpeg is installed in the box. - Each screenshot, and each recording you end with
record: "stop", also shows in the person's app as a step of the box, under its Screenshots & recordings (also when the box is listed under Stopped (last 7 days), seesandbox_exec); the files are deleted after 7 days. Pages captured together withurlsare the exception: the whole batch is recorded as one step with no pictures, see above. Past the hour, get fresh URLs (anothersandbox_shottakes a new picture; it does not bring back the old one): callGET https://api.parallelsandbox.com/v1/boxes/{id}/mediawith the API key (Authorization: Bearer <key>); it is REST only, with no MCP tool. It returns the box's steps taken in the last 7 days that have pictures, the newest 200 at most, oldest first, for a stopped box too:{"keepDays": 7, "steps": [...]}. Each step has the fields ofsandbox_statussteps[], plusmedia[], each withkind(videoorimage),urlandbytes, anddurationSecfor a video; the URLs are signed again on each call and valid for at least an hour (see REST). How long each kind of picture is kept, and who can still see it once the box is stopped: see the table under Finishing a box.
Every tool and topic is listed in the tool reference.