---
title: Computer Use
description: Programmatic control of desktop environments within Daytona sandboxes.
---

import { TabItem, Tabs } from '@astrojs/starlight/components'

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](/docs/en/vnc-access) 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**. **Windows** and **macOS** support is currently in private alpha.

:::caution[Private Alpha]
Computer Use for macOS and Windows is currently in private alpha and requires access. To request access, fill out the [Windows](https://docs.google.com/forms/d/e/1FAIpQLSfoK-77-VpfsMubw8F4f1opCxIL1AyJUgnM0ONYup5hZ0RTvQ/viewform?usp=dialog) or [macOS](https://docs.google.com/forms/d/e/1FAIpQLSc9xlGZ49OjWNkyzDPC9Ip3InMRR0ZXY3tcoD-PFQj3ck6gzQ/viewform?usp=sharing&ouid=103304973264148733944) access request form. Our team will review your request and reach out with setup instructions.
:::

- **GUI application testing**: automate interactions with native applications, click buttons, fill forms, and validate UI behavior
- **Visual testing & screenshots**: capture screenshots of applications, compare UI states, and perform visual regression testing
- **Desktop automation**: automate repetitive desktop tasks, file management through GUI, and complex workflows

## Start Computer Use

Start all computer use processes (Xvfb, xfce4, x11vnc, novnc) in the Sandbox.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
result = sandbox.computer_use.start()
print("Computer use processes started:", result.message)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const result = await sandbox.computerUse.start();
console.log('Computer use processes started:', result.message);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
result = sandbox.computer_use.start
puts "Computer use processes started: #{result.message}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
err := sandbox.ComputerUse.Start(ctx)
if err != nil {
	log.Fatal(err)
}
defer sandbox.ComputerUse.Stop(ctx)

fmt.Println("Computer use processes started")
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var result = sandbox.computerUse.start();
System.out.println("Computer use processes started: " + result.getMessage());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/start' \
  --request POST
```

</TabItem>
</Tabs>

## Stop Computer Use

Stop all computer use processes in the Sandbox.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
result = sandbox.computer_use.stop()
print("Computer use processes stopped:", result.message)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const result = await sandbox.computerUse.stop();
console.log('Computer use processes stopped:', result.message);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
result = sandbox.computer_use.stop
puts "Computer use processes stopped: #{result.message}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
err := sandbox.ComputerUse.Stop(ctx)
if err != nil {
	log.Fatal(err)
}

fmt.Println("Computer use processes stopped")
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var result = sandbox.computerUse.stop();
System.out.println("Computer use processes stopped: " + result.getMessage());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/stop' \
  --request POST
```

</TabItem>
</Tabs>

## Get status

Get the status of all computer use processes.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
response = sandbox.computer_use.get_status()
print("Computer use status:", response.status)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const status = await sandbox.computerUse.getStatus();
console.log('Computer use status:', status.status);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
response = sandbox.computer_use.status
puts "Computer use status: #{response.status}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
status, err := sandbox.ComputerUse.GetStatus(ctx)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Computer use status: %v\n", status["status"])
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var response = sandbox.computerUse.getStatus();
System.out.println("Computer use status: " + response.getStatus());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/status'
```

</TabItem>
</Tabs>

## Get process status

Get the status of a specific VNC process.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
novnc_status = sandbox.computer_use.get_process_status("novnc")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const xvfbStatus = await sandbox.computerUse.getProcessStatus('xvfb');
const noVncStatus = await sandbox.computerUse.getProcessStatus('novnc');
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
no_vnc_status = sandbox.computer_use.get_process_status("novnc")
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/status'
```

</TabItem>
</Tabs>

## Restart process

Restart a specific VNC process.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
result = sandbox.computer_use.restart_process("xfce4")
print("XFCE4 process restarted:", result.message)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const result = await sandbox.computerUse.restartProcess('xfce4');
console.log('XFCE4 process restarted:', result.message);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
result = sandbox.computer_use.restart_process("xfce4")
puts "XFCE4 process restarted: #{result.message}"
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/restart' \
  --request POST
```

</TabItem>
</Tabs>

## Get process logs

Get logs for a specific VNC process.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
logs = sandbox.computer_use.get_process_logs("novnc")
print("NoVNC logs:", logs)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const logsResp = await sandbox.computerUse.getProcessLogs('novnc');
console.log('NoVNC logs:', logsResp.logs);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
logs = sandbox.computer_use.get_process_logs("novnc")
puts "NoVNC logs: #{logs}"
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/logs'
```

</TabItem>
</Tabs>

## Get process errors

Get error logs for a specific VNC process.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
errors = sandbox.computer_use.get_process_errors("x11vnc")
print("X11VNC errors:", errors)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const errorsResp = await sandbox.computerUse.getProcessErrors('x11vnc');
console.log('X11VNC errors:', errorsResp.errors);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
errors = sandbox.computer_use.get_process_errors("x11vnc")
puts "X11VNC errors: #{errors}"
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/errors'
```

</TabItem>
</Tabs>

## 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.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# 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")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// 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');
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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')
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// 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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// Single left click
sandbox.computerUse.click(100, 200);

// Double click
sandbox.computerUse.doubleClick(100, 200);

// Right click
sandbox.computerUse.click(100, 200, "right");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
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
}'
```

</TabItem>
</Tabs>

### Move

Move the mouse cursor to the specified coordinates.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
result = sandbox.computer_use.mouse.move(100, 200)
print(f"Mouse moved to: {result.x}, {result.y}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const result = await sandbox.computerUse.mouse.move(100, 200);
console.log(`Mouse moved to: ${result.x}, ${result.y}`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
result = sandbox.computer_use.mouse.move(x: 100, y: 200)
puts "Mouse moved to: #{result.x}, #{result.y}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
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"])
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var result = sandbox.computerUse.moveMouse(100, 200);
System.out.println("Mouse moved to: " + result.getX() + ", " + result.getY());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/move' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "x": 1,
  "y": 1
}'
```

</TabItem>
</Tabs>

### Drag

Drag the mouse from start coordinates to end coordinates.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
result = sandbox.computer_use.mouse.drag(50, 50, 150, 150)
print(f"Drag ended at {result.x}, {result.y}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const result = await sandbox.computerUse.mouse.drag(50, 50, 150, 150);
console.log(`Drag ended at ${result.x}, ${result.y}`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
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}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
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"])
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var result = sandbox.computerUse.drag(50, 50, 150, 150);
System.out.println("Drag ended at: " + result.getX() + ", " + result.getY());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
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
}'
```

</TabItem>
</Tabs>

### 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.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# 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)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// 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);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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)
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// 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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// Scroll up (negative vertical delta maps to "up")
sandbox.computerUse.scroll(100, 200, 0, -3);

// Scroll down
sandbox.computerUse.scroll(100, 200, 0, 5);
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
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
}'
```

</TabItem>
</Tabs>

### Get position

Get the current mouse cursor position.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
position = sandbox.computer_use.mouse.get_position()
print(f"Mouse is at: {position.x}, {position.y}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const position = await sandbox.computerUse.mouse.getPosition();
console.log(`Mouse is at: ${position.x}, ${position.y}`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
position = sandbox.computer_use.mouse.position
puts "Mouse is at: #{position.x}, #{position.y}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
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"])
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var position = sandbox.computerUse.getMousePosition();
System.out.println("Mouse is at: " + position.getX() + ", " + position.getY());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/position'
```

</TabItem>
</Tabs>

## 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.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
sandbox.computer_use.keyboard.type("Hello, World!")

# With delay between characters
sandbox.computer_use.keyboard.type("Slow typing", 100)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
await sandbox.computerUse.keyboard.type('Hello, World!');

// With delay between characters
await sandbox.computerUse.keyboard.type('Slow typing', 100);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
sandbox.computer_use.keyboard.type(text: "Hello, World!")

# With delay between characters
sandbox.computer_use.keyboard.type(text: "Slow typing", delay: 100)
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
sandbox.computerUse.typeText("Hello, World!");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/type' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "delay": 1,
  "text": ""
}'
```

</TabItem>
</Tabs>

### Press

Press a key with optional modifiers.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# 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"])
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// 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']);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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"])
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// 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"})
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// Press Enter
sandbox.computerUse.pressKey("enter");

// Press Ctrl+C
sandbox.computerUse.pressHotkey("ctrl", "c");

// Press Ctrl+Shift+T
sandbox.computerUse.pressHotkey("ctrl", "shift", "t");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/key' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "key": "enter",
  "modifiers": []
}'
```

