computer use linux
Computer Use
Copy for LLMView as MarkdownOpen
Computer Use enables programmatic control of desktop environments within sandboxes. It provides mouse, keyboard, screenshot, screen recording, and display operations for automating GUI interactions and testing desktop applications.
Computer Use and VNC work together to enable both manual and automated desktop interactions. VNC provides the visual interface for users to manually interact with the desktop, while Computer Use provides the programmatic API for AI agents to automate operations.
Computer Use is available for Linux and Windows through Daytona. For macOS sandboxes and Computer Use, see macOS sandboxes.
# Start Computer Use
Section titled “Start Computer Use”
Start all computer use processes (Xvfb, xfce4, x11vnc, novnc) in the Sandbox.
result = sandbox.computer_use.start()
print("Computer use processes started:", result.message)
const result = await sandbox.computerUse.start();
console.log('Computer use processes started:', result.message);
result = sandbox.computer_use.start
puts "Computer use processes started: #{result.message}"
err := sandbox.ComputerUse.Start(ctx)
if err != nil {
log.Fatal(err)
}
defer sandbox.ComputerUse.Stop(ctx)
fmt.Println("Computer use processes started")
var result = sandbox.computerUse.start();
System.out.println("Computer use processes started: " + result.getMessage());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/start' \
--request POST
# Stop Computer Use
Section titled “Stop Computer Use”
Stop all computer use processes in the Sandbox.
result = sandbox.computer_use.stop()
print("Computer use processes stopped:", result.message)
const result = await sandbox.computerUse.stop();
console.log('Computer use processes stopped:', result.message);
result = sandbox.computer_use.stop
puts "Computer use processes stopped: #{result.message}"
err := sandbox.ComputerUse.Stop(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println("Computer use processes stopped")
var result = sandbox.computerUse.stop();
System.out.println("Computer use processes stopped: " + result.getMessage());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/stop' \
--request POST
# Get status
Get the status of all computer use processes.
response = sandbox.computer_use.get_status()
print("Computer use status:", response.status)
const status = await sandbox.computerUse.getStatus();
console.log('Computer use status:', status.status);
response = sandbox.computer_use.status
puts "Computer use status: #{response.status}"
status, err := sandbox.ComputerUse.GetStatus(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Computer use status: %v\n", status["status"])
var response = sandbox.computerUse.getStatus();
System.out.println("Computer use status: " + response.getStatus());
# Status of the computer use system
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/status'
# Status of all computer use processes
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process-status'
# Get process status
Section titled “Get process status”
Get the status of a specific VNC process.
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
novnc_status = sandbox.computer_use.get_process_status("novnc")
const xvfbStatus = await sandbox.computerUse.getProcessStatus('xvfb');
const noVncStatus = await sandbox.computerUse.getProcessStatus('novnc');
xvfb_status = sandbox.computer_use.get_process_status(process_name: "xvfb")
no_vnc_status = sandbox.computer_use.get_process_status(process_name: "novnc")
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/status'
# Restart process
Section titled “Restart process”
Restart a specific VNC process.
result = sandbox.computer_use.restart_process("xfce4")
print("XFCE4 process restarted:", result.message)
const result = await sandbox.computerUse.restartProcess('xfce4');
console.log('XFCE4 process restarted:', result.message);
result = sandbox.computer_use.restart_process(process_name: "xfce4")
puts "XFCE4 process restarted: #{result.message}"
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/restart' \
--request POST
# Get process logs
Section titled “Get process logs”
Get logs for a specific VNC process.
logs = sandbox.computer_use.get_process_logs("novnc")
print("NoVNC logs:", logs)
const logsResp = await sandbox.computerUse.getProcessLogs('novnc');
console.log('NoVNC logs:', logsResp.logs);
logs = sandbox.computer_use.get_process_logs(process_name: "novnc")
puts "NoVNC logs: #{logs}"
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/logs'
# Get process errors
Section titled “Get process errors”
Get error logs for a specific VNC process.
errors = sandbox.computer_use.get_process_errors("x11vnc")
print("X11VNC errors:", errors)
const errorsResp = await sandbox.computerUse.getProcessErrors('x11vnc');
console.log('X11VNC errors:', errorsResp.errors);
errors = sandbox.computer_use.get_process_errors(process_name: "x11vnc")
puts "X11VNC errors: #{errors}"
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/errors'
# Mouse operations
Section titled “Mouse operations”
# Click
Click the mouse at the specified coordinates. button is one of left, right, or middle (case-insensitive; defaults to left); other values return an error.
# Single left click
result = sandbox.computer_use.mouse.click(100, 200)
# Double click
double_click = sandbox.computer_use.mouse.click(100, 200, "left", True)
# Right click
right_click = sandbox.computer_use.mouse.click(100, 200, "right")
// Single left click
const result = await sandbox.computerUse.mouse.click(100, 200);
// Double click
const doubleClick = await sandbox.computerUse.mouse.click(100, 200, 'left', true);
// Right click
const rightClick = await sandbox.computerUse.mouse.click(100, 200, 'right');
# Single left click
result = sandbox.computer_use.mouse.click(x: 100, y: 200)
# Double click
double_click = sandbox.computer_use.mouse.click(x: 100, y: 200, button: 'left', double: true)
# Right click
right_click = sandbox.computer_use.mouse.click(x: 100, y: 200, button: 'right')
// Single left click
result, err := sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, nil, nil)
if err != nil {
log.Fatal(err)
}
// Double click
doubleClick := true
result, err = sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, nil, &doubleClick)
// Right click
rightButton := "right"
result, err = sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, &rightButton, nil)
// Single left click
sandbox.computerUse.click(100, 200);
// Double click
sandbox.computerUse.doubleClick(100, 200);
// Right click
sandbox.computerUse.click(100, 200, "right");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/click' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"button": "left",
"double": true,
"x": 100,
"y": 200
}'
# Move
Move the mouse cursor to the specified coordinates.
result = sandbox.computer_use.mouse.move(100, 200)
print(f"Mouse moved to: {result.x}, {result.y}")
const result = await sandbox.computerUse.mouse.move(100, 200);
console.log(`Mouse moved to: ${result.x}, ${result.y}`);
result = sandbox.computer_use.mouse.move(x: 100, y: 200)
puts "Mouse moved to: #{result.x}, #{result.y}"
result, err := sandbox.ComputerUse.Mouse().Move(ctx, 100, 200)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mouse moved to: %v, %v\n", result["x"], result["y"])
var result = sandbox.computerUse.moveMouse(100, 200);
System.out.println("Mouse moved to: " + result.getX() + ", " + result.getY());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/move' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"x": 1,
"y": 1
}'
# Drag
Drag the mouse from start coordinates to end coordinates.
result = sandbox.computer_use.mouse.drag(50, 50, 150, 150)
print(f"Drag ended at {result.x}, {result.y}")
const result = await sandbox.computerUse.mouse.drag(50, 50, 150, 150);
console.log(`Drag ended at ${result.x}, ${result.y}`);
result = sandbox.computer_use.mouse.drag(start_x: 50, start_y: 50, end_x: 150, end_y: 150)
puts "Drag ended at #{result.x}, #{result.y}"
result, err := sandbox.ComputerUse.Mouse().Drag(ctx, 50, 50, 150, 150, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Dragged to %v, %v\n", result["x"], result["y"])
var result = sandbox.computerUse.drag(50, 50, 150, 150);
System.out.println("Drag ended at: " + result.getX() + ", " + result.getY());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/drag' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"button": "left",
"endX": 200,
"endY": 300,
"startX": 100,
"startY": 100
}'
# Hold and release button
Section titled “Hold and release button”
Press and hold a mouse button, then release it. The button stays held until a matching release call, which lets you compose press-move-release gestures such as marquee selection or drawing strokes. When X and Y coordinates are provided, the cursor moves to that position before the button is pressed or released; when omitted, the action happens at the current cursor position. Button is one of left (default), right, or middle.
To hold a modifier key during the gesture, wrap it with the keyboard hold and release calls.
# Press the left button at (100, 200) and release it at (300, 400)
sandbox.computer_use.mouse.down(100, 200)
result = sandbox.computer_use.mouse.up(300, 400)
print(f"Released at {result.x}, {result.y}")
# Press and release the right button at the current cursor position
sandbox.computer_use.mouse.down(button="right")
sandbox.computer_use.mouse.up(button="right")
// Press the left button at (100, 200) and release it at (300, 400)
await sandbox.computerUse.mouse.down(100, 200);
const result = await sandbox.computerUse.mouse.up(300, 400);
console.log(`Released at ${result.x}, ${result.y}`);
// Press and release the right button at the current cursor position
await sandbox.computerUse.mouse.down(undefined, undefined, 'right');
await sandbox.computerUse.mouse.up(undefined, undefined, 'right');
# Press the left button at (100, 200) and release it at (300, 400)
sandbox.computer_use.mouse.down(x: 100, y: 200)
result = sandbox.computer_use.mouse.up(x: 300, y: 400)
puts "Released at #{result.x}, #{result.y}"
# Press and release the right button at the current cursor position
sandbox.computer_use.mouse.down(button: 'right')
sandbox.computer_use.mouse.up(button: 'right')
// Press the left button at (100, 200) and release it at (300, 400)
startX, startY := 100, 200
if _, err := sandbox.ComputerUse.Mouse().Down(ctx, nil, &startX, &startY); err != nil {
log.Fatal(err)
}
endX, endY := 300, 400
result, err := sandbox.ComputerUse.Mouse().Up(ctx, nil, &endX, &endY)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Released at %v, %v\n", result["x"], result["y"])
// Press and release the right button at the current cursor position
rightButton := "right"
_, err = sandbox.ComputerUse.Mouse().Down(ctx, &rightButton, nil, nil)
_, err = sandbox.ComputerUse.Mouse().Up(ctx, &rightButton, nil, nil)
// Press the left button at (100, 200) and release it at (300, 400)
sandbox.computerUse.mouseDown(100, 200);
var result = sandbox.computerUse.mouseUp(300, 400);
System.out.println("Released at " + result.getX() + ", " + result.getY());
// Press and release the right button at the current cursor position
sandbox.computerUse.mouseDown("right");
sandbox.computerUse.mouseUp("right");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/down' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"button": "left",
"x": 100,
"y": 200
}'
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/up' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"button": "left",
"x": 300,
"y": 400
}'
# Scroll
Scroll the mouse wheel at the specified coordinates. direction is up or down (other values return an error). amount is the number of scroll wheel ticks to send — one tick is roughly one notch of a physical mouse wheel, which moves a few lines in most apps. Defaults to 1 if omitted.
# Scroll up
scroll_up = sandbox.computer_use.mouse.scroll(100, 200, "up", 3)
# Scroll down
scroll_down = sandbox.computer_use.mouse.scroll(100, 200, "down", 5)
// Scroll up
const scrollUp = await sandbox.computerUse.mouse.scroll(100, 200, 'up', 3);
// Scroll down
const scrollDown = await sandbox.computerUse.mouse.scroll(100, 200, 'down', 5);
# Scroll up
scroll_up = sandbox.computer_use.mouse.scroll(x: 100, y: 200, direction: 'up', amount: 3)
# Scroll down
scroll_down = sandbox.computer_use.mouse.scroll(x: 100, y: 200, direction: 'down', amount: 5)
// Scroll up
amount := 3
success, err := sandbox.ComputerUse.Mouse().Scroll(ctx, 100, 200, "up", &amount)
if err != nil {
log.Fatal(err)
}
// Scroll down
amount = 5
success, err = sandbox.ComputerUse.Mouse().Scroll(ctx, 100, 200, "down", &amount)
// Scroll up (negative vertical delta maps to "up")
sandbox.computerUse.scroll(100, 200, 0, -3);
// Scroll down
sandbox.computerUse.scroll(100, 200, 0, 5);
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/scroll' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"amount": 3,
"direction": "down",
"x": 100,
"y": 200
}'
# Get position
Get the current mouse cursor position.
position = sandbox.computer_use.mouse.get_position()
print(f"Mouse is at: {position.x}, {position.y}")
const position = await sandbox.computerUse.mouse.getPosition();
console.log(`Mouse is at: ${position.x}, ${position.y}`);
position = sandbox.computer_use.mouse.position
puts "Mouse is at: #{position.x}, #{position.y}"
position, err := sandbox.ComputerUse.Mouse().GetPosition(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mouse is at: %v, %v\n", position["x"], position["y"])
var position = sandbox.computerUse.getMousePosition();
System.out.println("Mouse is at: " + position.getX() + ", " + position.getY());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/position'
# Keyboard operations
Section titled “Keyboard operations”
# Type
Types arbitrary text, including uppercase letters, symbols, and non-ASCII characters. Newlines (\n, \r, \r\n) are translated into Enter key presses; literal tab and other control characters are rejected.
sandbox.computer_use.keyboard.type("Hello, World!")
# With delay between characters
sandbox.computer_use.keyboard.type("Slow typing", 100)
await sandbox.computerUse.keyboard.type('Hello, World!');
// With delay between characters
await sandbox.computerUse.keyboard.type('Slow typing', 100);
sandbox.computer_use.keyboard.type(text: "Hello, World!")
# With delay between characters
sandbox.computer_use.keyboard.type(text: "Slow typing", delay: 100)
err := sandbox.ComputerUse.Keyboard().Type(ctx, "Hello, World!", nil)
if err != nil {
log.Fatal(err)
}
// With delay between characters
delay := 100
err = sandbox.ComputerUse.Keyboard().Type(ctx, "Slow typing", &delay)
sandbox.computerUse.typeText("Hello, World!");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/type' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"delay": 1,
"text": ""
}'
# Press
Press a key with optional modifiers.
# Press Enter
sandbox.computer_use.keyboard.press("enter")
# Press Ctrl+C
sandbox.computer_use.keyboard.press("c", ["ctrl"])
# Press Ctrl+Shift+T
sandbox.computer_use.keyboard.press("t", ["ctrl", "shift"])
// Press Enter
await sandbox.computerUse.keyboard.press('enter');
// Press Ctrl+C
await sandbox.computerUse.keyboard.press('c', ['ctrl']);
// Press Ctrl+Shift+T
await sandbox.computerUse.keyboard.press('t', ['ctrl', 'shift']);
# Press Enter
sandbox.computer_use.keyboard.press(key: "enter")
# Press Ctrl+C
sandbox.computer_use.keyboard.press(key: "c", modifiers: ["ctrl"])
# Press Ctrl+Shift+T
sandbox.computer_use.keyboard.press(key: "t", modifiers: ["ctrl", "shift"])
// Press Enter
err := sandbox.ComputerUse.Keyboard().Press(ctx, "enter", nil)
if err != nil {
log.Fatal(err)
}
// Press Ctrl+C
err = sandbox.ComputerUse.Keyboard().Press(ctx, "c", []string{"ctrl"})
// Press Ctrl+Shift+T
err = sandbox.ComputerUse.Keyboard().Press(ctx, "t", []string{"ctrl", "shift"})
// Press Enter
sandbox.computerUse.pressKey("enter");
// Press Ctrl+C
sandbox.computerUse.pressHotkey("ctrl", "c");
// Press Ctrl+Shift+T
sandbox.computerUse.pressHotkey("ctrl", "shift", "t");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/key' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"key": "enter",
"modifiers": []
}'
# Hotkey
Press a hotkey combination.
# Copy
sandbox.computer_use.keyboard.hotkey("ctrl+c")
# Paste
sandbox.computer_use.keyboard.hotkey("ctrl+v")
# Alt+Tab
sandbox.computer_use.keyboard.hotkey("alt+tab")
// Copy
await sandbox.computerUse.keyboard.hotkey('ctrl+c');
// Paste
await sandbox.computerUse.keyboard.hotkey('ctrl+v');
// Alt+Tab
await sandbox.computerUse.keyboard.hotkey('alt+tab');
# Copy
sandbox.computer_use.keyboard.hotkey(keys: "ctrl+c")
# Paste
sandbox.computer_use.keyboard.hotkey(keys: "ctrl+v")
# Alt+Tab
sandbox.computer_use.keyboard.hotkey(keys: "alt+tab")
// Copy
err := sandbox.ComputerUse.Keyboard().Hotkey(ctx, "ctrl+c")
if err != nil {
log.Fatal(err)
}
// Paste
err = sandbox.ComputerUse.Keyboard().Hotkey(ctx, "ctrl+v")
// Alt+Tab
err = sandbox.ComputerUse.Keyboard().Hotkey(ctx, "alt+tab")
// Copy
sandbox.computerUse.pressHotkey("ctrl", "c");
// Paste
sandbox.computerUse.pressHotkey("ctrl", "v");
// Alt+Tab
sandbox.computerUse.pressHotkey("alt", "tab");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/hotkey' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"keys": "ctrl+c"
}'
# Hold and release key
Section titled “Hold and release key”
Press and hold a key, then release it. The key stays held until a matching release call, which lets you hold a modifier such as shift across several mouse or keyboard actions. Keys use the same names as press, listed in supported keys. Release the key in a finally block (or the language equivalent) so a failed action does not leave the key held.
# Hold Shift while clicking two points, then release it
sandbox.computer_use.keyboard.down("shift")
try:
sandbox.computer_use.mouse.click(100, 200)
sandbox.computer_use.mouse.click(100, 300)
finally:
sandbox.computer_use.keyboard.up("shift")
// Hold Shift while clicking two points, then release it
await sandbox.computerUse.keyboard.down('shift');
try {
await sandbox.computerUse.mouse.click(100, 200);
await sandbox.computerUse.mouse.click(100, 300);
} finally {
await sandbox.computerUse.keyboard.up('shift');
}
# Hold Shift while clicking two points, then release it
sandbox.computer_use.keyboard.down(key: 'shift')
begin
sandbox.computer_use.mouse.click(x: 100, y: 200)
sandbox.computer_use.mouse.click(x: 100, y: 300)
ensure
sandbox.computer_use.keyboard.up(key: 'shift')
end
// Hold Shift while clicking two points, then release it
keyboard := sandbox.ComputerUse.Keyboard()
if err := keyboard.KeyDown(ctx, "shift"); err != nil {
log.Fatal(err)
}
defer keyboard.KeyUp(ctx, "shift")
if _, err := sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, nil, nil); err != nil {
log.Fatal(err)
}
if _, err := sandbox.ComputerUse.Mouse().Click(ctx, 100, 300, nil, nil); err != nil {
log.Fatal(err)
}
// Hold Shift while clicking two points, then release it
sandbox.computerUse.keyDown("shift");
try {
sandbox.computerUse.click(100, 200);
sandbox.computerUse.click(100, 300);
} finally {
sandbox.computerUse.keyUp("shift");
}
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/down' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"key": "shift"
}'
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/up' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"key": "shift"
}'
# Supported keys
Section titled “Supported keys”
keyboard.press(), keyboard.hotkey(), keyboard.down(), and keyboard.up() are case-insensitive for named keys. The following are supported:
| Category | Keys |
|---|---|
| Modifiers | ctrl, alt, shift, cmd |
| Editing | enter, escape, tab, backspace, delete, space |
| Navigation | home, end, pageup, pagedown, insert, arrow keys (up, down, left, right) |
| Function keys | f1 through f24 |
| Numpad | num0–num9, num_plus, num_minus, num_asterisk, num_slash, num_decimal, num_enter, num_equal, num_lock |
| Letters and digits | a–z (case-insensitive), 0–9 |
| Punctuation | ``````-=[]`;``'``,``.``/ |
| Other | capslock, menu |
Common aliases like Return → enter, control → ctrl, command / meta / win → cmd, and option → alt are normalized automatically. Unsupported or malformed inputs return an error, sometimes with a suggested alternative.
# Accessibility operations
Section titled “Accessibility operations”
Use Linux accessibility operations to inspect the AT-SPI tree and interact with UI elements by node ID. Start Computer Use before calling accessibility methods.
# Get tree
Read an accessibility tree for the focused app, a specific process, or all apps.
# Focused app
focused_tree = sandbox.computer_use.accessibility.get_tree(scope="focused", max_depth=2)
# Specific process
process_tree = sandbox.computer_use.accessibility.get_tree(
scope="pid",
pid=1234,
max_depth=2,
)
# All apps
desktop_tree = sandbox.computer_use.accessibility.get_tree(scope="all", max_depth=2)
// Focused app
const focusedTree = await sandbox.computerUse.accessibility.getTree({
scope: 'focused',
maxDepth: 2,
});
// Specific process
const processTree = await sandbox.computerUse.accessibility.getTree({
scope: 'pid',
pid: 1234,
maxDepth: 2,
});
// All apps
const desktopTree = await sandbox.computerUse.accessibility.getTree({
scope: 'all',
maxDepth: 2,
});
# Focused app
focused_tree = sandbox.computer_use.accessibility.get_tree(scope: "focused", max_depth: 2)
# Specific process
process_tree = sandbox.computer_use.accessibility.get_tree(
scope: "pid",
pid: 1234,
max_depth: 2
)
# All apps
desktop_tree = sandbox.computer_use.accessibility.get_tree(scope: "all", max_depth: 2)
maxDepth := 2
// Focused app
focusedScope := "focused"
focusedTree, err := sandbox.ComputerUse.Accessibility().GetTree(ctx, &daytona.AccessibilityTreeOptions{
Scope: &focusedScope,
MaxDepth: &maxDepth,
})
if err != nil {
log.Fatal(err)
}
// Specific process
processScope := "pid"
pid := 1234
processTree, err := sandbox.ComputerUse.Accessibility().GetTree(ctx, &daytona.AccessibilityTreeOptions{
Scope: &processScope,
PID: &pid,
MaxDepth: &maxDepth,
})
if err != nil {
log.Fatal(err)
}
// All apps
allScope := "all"
desktopTree, err := sandbox.ComputerUse.Accessibility().GetTree(ctx, &daytona.AccessibilityTreeOptions{
Scope: &allScope,
MaxDepth: &maxDepth,
})
if err != nil {
log.Fatal(err)
}
// Focused app
var focusedTree = sandbox.computerUse.getAccessibilityTree("focused", null, 2);
// Specific process
var processTree = sandbox.computerUse.getAccessibilityTree("pid", 1234, 2);
// All apps
var desktopTree = sandbox.computerUse.getAccessibilityTree("all", null, 2);
# Focused app
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/tree?scope=focused&maxDepth=2'
# Specific process
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/tree?scope=pid&pid=1234&maxDepth=2'
# All apps
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/tree?scope=all&maxDepth=2'
# Find nodes
Search the accessibility tree by role, accessible name, state, and scope.
# Find buttons by accessible name
buttons = sandbox.computer_use.accessibility.find_nodes(
scope="focused",
role="button",
name="Submit",
name_match="substring",
limit=10,
)
# Find text entries in a process
entries = sandbox.computer_use.accessibility.find_nodes(
scope="pid",
pid=1234,
role="entry",
states=["enabled", "focusable"],
limit=10,
)
# Find visible nodes across all apps
visible_nodes = sandbox.computer_use.accessibility.find_nodes(
scope="all",
states=["visible"],
limit=20,
)
// Find buttons by accessible name
const buttons = await sandbox.computerUse.accessibility.findNodes({
scope: 'focused',
role: 'button',
name: 'Submit',
nameMatch: 'substring',
limit: 10,
});
// Find text entries in a process
const entries = await sandbox.computerUse.accessibility.findNodes({
scope: 'pid',
pid: 1234,
role: 'entry',
states: ['enabled', 'focusable'],
limit: 10,
});
// Find visible nodes across all apps
const visibleNodes = await sandbox.computerUse.accessibility.findNodes({
scope: 'all',
states: ['visible'],
limit: 20,
});
# Find buttons by accessible name
buttons = sandbox.computer_use.accessibility.find_nodes(
scope: "focused",
role: "button",
name: "Submit",
name_match: "substring",
limit: 10
)
# Find text entries in a process
entries = sandbox.computer_use.accessibility.find_nodes(
scope: "pid",
pid: 1234,
role: "entry",
states: ["enabled", "focusable"],
limit: 10
)
# Find visible nodes across all apps
visible_nodes = sandbox.computer_use.accessibility.find_nodes(
scope: "all",
states: ["visible"],
limit: 20
)
limit := 10
// Find buttons by accessible name
focusedScope := "focused"
buttonRole := "button"
submitName := "Submit"
substringMatch := "substring"
buttons, err := sandbox.ComputerUse.Accessibility().FindNodes(ctx, &daytona.AccessibilityFindOptions{
Scope: &focusedScope,
Role: &buttonRole,
Name: &submitName,
NameMatch: &substringMatch,
Limit: &limit,
})
if err != nil {
log.Fatal(err)
}
// Find text entries in a process
processScope := "pid"
pid := 1234
entryRole := "entry"
entries, err := sandbox.ComputerUse.Accessibility().FindNodes(ctx, &daytona.AccessibilityFindOptions{
Scope: &processScope,
PID: &pid,
Role: &entryRole,
States: []string{"enabled", "focusable"},
Limit: &limit,
})
if err != nil {
log.Fatal(err)
}
// Find visible nodes across all apps
allScope := "all"
visibleLimit := 20
visibleNodes, err := sandbox.ComputerUse.Accessibility().FindNodes(ctx, &daytona.AccessibilityFindOptions{
Scope: &allScope,
States: []string{"visible"},
Limit: &visibleLimit,
})
if err != nil {
log.Fatal(err)
}
// Find buttons by accessible name
var buttons = sandbox.computerUse.findAccessibilityNodes(
new FindAccessibilityNodesRequest()
.scope("focused")
.role("button")
.name("Submit")
.nameMatch("substring")
.limit(10)
);
// Find text entries in a process
var entries = sandbox.computerUse.findAccessibilityNodes(
new FindAccessibilityNodesRequest()
.scope("pid")
.pid(1234)
.role("entry")
.states(java.util.List.of("enabled", "focusable"))
.limit(10)
);
// Find visible nodes across all apps
var visibleNodes = sandbox.computerUse.findAccessibilityNodes(
new FindAccessibilityNodesRequest()
.scope("all")
.states(java.util.List.of("visible"))
.limit(20)
);
# Find buttons by accessible name
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/find' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"scope": "focused",
"role": "button",
"name": "Submit",
"nameMatch": "substring",
"limit": 10
}'
# Find text entries in a process
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/find' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"scope": "pid",
"pid": 1234,
"role": "entry",
"states": ["enabled", "focusable"],
"limit": 10
}'
# Find visible nodes across all apps
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/find' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"scope": "all",
"states": ["visible"],
"limit": 20
}'
# Focus node
Move keyboard focus to a node returned by get_tree or find_nodes.
sandbox.computer_use.accessibility.focus_node("node-id")
await sandbox.computerUse.accessibility.focusNode('node-id');
sandbox.computer_use.accessibility.focus_node(id: "node-id")
if err := sandbox.ComputerUse.Accessibility().FocusNode(ctx, "node-id"); err != nil {
log.Fatal(err)
}
sandbox.computerUse.focusAccessibilityNode("node-id");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/node/focus' \
--request POST \
--header 'Content-Type: application/json' \
--data '{"id":"node-id"}'
# Invoke node
Run a node action, such as pressing a button.
# Invoke the primary action
sandbox.computer_use.accessibility.invoke_node("node-id")
# Invoke a named action
sandbox.computer_use.accessibility.invoke_node("node-id", action="click")
// Invoke the primary action
await sandbox.computerUse.accessibility.invokeNode('node-id');
// Invoke a named action
await sandbox.computerUse.accessibility.invokeNode('node-id', 'click');
# Invoke the primary action
sandbox.computer_use.accessibility.invoke_node(id: "node-id")
# Invoke a named action
sandbox.computer_use.accessibility.invoke_node(id: "node-id", action: "click")
// Invoke the primary action
if err := sandbox.ComputerUse.Accessibility().InvokeNode(ctx, "node-id", nil); err != nil {
log.Fatal(err)
}
// Invoke a named action
action := "click"
if err := sandbox.ComputerUse.Accessibility().InvokeNode(ctx, "node-id", &action); err != nil {
log.Fatal(err)
}
// Invoke the primary action
sandbox.computerUse.invokeAccessibilityNode("node-id");
// Invoke a named action
sandbox.computerUse.invokeAccessibilityNode("node-id", "click");
# Invoke the primary action
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/node/invoke' \
--request POST \
--header 'Content-Type: application/json' \
--data '{"id":"node-id"}'
# Invoke a named action
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/node/invoke' \
--request POST \
--header 'Content-Type: application/json' \
--data '{"id":"node-id","action":"click"}'
# Set node value
Section titled “Set node value”
Write text or value content to nodes that support value changes.
sandbox.computer_use.accessibility.set_node_value("node-id", "hello")
await sandbox.computerUse.accessibility.setNodeValue('node-id', 'hello');
sandbox.computer_use.accessibility.set_node_value(id: "node-id", value: "hello")
if err := sandbox.ComputerUse.Accessibility().SetNodeValue(ctx, "node-id", "hello"); err != nil {
log.Fatal(err)
}
sandbox.computerUse.setAccessibilityNodeValue("node-id", "hello");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/a11y/node/value' \
--request POST \
--header 'Content-Type: application/json' \
--data '{"id":"node-id","value":"hello"}'
# Screenshot operations
Section titled “Screenshot operations”
# Take full screen
Section titled “Take full screen”
Take a screenshot of the entire screen.
screenshot = sandbox.computer_use.screenshot.take_full_screen()
print(f"Screenshot captured, base64 length: {len(screenshot.screenshot)}")
# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(True)
const screenshot = await sandbox.computerUse.screenshot.takeFullScreen();
console.log(`Screenshot captured, base64 length: ${screenshot.screenshot?.length}`);
// With cursor visible
const withCursor = await sandbox.computerUse.screenshot.takeFullScreen(true);
screenshot = sandbox.computer_use.screenshot.take_full_screen
puts "Screenshot captured, base64 length: #{screenshot.screenshot.length}"
# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(show_cursor: true)
screenshot, err := sandbox.ComputerUse.Screenshot().TakeFullScreen(ctx, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Screenshot captured, base64 length: %d\n", len(screenshot.Image))
// With cursor visible
showCursor := true
withCursor, err := sandbox.ComputerUse.Screenshot().TakeFullScreen(ctx, &showCursor)
var screenshot = sandbox.computerUse.takeScreenshot();
System.out.println("Screenshot captured, base64 length: " + screenshot.getScreenshot().length());
// With cursor visible
var withCursor = sandbox.computerUse.takeScreenshot(true);
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot'
# Take region
Take a screenshot of a specific region.
from daytona import ScreenshotRegion
region = ScreenshotRegion(x=100, y=100, width=300, height=200)
screenshot = sandbox.computer_use.screenshot.take_region(region)
print(f"Captured {region.width}x{region.height} region, base64 length: {len(screenshot.screenshot)}")
const region = { x: 100, y: 100, width: 300, height: 200 };
const screenshot = await sandbox.computerUse.screenshot.takeRegion(region);
console.log(`Captured ${region.width}x${region.height} region, base64 length: ${screenshot.screenshot?.length}`);
region = Daytona::ComputerUse::ScreenshotRegion.new(x: 100, y: 100, width: 300, height: 200)
screenshot = sandbox.computer_use.screenshot.take_region(region: region)
puts "Captured #{region.width}x#{region.height} region, base64 length: #{screenshot.screenshot.length}"
region := types.ScreenshotRegion{X: 100, Y: 100, Width: 300, Height: 200}
screenshot, err := sandbox.ComputerUse.Screenshot().TakeRegion(ctx, region, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Captured region: %dx%d\n", screenshot.Width, screenshot.Height)
var screenshot = sandbox.computerUse.takeRegionScreenshot(100, 100, 300, 200);
System.out.println("Captured 300x200 region, base64 length: " + screenshot.getScreenshot().length());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/region?x=1&y=1&width=1&height=1'
# Take compressed
Section titled “Take compressed”
Take a compressed screenshot of the entire screen.
from daytona import ScreenshotOptions
# Default compression
screenshot = sandbox.computer_use.screenshot.take_compressed()
# High quality JPEG
jpeg = sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(fmt="jpeg", quality=95, show_cursor=True)
)
# Scaled down PNG
scaled = sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(fmt="png", scale=0.5)
)
// Default compression
const screenshot = await sandbox.computerUse.screenshot.takeCompressed();
// High quality JPEG
const jpeg = await sandbox.computerUse.screenshot.takeCompressed({
format: 'jpeg',
quality: 95,
showCursor: true
});
// Scaled down PNG
const scaled = await sandbox.computerUse.screenshot.takeCompressed({
format: 'png',
scale: 0.5
});
# Default compression
screenshot = sandbox.computer_use.screenshot.take_compressed
# High quality JPEG
jpeg = sandbox.computer_use.screenshot.take_compressed(
options: Daytona::ComputerUse::ScreenshotOptions.new(format: "jpeg", quality: 95, show_cursor: true)
)
# Scaled down PNG
scaled = sandbox.computer_use.screenshot.take_compressed(
options: Daytona::ComputerUse::ScreenshotOptions.new(format: "png", scale: 0.5)
)
// Compressed full screen (format, quality 1-100, scale factor)
var screenshot = sandbox.computerUse.takeCompressedScreenshot("png", 80, 1.0);
// High quality JPEG at full scale
var jpeg = sandbox.computerUse.takeCompressedScreenshot("jpeg", 95, 1.0);
// Scaled down PNG
var scaled = sandbox.computerUse.takeCompressedScreenshot("png", 80, 0.5);
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/compressed'
# Take compressed region
Section titled “Take compressed region”
Take a compressed screenshot of a specific region.
from daytona import ScreenshotRegion, ScreenshotOptions
region = ScreenshotRegion(x=0, y=0, width=800, height=600)
screenshot = sandbox.computer_use.screenshot.take_compressed_region(
region,
ScreenshotOptions(fmt="jpeg", quality=80, show_cursor=True)
)
print(f"Compressed size: {screenshot.size_bytes} bytes")
const region = { x: 0, y: 0, width: 800, height: 600 };
const screenshot = await sandbox.computerUse.screenshot.takeCompressedRegion(region, {
format: 'jpeg',
quality: 80,
showCursor: true
});
console.log(`Compressed size: ${screenshot.sizeBytes} bytes`);
region = Daytona::ComputerUse::ScreenshotRegion.new(x: 0, y: 0, width: 800, height: 600)
screenshot = sandbox.computer_use.screenshot.take_compressed_region(
region: region,
options: Daytona::ComputerUse::ScreenshotOptions.new(format: "jpeg", quality: 80, show_cursor: true)
)
puts "Compressed size: #{screenshot.size_bytes} bytes"
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/region/compressed?x=1&y=1&width=1&height=1'
# Screen Recording
Section titled “Screen Recording”
Computer Use supports screen recording capabilities, allowing you to capture desktop sessions for debugging, documentation, or automation workflows.
# Configure Recording Directory
Section titled “Configure Recording Directory”
By default, recordings are saved to ~/.daytona/recordings. You can specify a custom directory by passing the DAYTONA_RECORDINGS_DIR environment variable when creating a sandbox:
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(
snapshot="daytonaio/sandbox:0.6.0",
name="my-sandbox",
env_vars={"DAYTONA_RECORDINGS_DIR": "/home/daytona/my-recordings"}
)
)
import { Daytona } from '@daytona/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create({
snapshot: 'daytonaio/sandbox:0.6.0',
name: 'my-sandbox',
envVars: { DAYTONA_RECORDINGS_DIR: '/home/daytona/my-recordings' }
});
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(
snapshot: 'daytonaio/sandbox:0.6.0',
env_vars: { 'DAYTONA_RECORDINGS_DIR' => '/home/daytona/my-recordings' }
))
import (
"github.com/daytona/clients/sdk-go/pkg/daytona"
"github.com/daytona/clients/sdk-go/pkg/types"
)
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(ctx, types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
Name: "my-sandbox",
EnvVars: map[string]string{
"DAYTONA_RECORDINGS_DIR": "/home/daytona/my-recordings",
},
},
Snapshot: "daytonaio/sandbox:0.6.0",
})
if err != nil {
log.Fatal(err)
}
import io.daytona.sdk.Daytona;
import io.daytona.sdk.Sandbox;
import io.daytona.sdk.model.CreateSandboxFromSnapshotParams;
import java.util.Map;
try (Daytona daytona = new Daytona()) {
CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams();
params.setSnapshot("daytonaio/sandbox:0.6.0");
params.setName("my-sandbox");
params.setEnvVars(Map.of("DAYTONA_RECORDINGS_DIR", "/home/daytona/my-recordings"));
Sandbox sandbox = daytona.create(params);
}
# Start Recording
Section titled “Start Recording”
Start a new screen recording session with an optional label:
# Start recording with a custom label
recording = sandbox.computer_use.recording.start("test-1")
print(f"Recording started: {recording.id}")
print(f"File path: {recording.file_path}")
// Start recording with a custom label
const recording = await sandbox.computerUse.recording.start('test-1');
console.log(`Recording started: ${recording.id}`);
console.log(`File path: ${recording.filePath}`);
# Start recording with a custom label
recording = sandbox.computer_use.recording.start(label: 'test-1')
puts "Recording started: #{recording.id}"
puts "File path: #{recording.file_path}"
// Start recording with a custom label
label := "test-1"
recording, err := sandbox.ComputerUse.Recording().Start(ctx, &label)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Recording started: %s\n", recording.Id)
fmt.Printf("File path: %s\n", recording.FilePath)
// Start recording with a custom label
var recording = sandbox.computerUse.startRecording("test-1");
System.out.println("Recording started: " + recording.getId());
System.out.println("File path: " + recording.getFilePath());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/start' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"label": "test-1"
}'
# Stop Recording
Section titled “Stop Recording”
Stop an active recording session by providing the recording ID:
# Stop the recording
stopped_recording = sandbox.computer_use.recording.stop(recording.id)
print(f"Recording stopped: {stopped_recording.duration_seconds} seconds")
print(f"Saved to: {stopped_recording.file_path}")
// Stop the recording
const stoppedRecording = await sandbox.computerUse.recording.stop(recording.id);
console.log(`Recording stopped: ${stoppedRecording.durationSeconds} seconds`);
console.log(`Saved to: ${stoppedRecording.filePath}`);
# Stop the recording
stopped_recording = sandbox.computer_use.recording.stop(id: recording.id)
puts "Recording stopped: #{stopped_recording.duration_seconds} seconds"
puts "Saved to: #{stopped_recording.file_path}"
// Stop the recording
stoppedRecording, err := sandbox.ComputerUse.Recording().Stop(ctx, recording.Id)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Recording stopped: %f seconds\n", *stoppedRecording.DurationSeconds)
fmt.Printf("Saved to: %s\n", stoppedRecording.FilePath)
// Stop the recording
var stoppedRecording = sandbox.computerUse.stopRecording(recording.getId());
System.out.println("Recording stopped: " + stoppedRecording.getDurationSeconds() + " seconds");
System.out.println("Saved to: " + stoppedRecording.getFilePath());
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/stop' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"id": "recording-id"
}'
# List Recordings
Section titled “List Recordings”
Get a list of all recordings in the sandbox:
recordings_list = sandbox.computer_use.recording.list()
print(f"Total recordings: {len(recordings_list.recordings)}")
for rec in recordings_list.recordings:
print(f"- {rec.file_name}: {rec.duration_seconds}s ({rec.size_bytes} bytes)")
const recordingsList = await sandbox.computerUse.recording.list();
console.log(`Total recordings: ${recordingsList.recordings.length}`);
recordingsList.recordings.forEach(rec => {
console.log(`- ${rec.fileName}: ${rec.durationSeconds}s (${rec.sizeBytes} bytes)`);
});
recordings_list = sandbox.computer_use.recording.list
puts "Total recordings: #{recordings_list.recordings.length}"
recordings_list.recordings.each do |rec|
puts "- #{rec.file_name}: #{rec.duration_seconds}s (#{rec.size_bytes} bytes)"
end
recordingsList, err := sandbox.ComputerUse.Recording().List(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total recordings: %d\n", len(recordingsList.Recordings))
for _, rec := range recordingsList.Recordings {
fmt.Printf("- %s: %.2fs (%d bytes)\n", rec.FileName, rec.GetDurationSeconds(), rec.GetSizeBytes())
}
var recordingsList = sandbox.computerUse.listRecordings();
System.out.println("Total recordings: " + recordingsList.getRecordings().size());
for (var rec : recordingsList.getRecordings()) {
System.out.println(
"- " + rec.getFileName() + ": " + rec.getDurationSeconds() + "s (" + rec.getSizeBytes() + " bytes)"
);
}
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings'
# Get Recording
Section titled “Get Recording”
Get details about a specific recording:
recording_detail = sandbox.computer_use.recording.get("recording-id")
print(f"Recording: {recording_detail.file_name}")
print(f"Status: {recording_detail.status}")
print(f"Duration: {recording_detail.duration_seconds}s")
const recordingDetail = await sandbox.computerUse.recording.get('recording-id');
console.log(`Recording: ${recordingDetail.fileName}`);
console.log(`Status: ${recordingDetail.status}`);
console.log(`Duration: ${recordingDetail.durationSeconds}s`);
recording_detail = sandbox.computer_use.recording.get(id: 'recording-id')
puts "Recording: #{recording_detail.file_name}"
puts "Status: #{recording_detail.status}"
puts "Duration: #{recording_detail.duration_seconds}s"
recordingDetail, err := sandbox.ComputerUse.Recording().Get(ctx, "recording-id")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Recording: %s\n", recordingDetail.FileName)
fmt.Printf("Status: %s\n", recordingDetail.Status)
fmt.Printf("Duration: %.2fs\n", *recordingDetail.DurationSeconds)
var recordingDetail = sandbox.computerUse.getRecording("recording-id");
System.out.println("Recording: " + recordingDetail.getFileName());
System.out.println("Status: " + recordingDetail.getStatus());
System.out.println("Duration: " + recordingDetail.getDurationSeconds() + "s");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}'
# Delete Recording
Section titled “Delete Recording”
Delete a recording by ID:
sandbox.computer_use.recording.delete("recording-id")
print("Recording deleted successfully")
await sandbox.computerUse.recording.delete('recording-id');
console.log('Recording deleted successfully');
sandbox.computer_use.recording.delete(id: 'recording-id')
puts 'Recording deleted successfully'
err := sandbox.ComputerUse.Recording().Delete(ctx, "recording-id")
if err != nil {
log.Fatal(err)
}
fmt.Println("Recording deleted successfully")
sandbox.computerUse.deleteRecording("recording-id");
System.out.println("Recording deleted successfully");
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}' \
--request DELETE
# Download Recording
Section titled “Download Recording”
Download a recording file from the sandbox to your local machine. The file is streamed efficiently without loading the entire content into memory, making it suitable for large recordings.
# Download recording to local file
sandbox.computer_use.recording.download(recording.id, "local_recording.mp4")
print("Recording downloaded successfully")
# Or with custom path
import os
download_path = os.path.join("recordings", f"recording_{recording.id}.mp4")
sandbox.computer_use.recording.download(recording.id, download_path)
// Download recording to local file
await sandbox.computerUse.recording.download(recording.id, 'local_recording.mp4');
console.log('Recording downloaded successfully');
// Or with custom path
const downloadPath = `recordings/recording_${recording.id}.mp4`;
await sandbox.computerUse.recording.download(recording.id, downloadPath);
# Download recording to local file
sandbox.computer_use.recording.download(id: recording.id, local_path: 'local_recording.mp4')
puts 'Recording downloaded successfully'
# Or with custom path
download_path = "recordings/recording_#{recording.id}.mp4"
sandbox.computer_use.recording.download(id: recording.id, local_path: download_path)
// Download recording to local file
err := sandbox.ComputerUse.Recording().Download(ctx, recording.GetId(), "local_recording.mp4")
if err != nil {
log.Fatal(err)
}
fmt.Println("Recording downloaded successfully")
// Or with custom path
downloadPath := fmt.Sprintf("recordings/recording_%s.mp4", recording.GetId())
err = sandbox.ComputerUse.Recording().Download(ctx, recording.GetId(), downloadPath)
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
// Download returns a temp file from the API client; copy it to a stable path
var tempFile = sandbox.computerUse.downloadRecording(recording.getId());
Files.copy(tempFile.toPath(), Path.of("local_recording.mp4"), StandardCopyOption.REPLACE_EXISTING);
System.out.println("Recording saved to local_recording.mp4");
var downloadPath = Path.of("recordings", "recording_" + recording.getId() + ".mp4");
Files.createDirectories(downloadPath.getParent());
Files.copy(tempFile.toPath(), downloadPath, StandardCopyOption.REPLACE_EXISTING);
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}/download' \
--output local_recording.mp4
# Recording Dashboard
Section titled “Recording Dashboard”
Every sandbox includes a built-in recording dashboard for managing screen recordings through a web interface. The dashboard allows you to view, download, and delete recordings without writing code.
To access the recording dashboard:
- Navigate to your sandboxes in the Daytona Dashboard
- Click the action menu (three dots) for your sandbox
- Select Screen Recordings from the dropdown menu
The recording dashboard provides:
- List of all recordings with metadata (name, duration, file size, creation time)
- Playback controls for reviewing recordings
- Download functionality to save recordings locally
- Delete options for managing storage
# Display operations
Section titled “Display operations”
# Configure desktop resolution
Section titled “Configure desktop resolution”
By default, the virtual desktop runs at 1024x768. Choose a different resolution by passing the VNC_RESOLUTION environment variable when creating a sandbox. Use the <width>x<height> format; widths from 640 to 7680 pixels and heights from 480 to 4320 pixels are supported.
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(
env_vars={"VNC_RESOLUTION": "1920x1080"}
)
)
import { Daytona } from '@daytona/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create({
envVars: { VNC_RESOLUTION: '1920x1080' }
});
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(
env_vars: { 'VNC_RESOLUTION' => '1920x1080' }
))
import (
"github.com/daytona/clients/sdk-go/pkg/daytona"
"github.com/daytona/clients/sdk-go/pkg/types"
)
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(ctx, types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
EnvVars: map[string]string{
"VNC_RESOLUTION": "1920x1080",
},
},
})
if err != nil {
log.Fatal(err)
}
import io.daytona.sdk.Daytona;
import io.daytona.sdk.Sandbox;
import io.daytona.sdk.model.CreateSandboxFromSnapshotParams;
import java.util.Map;
try (Daytona daytona = new Daytona()) {
CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams();
params.setEnvVars(Map.of("VNC_RESOLUTION", "1920x1080"));
Sandbox sandbox = daytona.create(params);
}
You can also bake a resolution into a snapshot image with ENV VNC_RESOLUTION=1920x1080 in its Dockerfile. A value passed at creation takes precedence over the image’s ENV, which takes precedence over the 1024x768 default. Invalid values fall back to the default.
The virtual display’s framebuffer is allocated when the X server starts, so the resolution can only be set when creating the sandbox. Restarting display processes or stopping and starting the sandbox keeps the original geometry; create a new sandbox to use a different resolution.
Pick the resolution to match what your agent assumes. Agents that emit normalized coordinates scale them by an assumed screen size, so a desktop that differs from that assumption displaces every click. Verify the live geometry with Get info below.
# Get info
Get information about the displays.
info = sandbox.computer_use.display.get_info()
displays = info.displays or []
print(f"Total displays: {len(displays)}")
for i, display in enumerate(displays):
print(f"Display {i}: {display.width}x{display.height} at {display.x},{display.y}")
const info = await sandbox.computerUse.display.getInfo();
const displays = info.displays ?? [];
console.log(`Total displays: ${displays.length}`);
displays.forEach((display, index) => {
console.log(`Display ${index}: ${display.width}x${display.height} at ${display.x},${display.y}`);
});
info = sandbox.computer_use.display.info
displays = info.displays || []
puts "Total displays: #{displays.length}"
displays.each_with_index do |display, i|
puts "Display #{i}: #{display.width}x#{display.height} at #{display.x},#{display.y}"
end
info, err := sandbox.ComputerUse.Display().GetInfo(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Displays: %v\n", info["displays"])
var info = sandbox.computerUse.getDisplayInfo();
if (info.getDisplays() != null) {
for (var display : info.getDisplays()) {
System.out.println(
"Display " + display.getId() + ": " + display.getWidth() + "x" + display.getHeight()
+ " at " + display.getX() + "," + display.getY()
);
}
}
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/display/info'
# Get windows
Get the list of open windows.
windows = sandbox.computer_use.display.get_windows()
window_list = windows.windows or []
print(f"Found {len(window_list)} open windows:")
for window in window_list:
print(f"- {window.title} (ID: {window.id})")
const windows = await sandbox.computerUse.display.getWindows();
const windowList = windows.windows ?? [];
console.log(`Found ${windowList.length} open windows:`);
windowList.forEach(window => {
console.log(`- ${window.title} (ID: ${window.id})`);
});
windows = sandbox.computer_use.display.windows
window_list = windows.windows || []
puts "Found #{window_list.length} open windows:"
window_list.each do |window|
puts "- #{window.title} (ID: #{window.id})"
end
result, err := sandbox.ComputerUse.Display().GetWindows(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Open windows: %v\n", result["windows"])
var windows = sandbox.computerUse.getWindows();
var list = windows.getWindows();
if (list != null) {
System.out.println("Found " + list.size() + " open windows:");
for (var window : list) {
System.out.println("- " + window.getTitle() + " (ID: " + window.getId() + ")");
}
}
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/display/windows'