Use Windows Computer Use Sandbox
Create a Windows sandbox with the Desktop SDK, start a noVNC live stream, and verify that keyboard input and file read and write operations succeed.
Background information
Windows Computer Use Sandbox is a Windows desktop environment provided by Agent Sandbox. Agents control it through the Desktop SDK (e2b-desktop). It is designed for agent tasks that must interact with Windows desktop applications. noVNC is an HTML5-based Virtual Network Computing (VNC) client that lets you view and control a remote desktop in a browser.
To operate a Linux desktop, see Use Computer Use Sandbox.
Windows Desktop images are provided only through official channels. Building or importing your own Windows images is not supported. Obtain the official Windows Desktop image address first, and then build a template from that image.
Prerequisites
-
The official Windows Desktop image address is obtained. The image is in invitational preview. To obtain the image, contact technical support.
-
Python 3.12 is installed.
-
An API key is created, and the endpoint of the region where the template resides is obtained. For more information, see Create an API Key.
-
(Required only to save and restore sandboxes) Your account is added to the Snapshot allowlist. Snapshot is supported only by the second-generation runtime (
micro-sandbox). For the supported regions, see Usage constraints. -
(Required only to view the noVNC live stream in a browser) A custom domain name is bound to the sandbox. For more information, see Custom Domains.
-
(Required only to run the Snapshot lifecycle script in More operations)
uvis installed. Runpip install uvto install it.
Usage notes
Public access to a sandbox and control plane authentication are controlled separately, each by its own parameter and token:
-
allow_public_traffic(Python SDK) orallowPublicTraffic(JavaScript SDK, TypeScript SDK, and REST) defaults toTrue, which means that the public URL is accessible without a traffic token. Set it toFalseto require thee2b-traffic-access-tokenrequest header in all public requests. Query parameters are not supported. -
securedefaults toTrueand manages control plane authentication between the SDK and the envd daemon in the sandbox. This authentication uses its own token, which is separate from the traffic token. The example in Step 3 omits thenetworkparameter to use its default value and explicitly setssecure=True.
Treat the public URL as an access credential. Without application-layer authentication, anyone who holds the URL has full control of the sandbox desktop. Do not share the URL publicly, and do not write it to logs or frontend code.
To restrict access, see Network Access Control and Shared responsibility model for security. A restricted API key must have the following permissions in Enforce mode:
|
Permission |
When required |
|
|
For the Python SDK, passing |
|
|
The SDK sends |
In restricted mode, non-browser clients such as servers can pass e2b-traffic-access-token directly in the WebSocket handshake headers. Clients that run in a browser page, such as the web version of noVNC, cannot customize handshake headers. For these clients, inject the token through a URL query parameter in the format vnc.html?AccessToken=<TOKEN>.
Procedure
Step 1: Prepare the environment and configuration
-
Create a Python virtual environment and install dependencies such as the E2B SDK and the Desktop SDK:
python3.12 -m venv .venv source .venv/bin/activate pip install e2b==2.31.0 e2b-desktop==2.4.2 python-dotenv -
Create a
.envfile in the project directory and specify the endpoint parameters and the image address. This example uses the China (Beijing) region. For the values of other regions, see Usage constraints.E2B_API_KEY=<YOUR-API-KEY> E2B_API_URL=https://api.cn-beijing.sandbox.aliyuncs.com E2B_DOMAIN=cn-beijing.sandbox.aliyuncs.com E2B_WINDOWS_DESKTOP_IMAGE=<YOUR-WINDOWS-DESKTOP-IMAGE>.envcontains secrets. Add it to.gitignoreand do not commit it to a repository. The SDK reads these environment variables automatically, so you do not need to pass them in method calls.
Step 2: Build a Windows Desktop template
-
Save the following code as
build_windows_template.py. It builds a template from the official Windows Desktop image."""Build a template from the official Windows Desktop image.""" import os from dotenv import load_dotenv from e2b import Template, default_build_logger load_dotenv() image = os.environ["E2B_WINDOWS_DESKTOP_IMAGE"] build = Template.build( Template().from_image(image), name="my-windows-desktop", cpu_count=8, memory_mb=8192, on_build_logs=default_build_logger(), ) print(f"template_id: {build.template_id}") -
Build the template:
python build_windows_template.py -
After the build completes, add the template ID from the output to
.env:E2B_WINDOWS_DESKTOP_TEMPLATE=<YOUR-WINDOWS-DESKTOP-TEMPLATE-ID>
Step 3: Run the example
-
Save the following code as
windows_desktop_demo.py. The example creates a Windows sandbox, starts a noVNC live stream, types text in Notepad, and reads the file back to verify keyboard input."""Operate Windows through the Desktop SDK and view the live stream in noVNC.""" from __future__ import annotations import os import time from dotenv import load_dotenv from e2b import CommandExitException from e2b_desktop import Sandbox DEMO_PATH = "/tmp/e2b-desktop-demo.txt" DEMO_TEXT = "E2B Desktop SDK + Windows + noVNC\r\nKeyboard input and live stream demo succeeded" def wait_for_notepad(desktop: Sandbox) -> str: """Wait for the Notepad window to appear and return its window ID.""" for _ in range(40): try: windows = desktop.get_application_windows("Notepad") if windows and windows != [""]: return windows[0] except CommandExitException: pass time.sleep(0.25) raise RuntimeError("Notepad window not found within 10 seconds") def main() -> None: load_dotenv() template = os.environ["E2B_WINDOWS_DESKTOP_TEMPLATE"] desktop: Sandbox | None = None try: desktop = Sandbox.create( template=template, resolution=(1920, 1080), timeout=900, secure=True, ) width, height = desktop.get_screen_size() print(f"Windows Desktop created: {desktop.sandbox_id}, {width}x{height}") desktop.stream.start(require_auth=False) stream_url = desktop.stream.get_url() print(f"Open the noVNC URL in a browser:\n{stream_url}") desktop.files.write(DEMO_PATH, "Waiting for SDK input...") desktop.commands.run( "Get-Process -Name notepad -ErrorAction SilentlyContinue " "| Stop-Process -Force; exit 0" ) desktop.launch("notepad.exe", DEMO_PATH) window_id = wait_for_notepad(desktop) print(f"Window launched: {desktop.get_window_title(window_id)}") desktop.commands.run(f"xdotool windowactivate --sync {window_id}") desktop.press(["ctrl", "a"]) desktop.write(DEMO_TEXT, chunk_size=64, delay_in_ms=20) desktop.press(["ctrl", "s"]) desktop.wait(500) content = desktop.files.read(DEMO_PATH) if "Keyboard input and live stream demo succeeded" not in content: raise RuntimeError("The SDK keyboard input was not written to the demo file") print("Keyboard input and file verification succeeded.") input("Press Enter to end the example and release the sandbox...") finally: if desktop is not None: desktop.kill() if __name__ == "__main__": main() -
Run the example:
python windows_desktop_demo.py -
After the program prints the noVNC URL, open the URL in a browser to view the Windows desktop live stream. The example opens Notepad, types text, and reads the file back to verify the result. After you press Enter, the
finallyblock destroys the sandbox and releases resources.
The example uses desktop.stream.start(require_auth=False) for local debugging, so the generated noVNC URL can be opened without a password. On the default platform domain *.sandbox.aliyuncs.com, the response for this page includes the Content-Disposition: attachment header, so the browser downloads vnc.html instead of opening it. Bind a custom domain name first. For external access, enable authentication. The following collapsible panel describes how the noVNC URL is generated and how the password is appended. For the full description of tokens and handshake headers, see Usage notes.
Step 4: Verify the result
If the example runs successfully, the terminal prints messages about sandbox creation, window launch, and verification in sequence:
Windows Desktop created: <SANDBOX-ID>, 1920x1080
Open the noVNC URL in a browser:
<NOVNC-URL>
Window launched: <WINDOW-TITLE>
Keyboard input and file verification succeeded.
On the noVNC page, the Notepad window shows the text typed by the SDK, and the content of /tmp/e2b-desktop-demo.txt matches the input.
More operations
Save and restore a Windows sandbox with Snapshot
To repeatedly start a Windows environment whose desktop initialization is complete, create a Snapshot from a running Windows sandbox, and then create a new sandbox from the Snapshot ID. The example performs the following operations in order:
-
Build a second-generation runtime template from the official Windows Desktop image.
-
Create the source sandbox from the template ID.
-
Wait until the Windows command service and the first noVNC frame are ready, and then create the Snapshot.
-
Create the restored sandbox from the Snapshot ID and verify the Windows command service.
-
Print the noVNC URL of the restored sandbox.
Snapshot is in invitational preview. It is available only to allowlisted accounts and is supported only by the second-generation runtime (micro-sandbox). Windows Desktop images are provided only through official channels. Building or importing your own Windows images is not supported. For the default retention period, naming, deletion, and billing rules of Snapshot, see Snapshot (Preview).
Prepare the configuration
By default, the example uses 16 vCPUs, 16,448 MiB of memory, and a 61,440 MiB system disk. The API, the image, and the Virtual Private Cloud (VPC) resources must belong to the same region. Save the following content as a .env file in the same directory as the script, and replace the placeholder values in angle brackets. This .env file has the same name as the .env file created in Step 1, but the variable name of the image address differs. This script uses ROOTFS_IMAGE, and Step 1 uses E2B_WINDOWS_DESKTOP_IMAGE. If this script and the examples in Steps 1 to 3 share a directory, merge the variables into a single .env file to prevent them from overwriting each other.
E2B_API_KEY=<YOUR-API-KEY>
E2B_API_URL=https://api.cn-beijing.sandbox.aliyuncs.com
E2B_DOMAIN=cn-beijing.sandbox.aliyuncs.com
ROOTFS_IMAGE=<YOUR-WINDOWS-DESKTOP-IMAGE>
# Configure the following three variables if you build the template in the VPC where the image resides.
E2B_TEMPLATE_SOURCE_VPC_ID=<YOUR-VPC-ID>
E2B_TEMPLATE_SOURCE_VSWITCH_IDS=<YOUR-VSWITCH-ID>
E2B_TEMPLATE_SOURCE_SECURITY_GROUP_ID=<YOUR-SECURITY-GROUP-ID>
E2B_TEMPLATE_CPU_COUNT=16
E2B_TEMPLATE_MEMORY_MB=16448
E2B_TEMPLATE_DISK_SIZE=61440
E2B_TEMPLATE_BUILD_MODE=micro
E2B_TEMPLATE_OS_TYPE=windows-osworld
E2B_REQUEST_TIMEOUT_SECONDS=600
SANDBOX_TIMEOUT_SECONDS=900
TEMPLATE_BUILD_TIMEOUT_SECONDS=3600
NOVNC_READY_TIMEOUT_SECONDS=600
# By default, the source sandbox is destroyed and the restored sandbox is kept so that noVNC can be opened to check the result.
KEEP_SOURCE_SANDBOX=false
CLEANUP_RESTORED_SANDBOX=false
Run the full lifecycle script
Save the following code as windows_snapshot_lifecycle.py. The script pins its dependency versions with PEP 723 inline metadata. Install uv first, and then run the script with uv run.
Run the script:
uv run windows_snapshot_lifecycle.py
After the script succeeds, it prints the template ID, the Snapshot ID, the restored sandbox ID, and the noVNC URL. The source sandbox is destroyed at the end of the workflow by default. The restored sandbox is kept by default so that you can inspect the restored desktop immediately. After you finish, destroy it manually, or set CLEANUP_RESTORED_SANDBOX=true before you run the script to clean it up automatically.
The noVNC URL printed by the example contains a sandbox access token. Treat it as a temporary access credential. Do not write it to persistent logs, commit it to a code repository, or share it publicly. In production, provide access through a controlled backend proxy, or use Desktop Stream with authentication.