</TabItem>
</Tabs>

### Hotkey

Press a hotkey combination.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# 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")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">
```typescript
// 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');
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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")
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// 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")
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// Copy
sandbox.computerUse.pressHotkey("ctrl", "c");

// Paste
sandbox.computerUse.pressHotkey("ctrl", "v");

// Alt+Tab
sandbox.computerUse.pressHotkey("alt", "tab");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/hotkey' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "keys": "ctrl+c"
}'
```

</TabItem>
</Tabs>

### Supported keys

`keyboard.press()` and `keyboard.hotkey()` 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.

## Screenshot operations

### Take full screen

Take a screenshot of the entire screen.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
screenshot = sandbox.computer_use.screenshot.take_full_screen()
print(f"Screenshot size: {screenshot.width}x{screenshot.height}")

# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(True)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const screenshot = await sandbox.computerUse.screenshot.takeFullScreen();
console.log(`Screenshot size: ${screenshot.width}x${screenshot.height}`);

// With cursor visible
const withCursor = await sandbox.computerUse.screenshot.takeFullScreen(true);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
screenshot = sandbox.computer_use.screenshot.take_full_screen
puts "Screenshot size: #{screenshot.width}x#{screenshot.height}"

# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(show_cursor: true)
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
screenshot, err := sandbox.ComputerUse.Screenshot().TakeFullScreen(ctx, nil)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Screenshot captured, size: %d bytes\n", *screenshot.SizeBytes)

// With cursor visible
showCursor := true
withCursor, err := sandbox.ComputerUse.Screenshot().TakeFullScreen(ctx, &showCursor)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var screenshot = sandbox.computerUse.takeScreenshot();
Integer sizeBytes = screenshot.getSizeBytes();
System.out.println("Screenshot payload size: " + (sizeBytes != null ? sizeBytes + " bytes" : "n/a"));

// With cursor visible
var withCursor = sandbox.computerUse.takeScreenshot(true);
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot'
```

</TabItem>
</Tabs>

### Take region

Take a screenshot of a specific region.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
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: {screenshot.region.width}x{screenshot.region.height}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const region = { x: 100, y: 100, width: 300, height: 200 };
const screenshot = await sandbox.computerUse.screenshot.takeRegion(region);
console.log(`Captured region: ${screenshot.region.width}x${screenshot.region.height}`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
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: #{screenshot.region.width}x#{screenshot.region.height}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var screenshot = sandbox.computerUse.takeRegionScreenshot(100, 100, 300, 200);
Integer sizeBytes = screenshot.getSizeBytes();
System.out.println("Captured region, payload size: " + (sizeBytes != null ? sizeBytes + " bytes" : "n/a"));
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/region?x=1&y=1&width=1&height=1'
```

</TabItem>
</Tabs>

### Take compressed

Take a compressed screenshot of the entire screen.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import ScreenshotOptions

# Default compression
screenshot = sandbox.computer_use.screenshot.take_compressed()

# High quality JPEG
jpeg = sandbox.computer_use.screenshot.take_compressed(
    ScreenshotOptions(format="jpeg", quality=95, show_cursor=True)
)

# Scaled down PNG
scaled = sandbox.computer_use.screenshot.take_compressed(
    ScreenshotOptions(format="png", scale=0.5)
)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// 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
});
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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)
)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// 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);
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/compressed'
```

</TabItem>
</Tabs>

### Take compressed region

Take a compressed screenshot of a specific region.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
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(format="webp", quality=80, show_cursor=True)
)
print(f"Compressed size: {screenshot.size_bytes} bytes")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const region = { x: 0, y: 0, width: 800, height: 600 };
const screenshot = await sandbox.computerUse.screenshot.takeCompressedRegion(region, {
  format: 'webp',
  quality: 80,
  showCursor: true
});
console.log(`Compressed size: ${screenshot.size_bytes} bytes`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
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: "webp", quality: 80, show_cursor: true)
)
puts "Compressed size: #{screenshot.size_bytes} bytes"
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/region/compressed?x=1&y=1&width=1&height=1'
```

</TabItem>
</Tabs>

## Screen Recording

Computer Use supports screen recording capabilities, allowing you to capture desktop sessions for debugging, documentation, or automation workflows.

### 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:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
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"}
    )
)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
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' }
});
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
require 'daytona'

daytona = Daytona::Client.new
sandbox = daytona.create(
  snapshot: 'daytonaio/sandbox:0.6.0',
  name: 'my-sandbox',
  env_vars: { DAYTONA_RECORDINGS_DIR: '/home/daytona/my-recordings' }
)
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
import (
	"github.com/daytonaio/daytona/pkg/client"
	"github.com/daytonaio/daytona/pkg/types"
)

daytona := client.New()
envVars := map[string]string{
	"DAYTONA_RECORDINGS_DIR": "/home/daytona/my-recordings",
}

sandbox, err := daytona.Create(ctx, &types.CreateSandboxParams{
	Snapshot: "daytonaio/sandbox:0.6.0",
	Name:     "my-sandbox",
	EnvVars:  envVars,
})
if err != nil {
	log.Fatal(err)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
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);
}
```

</TabItem>
</Tabs>

### Start Recording

Start a new screen recording session with an optional name identifier:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# Start recording with a custom name
recording = sandbox.computer_use.recording.start("test-1")
print(f"Recording started: {recording.id}")
print(f"File path: {recording.file_path}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// Start recording with a custom name
const recording = await sandbox.computerUse.recording.start('test-1');
console.log(`Recording started: ${recording.id}`);
console.log(`File path: ${recording.file_path}`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// Start recording with a custom name
name := "test-1"
recording, err := sandbox.ComputerUse.Recording().Start(ctx, &name)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Recording started: %s\n", *recording.Id)
fmt.Printf("File path: %s\n", *recording.FilePath)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// 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());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/start' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "test-1"
}'
```

</TabItem>
</Tabs>

### Stop Recording

Stop an active recording session by providing the recording ID:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# 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}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// Stop the recording
const stoppedRecording = await sandbox.computerUse.recording.stop(recording.id);
console.log(`Recording stopped: ${stoppedRecording.duration_seconds} seconds`);
console.log(`Saved to: ${stoppedRecording.file_path}`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// 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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// 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());
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/stop' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "id": "recording-id"
}'
```

</TabItem>
</Tabs>

### List Recordings

Get a list of all recordings in the sandbox:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
recordings_list = sandbox.computer_use.recording.list()
print(f"Total recordings: {len(recordings_list.recordings)}")
for rec in recordings_list.recordings:
    print(f"- {rec.name}: {rec.duration_seconds}s ({rec.file_size_bytes} bytes)")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const recordingsList = await sandbox.computerUse.recording.list();
console.log(`Total recordings: ${recordingsList.recordings.length}`);
recordingsList.recordings.forEach(rec => {
  console.log(`- ${rec.name}: ${rec.duration_seconds}s (${rec.file_size_bytes} bytes)`);
});
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
recordings_list = sandbox.computer_use.recording.list
puts "Total recordings: #{recordings_list.recordings.length}"
recordings_list.recordings.each do |rec|
  puts "- #{rec.name}: #{rec.duration_seconds}s (#{rec.file_size_bytes} bytes)"
end
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
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.Name, *rec.DurationSeconds, *rec.FileSizeBytes)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
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)"
    );
}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings'
```

</TabItem>
</Tabs>

### Get Recording

Get details about a specific recording:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
recording_detail = sandbox.computer_use.recording.get("recording-id")
print(f"Recording: {recording_detail.name}")
print(f"Status: {recording_detail.status}")
print(f"Duration: {recording_detail.duration_seconds}s")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const recordingDetail = await sandbox.computerUse.recording.get('recording-id');
console.log(`Recording: ${recordingDetail.name}`);
console.log(`Status: ${recordingDetail.status}`);
console.log(`Duration: ${recordingDetail.duration_seconds}s`);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
recording_detail = sandbox.computer_use.recording.get(id: 'recording-id')
puts "Recording: #{recording_detail.name}"
puts "Status: #{recording_detail.status}"
puts "Duration: #{recording_detail.duration_seconds}s"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
recordingDetail, err := sandbox.ComputerUse.Recording().Get(ctx, "recording-id")
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Recording: %s\n", *recordingDetail.Name)
fmt.Printf("Status: %s\n", *recordingDetail.Status)
fmt.Printf("Duration: %.2fs\n", *recordingDetail.DurationSeconds)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
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");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}'
```

</TabItem>
</Tabs>

### Delete Recording

Delete a recording by ID:

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
sandbox.computer_use.recording.delete("recording-id")
print("Recording deleted successfully")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
await sandbox.computerUse.recording.delete('recording-id');
console.log('Recording deleted successfully');
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
sandbox.computer_use.recording.delete(id: 'recording-id')
puts 'Recording deleted successfully'
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
err := sandbox.ComputerUse.Recording().Delete(ctx, "recording-id")
if err != nil {
	log.Fatal(err)
}

fmt.Println("Recording deleted successfully")
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
sandbox.computerUse.deleteRecording("recording-id");
System.out.println("Recording deleted successfully");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}' \
  --request DELETE
```

</TabItem>
</Tabs>

### 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.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# 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)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// 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);
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# 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)
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// 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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
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);
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}/download' \
  --output local_recording.mp4
```

</TabItem>
</Tabs>

:::tip[Streaming Downloads]
All SDK implementations stream the recording file directly to disk without loading the entire content into memory. This allows you to download large recordings (hundreds of MB or even GB) efficiently without running out of memory.

- **Python**: Streams in 64KB chunks using `httpx`
- **TypeScript**: Uses Node.js `pipeline()` with backpressure handling
- **Ruby**: Uses Typhoeus streaming with `on_body` callbacks
- **Go**: Uses `io.Copy()` with 32KB internal buffer
- **Java**: The OpenAPI client streams the response body into a temporary file via OkHttp
:::

### 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:

1. Navigate to your sandboxes in the Daytona Dashboard
2. Click the action menu (three dots) for your sandbox
3. 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

:::tip
The recording dashboard runs on a private port and is automatically secured. No additional authentication is required once you access it through the Daytona Dashboard.
:::

## Display operations

### Get info

Get information about the displays.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
info = sandbox.computer_use.display.get_info()
print(f"Primary display: {info.primary_display.width}x{info.primary_display.height}")
print(f"Total displays: {info.total_displays}")
for i, display in enumerate(info.displays):
    print(f"Display {i}: {display.width}x{display.height} at {display.x},{display.y}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const info = await sandbox.computerUse.display.getInfo();
console.log(`Primary display: ${info.primary_display.width}x${info.primary_display.height}`);
console.log(`Total displays: ${info.total_displays}`);
info.displays.forEach((display, index) => {
  console.log(`Display ${index}: ${display.width}x${display.height} at ${display.x},${display.y}`);
});
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
info = sandbox.computer_use.display.info
puts "Primary display: #{info.primary_display.width}x#{info.primary_display.height}"
puts "Total displays: #{info.total_displays}"
info.displays.each_with_index do |display, i|
  puts "Display #{i}: #{display.width}x#{display.height} at #{display.x},#{display.y}"
end
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
info, err := sandbox.ComputerUse.Display().GetInfo(ctx)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Displays: %v\n", info["displays"])
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
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()
        );
    }
}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/display/info'
```

</TabItem>
</Tabs>

### Get windows

Get the list of open windows.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
windows = sandbox.computer_use.display.get_windows()
print(f"Found {windows.count} open windows:")
for window in windows.windows:
    print(f"- {window.title} (ID: {window.id})")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const windows = await sandbox.computerUse.display.getWindows();
console.log(`Found ${windows.count} open windows:`);
windows.windows.forEach(window => {
  console.log(`- ${window.title} (ID: ${window.id})`);
});
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
windows = sandbox.computer_use.display.windows
puts "Found #{windows.count} open windows:"
windows.windows.each do |window|
  puts "- #{window.title} (ID: #{window.id})"
end
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
result, err := sandbox.ComputerUse.Display().GetWindows(ctx)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Open windows: %v\n", result["windows"])
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
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() + ")");
    }
}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/display/windows'
```

</TabItem>
</Tabs>
