# Displays

**Page:** kit/displays

[Download Raw Markdown](./kit/displays.md)

---

# Displays

**Your desktop applications are URLs.** Run VS Code, browsers, LibreOffice, any GUI program—accessible from your phone, tablet, laptop, or TV. Just open the URL.

Every Hoody container includes **hoody-display**, transforming your entire Linux desktop into a web-native interface with zero client installation.

---

## What You Can Do

**hoody-display** provides complete desktop access through HTTP:

- **🖥️ Full Desktop Environments** - Run any GUI application via HTML5 client
- **📱 Universal Access** - Phone, tablet, laptop, TV—anything with a browser
- **👥 Multiplayer Sessions** - Multiple users viewing/controlling same desktop simultaneously
- **🎨 50+ Customization Options** - Configure via URL parameters (themes, performance, input)
- **📸 Screenshot API** - Capture desktop state as PNG/JPEG programmatically
- **🖱️ Computer Use API** - Full mouse, keyboard, and window control over HTTP (dozens of endpoints)
- **🔧 Zero Installation** - No VNC client, no RDP, just browser
- **⚡ Hardware Acceleration** - H264 video encoding for smooth graphics
- **📋 Clipboard Sync** - Copy/paste between local and remote automatically


**Access Control**: By default, display URLs are open to anyone who has the cryptographic URL. Configure [Proxy Permissions →](/foundation/proxy/permissions/) to add authentication (IP whitelist, passwords, JWT tokens) when needed.


---

## API Endpoints Summary

**Official Technical Reference:**

For complete endpoint documentation with all parameters, responses, and examples:

**Web Client Interface:**
- **[GET /](/api/displays/web-client/)** - HTML5 display client with 50+ URL customization parameters
  - [UI & Theming](/api/displays/ui-theming/) - `dark_mode`, `decorations`, `toolbar`, `floating_menu`, `title`
  - [Performance & Encoding](/api/displays/performance/) - `encoding`, `bandwidth_limit`, `video`, `quality`
  - [Input & Clipboard](/api/displays/input-clipboard/) - `keyboard_layout`, `swap_keys`, `clipboard`, `keyboard`
  - [Session Sharing](/api/displays/session-sharing/) - `sharing`, `steal`, `reconnect`, `readonly`
  - [Feature Flags](/api/displays/feature-flags/) - `sound`, `file_transfer`, `printing`
  - [Debugging](/api/displays/debugging/) - `debug_main`, `debug_network`, `debug_keyboard`, `debug_mouse`

**Screenshot & Thumbnail API:**
- **[GET /api/v1/display/screenshot](/api/displays/screenshots/)** - Capture new full-resolution screenshot
- **[GET /api/v1/display/screenshot/last](/api/displays/screenshots/)** - Get most recent screenshot without capturing
- **[GET /api/v1/display/screenshot/\{timestamp\}](/api/displays/screenshots/)** - Get historical screenshot by timestamp
- **[GET /api/v1/display/screenshot/info](/api/displays/screenshots/)** - Get metadata only (no image)
- **[GET /api/v1/display/thumbnail](/api/displays/screenshots/)** - Capture new lightweight preview
- **[GET /api/v1/display/thumbnail/last](/api/displays/screenshots/)** - Get latest thumbnail
- **[GET /api/v1/display/thumbnail/\{timestamp\}](/api/displays/screenshots/)** - Get historical thumbnail

**System Information:**
- **[GET /api/v1/display/health](/api/displays/health/)** - Service health check
- **[GET /api/v1/display/info](/api/displays/screenshots/)** - Display info with screenshot list
- **[GET /api/v1/display/screenshots](/api/displays/screenshots/)** - List all available screenshots with metadata
- **[GET /api/v1/display/screenshot/last/info](/api/displays/screenshots/)** - Get latest screenshot metadata without capturing new one

**Mouse Control:**
- **POST /api/v1/display/mouse/click** - Click a mouse button
- **POST /api/v1/display/mouse/double-click** - Double-click
- **POST /api/v1/display/mouse/move** - Move cursor to absolute position
- **POST /api/v1/display/mouse/move-relative** - Move cursor by offset
- **POST /api/v1/display/mouse/down** - Press and hold mouse button
- **POST /api/v1/display/mouse/up** - Release mouse button
- **POST /api/v1/display/mouse/scroll** - Scroll
- **GET /api/v1/display/mouse/location** - Get current cursor position

**Keyboard Control:**
- **POST /api/v1/display/keyboard/type** - Type a string of text
- **POST /api/v1/display/keyboard/key** - Press key combinations (X11 keysym notation)
- **POST /api/v1/display/keyboard/key-down** - Hold a key down
- **POST /api/v1/display/keyboard/key-up** - Release a held key

**Window Management:**
- **GET /api/v1/display/windows** - List all windows
- **POST /api/v1/display/window/focus** - Focus/activate a window
- **POST /api/v1/display/window/move** - Move a window
- **POST /api/v1/display/window/resize** - Resize a window
- **POST /api/v1/display/window/minimize** - Minimize a window
- **POST /api/v1/display/window/close** - Close a window
- **POST /api/v1/display/window/raise** - Raise window to top
- **GET /api/v1/display/window/active** - Get active window ID
- **POST /api/v1/display/window/search** - Search windows by title pattern
- **GET /api/v1/display/window/\{windowId\}/geometry** - Get window position and size
- **GET /api/v1/display/window/\{windowId\}/name** - Get window title
- **GET /api/v1/display/window/\{windowId\}/properties** - Get extended window properties

**Compound Actions (Computer Use):**
- **POST /api/v1/display/input/click-at** - Move cursor and click
- **POST /api/v1/display/input/type-at** - Move, click, and type in one operation
- **POST /api/v1/display/input/drag** - Drag from one position to another
- **POST /api/v1/display/input/select** - Select a range via click + shift-click
- **POST /api/v1/display/input/act** - Execute one action with optional screenshot
- **POST /api/v1/display/input/wait** - Wait with optional screenshot
- **POST /api/v1/display/input/batch** - Execute a sequence of actions atomically
- **POST /api/v1/display/input/reset** - Emergency release all held inputs
- **GET /api/v1/display/input/display-geometry** - Get display dimensions

---

## Core Capabilities

### 1. Desktop as a URL

**Every container can run multiple display instances—one per application:**

```
https://{project}-{container}-display-1.{server}.containers.hoody.icu
https://{project}-{container}-display-2.{server}.containers.hoody.icu
https://{project}-{container}-display-3.{server}.containers.hoody.icu
```

**Recommended pattern: One display per application**

- `display-1` - Your main IDE (VS Code)
- `display-2` - Web browser (Firefox/Chrome)
- `display-3` - Office applications (LibreOffice)
- `display-4` - Graphics editor (GIMP)
- `display-5` - Database tools

**Why separate displays matter:**

Each display runs independently with its own:
- Screen resolution
- Window manager state
- Application set
- Performance profile

**Access any display from any browser**—phone, tablet, laptop, TV. No installation. No configuration. Just open the URL.

**Terminal integration:** When you use [`terminal-5`](/kit/terminals/), it automatically connects to `display-5` (`:5` in X11 terms). This makes GUI programs work seamlessly—run `firefox` in terminal-5, and it appears in display-5.

**Manual display selection:** Set the `DISPLAY` environment variable to target a specific display:

```bash
# In any terminal
export DISPLAY=:5

# Now GUI programs open in display-5
firefox &  # Opens in display-5
code .     # Opens in display-5
```

This flexibility lets you organize applications across displays while controlling them from any terminal.

### 2. Access from Literally Anywhere

**Your phone is now a full computer:**

Same URL on different devices:
- **Laptop browser** → Full desktop experience
- **Phone browser** → Same desktop, touch-optimized
- **Tablet** → Perfect for presentations
- **TV** → Display on big screen
- **Smart watch** → View monitoring dashboards
- **Smart glasses** (future) → AR overlays of your infrastructure

**Because everything is HTTP, device capabilities don't limit you.** Your phone didn't get more powerful—it became a window into infinite compute.

### 3. Multiplayer Desktop Sessions

**Share the URL and everyone sees/controls the same desktop:**

```
https://{project}-{container}-display-1.{server}.containers.hoody.icu/?sharing=true
```

Multiple users connecting:
- ✅ See the same screen in real-time
- ✅ Can all type and click simultaneously  
- ✅ Cursors show who's doing what
- ✅ Changes reflect instantly for everyone

**Perfect for:**
- Team debugging (everyone sees the error)
- Teaching (instructor and students share desktop)
- Pair programming (both using same IDE)
- Customer support (solve issues together)

**See:** [Multiplayer by Default →](/vision/multiplayer/) for collaboration philosophy.

### 4. Extensive Customization

**Configure the entire experience via URL parameters:**

```txt
# Read-only dashboard
?readonly=true&decorations=false&toolbar=false&reconnect=true

# Low-bandwidth mode
?encoding=jpeg&bandwidth_limit=1000000&video=false&sound=false

# Collaborative session
?sharing=true&steal=false

# macOS user setup
?swap_keys=true&keyboard_layout=us

# Dark mode with floating menu
?floating_menu=true&dark_mode=true
```

**Over 50 parameters** control UI, performance, input, features, and behavior.

**See:** [Web Client Interface →](/api/displays/web-client/) for complete customization reference.

### 5. Screenshot API

**Programmatically capture desktop state:**

```bash
# Capture current screenshot
GET /screenshot?displayId=1

# Get as base64 for AI vision
GET /screenshot?base64=true

# Lightweight thumbnail
GET /thumbnail/last
```

**Use cases:**
- AI vision analysis of UI states
- Automated testing verification
- Documentation generation
- Monitoring dashboards
- Time-lapse recordings

**See:** [Screenshot API →](/api/displays/screenshots/)

### 6. Embeddable Everywhere

**Because displays are URLs, they're `<iframe>`able:**

```html
<!-- Embed desktop in webpage -->
<iframe src="https://{project}-{container}-display-1.{server}.containers.hoody.icu" 
        width="1280" height="720" />

<!-- Multiple displays in one page -->
<iframe src="https://prod-container-display-1.hoody.icu" />
<iframe src="https://staging-container-display-1.hoody.icu" />
<iframe src="https://dev-container-display-1.hoody.icu" />
```

**Build custom dashboards** by composing iframes. Your infrastructure IS the UI.

**See:** [Embeddability Revolution →](/vision/embeddability/)

---

## Why This Changes Everything

### Traditional Remote Desktop

```
RDP Client (installed) → RDP Server (configured) → Desktop (complex)
```

**Problems:**
- Client installation required (difficult on mobile devices)
- Port configuration and firewalls
- Not embeddable (can't iframe RDP)
- Single-user (one connection kicks others)
- AI can't see (binary protocol)
- Complex setup

### Hoody Displays

```
Any Browser → Display URL → Desktop (immediately)
```

**Advantages:**
- ✅ Zero installation (every device has browser)
- ✅ Zero port configuration (HTTPS port 443 through Hoody Proxy)
- ✅ Naturally embeddable (`<iframe src="display-url" />`)
- ✅ Multiplayer by default (share URL = instant collaboration)
- ✅ AI-accessible (HTTP + screenshot API)
- ✅ Observable (all HTTP, fully logged)
- ✅ Mobile-native (works on phones out-of-box)

### Desktop Applications on Mobile

**Your phone can now run:**

```javascript
// Phone browser opens display URL
https://{project}-{container}-display-1.{server}.containers.hoody.icu

// Inside that desktop:
- Full VS Code IDE
- Chrome browser with DevTools
- Terminal sessions
- Database tools
- Any Linux GUI application
```

**The device doesn't matter. The URL is the computer.**

---

## Computer Use API

**This is where Hoody gets dangerous.** Full programmatic control of any desktop over HTTP — mouse, keyboard, windows, compound actions. Dozens of endpoints. Every one of them a REST call.

AI agents, automation scripts, remote operators — anything that can make an HTTP request can now drive a GUI application with the precision of a human, at the speed of software.

### Mouse Control

Pixel-precise cursor control at any speed:



```bash
# Move cursor to position
hoody display move --x 640 --y 480 --display-id 10 -c <container-id>

# Click at current position
hoody display click --button 1 --display-id 10 -c <container-id>

# Double-click
hoody display double-click --button 1 --display-id 10 -c <container-id>

# Scroll down
hoody display scroll --direction down --clicks 5 --display-id 10 -c <container-id>
```


```typescript


const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });
const containerClient = await client.withContainer({ id: CONTAINER_ID, project_id: PROJECT_ID, server: SERVER });

// Move cursor to position
await containerClient.display.input.mouseMove({ x: 960, y: 540 }, { displayId: 10 });

// Click the left mouse button
await containerClient.display.input.mouseClick({ button: 1 }, { displayId: 10 });

// Double-click
await containerClient.display.input.mouseDoubleClick({ button: 1 }, { displayId: 10 });

// Scroll down
await containerClient.display.input.mouseScroll({ direction: 'down', clicks: 3 }, { displayId: 10 });

// Get current cursor position
const location = await containerClient.display.input.mouseLocation({ displayId: 10 });
```


```bash
# Click the left mouse button
curl -X POST "https://{project}-{container}-display-1.{server}.containers.hoody.icu/api/v1/display/mouse/click" \
  -H "Content-Type: application/json" \
  -d '{"button": 1}'

# Double-click
curl -X POST ".../api/v1/display/mouse/double-click" \
  -d '{"button": 1}'

# Move cursor to absolute position
curl -X POST ".../api/v1/display/mouse/move" \
  -d '{"x": 960, "y": 540}'

# Move cursor by relative offset
curl -X POST ".../api/v1/display/mouse/move-relative" \
  -d '{"x": 50, "y": -20}'

# Press and hold mouse button (for drag setup)
curl -X POST ".../api/v1/display/mouse/down" \
  -d '{"button": 1}'

# Release held mouse button
curl -X POST ".../api/v1/display/mouse/up" \
  -d '{"button": 1}'

# Scroll down
curl -X POST ".../api/v1/display/mouse/scroll" \
  -d '{"direction": "down", "clicks": 3}'

# Get current cursor position
curl ".../api/v1/display/mouse/location"
```



**Available mouse buttons:** `1` (left), `2` (middle), `3` (right)

### Keyboard Control

Type text and send any key combination the OS understands:



```bash
# Type text
hoody display type --text "Hello, World!" --delay 50 --display-id 10 -c <container-id>

# Press key combination
hoody display key --keys "ctrl+s" --display-id 10 -c <container-id>

# Hold key
hoody display key-down --key "Shift_L" --hold-ms 2000 --display-id 10 -c <container-id>
```


```typescript
// Type a string of text
await containerClient.display.input.keyboardType({ text: 'Hello, world!' }, { displayId: 10 });

// Press key combinations (X11 keysym notation)
await containerClient.display.input.keyboardKey({ keys: ['ctrl+c'] }, { displayId: 10 });
await containerClient.display.input.keyboardKey({ keys: ['ctrl+shift+t'] }, { displayId: 10 });

// Hold a key down
await containerClient.display.input.keyboardKeyDown({ key: 'shift' }, { displayId: 10 });

// Release a held key
await containerClient.display.input.keyboardKeyUp({ key: 'shift' }, { displayId: 10 });
```


```bash
# Type a string of text
curl -X POST "https://{project}-{container}-display-1.{server}.containers.hoody.icu/api/v1/display/keyboard/type" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello, world!"}'

# Press key combinations (X11 keysym notation)
curl -X POST ".../api/v1/display/keyboard/key" \
  -d '{"keys": ["ctrl+c"]}'

curl -X POST ".../api/v1/display/keyboard/key" \
  -d '{"keys": ["ctrl+shift+t"]}'

curl -X POST ".../api/v1/display/keyboard/key" \
  -d '{"keys": ["super+l"]}'

# Hold a key down (for sustained modifier keys)
curl -X POST ".../api/v1/display/keyboard/key-down" \
  -d '{"key": "shift"}'

# Release a held key
curl -X POST ".../api/v1/display/keyboard/key-up" \
  -d '{"key": "shift"}'
```



### Window Management

Enumerate, target, and fully control any window on the desktop:



```bash
# List visible windows
hoody display list --only-visible --display-id 10 -c <container-id>

# Focus a window
hoody display focus --window-id 83886081 --display-id 10 -c <container-id>

# Move a window
hoody display move --window-id 83886081 --x 100 --y 100 --display-id 10 -c <container-id>

# Resize a window
hoody display resize --window-id 83886081 --width 1024 --height 768 --display-id 10 -c <container-id>

# Search for windows by name
hoody display search --pattern "Firefox" --name --only-visible --display-id 10 -c <container-id>
```


```typescript
// List all windows
const windows = await containerClient.display.listWindows({ displayId: 10 });

// Get the currently active window ID
const activeId = await containerClient.display.input.windowActive({ displayId: 10 });

// Search windows by title pattern
const matches = await containerClient.display.input.windowSearch({ pattern: 'Visual Studio Code' }, { displayId: 10 });

// Focus/activate a window
await containerClient.display.input.windowFocus({ windowId: 12345678 }, { displayId: 10 });

// Move a window to new position
await containerClient.display.input.windowMove({ windowId: 12345678, x: 100, y: 50 }, { displayId: 10 });

// Resize a window
await containerClient.display.input.windowResize({ windowId: 12345678, width: 1280, height: 800 }, { displayId: 10 });

// Close a window
await containerClient.display.input.windowClose({ windowId: 12345678 }, { displayId: 10 });
```


```bash
# List all windows
curl "https://{project}-{container}-display-1.{server}.containers.hoody.icu/api/v1/display/windows"

# Get the currently active window ID
curl ".../api/v1/display/window/active"

# Search windows by title pattern
curl -X POST ".../api/v1/display/window/search" \
  -H "Content-Type: application/json" \
  -d '{"pattern": "Visual Studio Code"}'

# Focus/activate a window
curl -X POST ".../api/v1/display/window/focus" \
  -d '{"windowId": 12345678}'

# Move a window to new position
curl -X POST ".../api/v1/display/window/move" \
  -d '{"windowId": 12345678, "x": 100, "y": 50}'

# Resize a window
curl -X POST ".../api/v1/display/window/resize" \
  -d '{"windowId": 12345678, "width": 1280, "height": 800}'

# Minimize a window
curl -X POST ".../api/v1/display/window/minimize" \
  -d '{"windowId": 12345678}'

# Raise window to top of z-order
curl -X POST ".../api/v1/display/window/raise" \
  -d '{"windowId": 12345678}'

# Close a window
curl -X POST ".../api/v1/display/window/close" \
  -d '{"windowId": 12345678}'

# Get window position and size
curl ".../api/v1/display/window/12345678/geometry"

# Get window title
curl ".../api/v1/display/window/12345678/name"

# Get extended window properties
curl ".../api/v1/display/window/12345678/properties"
```



### Compound Actions (Computer Use)

The high-level interface for computer use workflows. These endpoints combine multiple primitives into single atomic operations — exactly what AI agents need:



```bash
# Click at specific position
hoody display click-at --x 640 --y 480 --button 1 --display-id 10 -c <container-id>

# Type at position
hoody display type-at --x 300 --y 400 --text "Hello" --delay 50 --display-id 10 -c <container-id>

# Drag between positions
hoody display drag --start-x 100 --start-y 100 --end-x 300 --end-y 300 --button 1 --steps 50 --display-id 10 -c <container-id>

# Execute action with screenshot
hoody display act --action "mouse/click" --params '{"button":1}' --screenshot --screenshot-delay 200 --display-id 10 -c <container-id>
```


```typescript
// Click at specific position
await containerClient.display.input.clickAt({ x: 960, y: 540, button: 1 }, { displayId: 10 });

// Move, click, and type — fill a form field
await containerClient.display.input.typeAt({ x: 450, y: 320, text: 'user@example.com' }, { displayId: 10 });

// Drag from one position to another
await containerClient.display.input.drag({ startX: 100, startY: 200, endX: 500, endY: 200 }, { displayId: 10 });

// Execute action with post-action screenshot
const result = await containerClient.display.input.act({
  action: 'mouse/click',
  params: { button: 1 },
  screenshot: true,
}, { displayId: 10 });

// Execute a sequence of actions in one call
await containerClient.display.input.batch({
  actions: [
    { action: 'mouse/click', params: { button: 1 } },
    { action: 'wait', params: { ms: 500 } },
    { action: 'keyboard/type', params: { text: 'https://hoody.icu' } },
    { action: 'keyboard/key', params: { keys: ['Return'] } },
    { action: 'wait', params: { ms: 2000 } },
    { action: 'screenshot' },
  ],
}, { displayId: 10 });

// Emergency: release all held inputs
await containerClient.display.input.reset({ displayId: 10 });
```


```bash
# Move cursor and click in one call
curl -X POST "https://{project}-{container}-display-1.{server}.containers.hoody.icu/api/v1/display/input/click-at" \
  -H "Content-Type: application/json" \
  -d '{"x": 960, "y": 540, "button": 1}'

# Move, click, and type — all in one operation
# Perfect for filling form fields
curl -X POST ".../api/v1/display/input/type-at" \
  -d '{"x": 450, "y": 320, "text": "user@example.com"}'

# Drag from one position to another
curl -X POST ".../api/v1/display/input/drag" \
  -d '{"startX": 100, "startY": 200, "endX": 500, "endY": 200}'

# Select a range via click + shift-click
curl -X POST ".../api/v1/display/input/select" \
  -d '{"x": 200, "y": 150, "endX": 800, "endY": 150}'

# Execute a single action with optional post-action screenshot
curl -X POST ".../api/v1/display/input/act" \
  -d '{"action": "mouse/click", "params": {"button": 1}, "screenshot": true}'

# Wait (with optional screenshot to observe state)
curl -X POST ".../api/v1/display/input/wait" \
  -d '{"ms": 1500, "screenshot": true}'

# Execute a sequence of actions in one HTTP call
curl -X POST ".../api/v1/display/input/batch" \
  -H "Content-Type: application/json" \
  -d '{
    "actions": [
      {"action": "mouse/click", "params": {"button": 1}},
      {"action": "wait", "params": {"ms": 500}},
      {"action": "keyboard/type", "params": {"text": "https://hoody.icu"}},
      {"action": "keyboard/key", "params": {"keys": ["Return"]}},
      {"action": "wait", "params": {"ms": 2000}},
      {"action": "screenshot"}
    ]
  }'

# Emergency: release all held inputs (buttons, keys)
curl -X POST ".../api/v1/display/input/reset"

# Get display dimensions
curl ".../api/v1/display/input/display-geometry"
```



### Full Computer Use Workflow

**AI agent opens a browser, navigates, fills a form, submits:**

```javascript
const base = 'https://{project}-{container}-display-1.{server}.containers.hoody.icu';

// 1. Find the browser window
const windows = await fetch(`${base}/api/v1/display/windows`).then(r => r.json());
const browser = windows.find(w => w.name.includes('Firefox'));

// 2. Focus it
await fetch(`${base}/api/v1/display/window/focus`, {
  method: 'POST',
  body: JSON.stringify({ windowId: browser.id })
});

// 3. Navigate to URL via address bar
await fetch(`${base}/api/v1/display/input/batch`, {
  method: 'POST',
  body: JSON.stringify({
    actions: [
      { action: 'keyboard/key', params: { keys: ['ctrl+l'] } },  // Focus address bar
      { action: 'wait', params: { ms: 200 } },
      { action: 'keyboard/type', params: { text: 'https://app.example.com/login' } },
      { action: 'keyboard/key', params: { keys: ['Return'] } },
      { action: 'wait', params: { ms: 2000 } },                  // Wait for page load
      { action: 'screenshot' }                                    // Verify it loaded
    ]
  })
});

// 4. Fill in login form
await fetch(`${base}/api/v1/display/input/type-at`, {
  method: 'POST',
  body: JSON.stringify({ x: 640, y: 380, text: 'user@example.com' })
});

await fetch(`${base}/api/v1/display/input/type-at`, {
  method: 'POST',
  body: JSON.stringify({ x: 640, y: 450, text: 'supersecretpassword' })
});

// 5. Submit and capture result
const result = await fetch(`${base}/api/v1/display/input/act`, {
  method: 'POST',
  body: JSON.stringify({
    action: 'keyboard/key',
    params: { keys: ['Return'] },
    screenshot: true
  })
}).then(r => r.json());

// result.screenshot contains base64 PNG — send to vision model to verify login success
```

**This is full computer use.** Not CLI wrappers. Not browser automation. Actual pixel-level GUI control over HTTP, on any Linux application, in any window, driven by anything that can make a curl request.


**Batch for performance:** Combine multiple actions into a single `POST /api/v1/display/input/batch` call to minimize round-trips. Each action in a batch executes sequentially with optional waits between steps.



**Always call reset on failure:** If your automation script crashes mid-interaction, a key or mouse button may remain held down. Call `POST /api/v1/display/input/reset` to release all inputs before retrying.


---

## Common Workflows

### Personal Development Environment

**Access your full dev environment from any device:**

```bash
# Laptop: Configure display
https://dev-container-display-1.hoody.icu/?fontSize=14&swap_keys=true

# Phone (later): Same URL, same environment
https://dev-container-display-1.hoody.icu/?fontSize=14&swap_keys=true

# Tablet (during presentation): Same environment
https://dev-container-display-1.hoody.icu/?fontSize=16
```

**One computer. Accessible from phone, laptop, tablet, TV.** Not synced—actually the same running instance.

### Team Collaboration

**Multiple users working in same desktop:**

```javascript
// Setup: Create collaborative session
const displayUrl = 'https://{project}-{container}-display-1.{server}.containers.hoody.icu';
const collaborativeUrl = `${displayUrl}/?sharing=true&steal=false`;

// Share URL with team
// Everyone sees same desktop
// Everyone can:
// - Open files in shared VS Code
// - Type in shared terminal  
// - Click in shared browser
// - Edit in shared applications

// Real-time collaboration like Google Docs, but for your entire desktop
```

### Customer Support

**Support agent helps customer by joining their desktop:**

```bash
# Customer shares display URL
https://customer-issue-container-display-1.hoody.icu/?sharing=true

# Support agent opens URL on phone during commute
# Sees customer's desktop
# Types fix directly
# Issue resolved in 2 minutes

# No screen share setup
# No "can you see my screen?"
# Just shared desktop state
```

### Presentations and Demos

**Present live desktop to team:**

```txt
# Presenter URL (full control)
?sharing=true&steal=false&readonly=false

# Viewers URL (watch only)
?sharing=true&steal=false&readonly=true
```

Presenter controls desktop. Viewers watch in real-time. Perfect for:
- Product demos
- Architecture reviews
- Training sessions
- Live coding demonstrations

### AI Vision Integration

**Let AI see and analyze your desktop:**

```javascript
// 1. Capture screenshot via HTTP
const response = await fetch(
  'https://{project}-{container}-display-1.{server}.containers.hoody.icu/screenshot?base64=true'
);
const { image, info } = await response.json();

// 2. Send to a vision model via Hoody AI (any provider you've configured)
const analysis = await ai.chat.completions.create({
  model: 'your-vision-model',
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What errors do you see in this IDE?' },
      { type: 'image_url', image_url: { url: `data:image/png;base64,${image.data}` }}
    ]
  }]
});

// 3. AI describes what it sees
console.log(analysis.choices[0].message.content);
// "I see a syntax error on line 23: unclosed bracket..."
```

**AI can now see your desktop** and provide visual debugging, UI analysis, and accessibility testing.

### Monitoring Dashboards

**Embed multiple displays in monitoring dashboard:**

```html
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
  <!-- Production -->
  <iframe src="https://prod-container-display-1.hoody.icu/?readonly=true&toolbar=false" />
  
  <!-- Staging -->
  <iframe src="https://staging-container-display-1.hoody.icu/?readonly=true&toolbar=false" />
  
  <!-- Development -->
  <iframe src="https://dev-container-display-1.hoody.icu/?readonly=true&toolbar=false" />
</div>
```

**Live view of all environments.** No switching tabs. All visible at once.

---

## Use Cases

### Remote Work Without Limits

Work from café, beach, airport, hotel—anywhere with internet. Your desktop isn't on your laptop—it's in the URL. Laptop breaks? Use any device. Travel light, work heavy.

### Social Media Team Management

**20 brand accounts, one desktop, five team members:**

One container runs multiple browsers, each logged into different social accounts. All team members open the display URL. Everyone sees all 20 browsers. Coordinate without "whose turn to post?" or credential sharing.

**One computer is shared control center.** No individual logins. No syncing. Just shared desktop state.

### Development Across Devices

Start coding on laptop. Continue on tablet during commute. Finish on phone at café. Same VS Code. Same terminal. Same files. Not synced—same actual desktop.

### AI-First Development

AI agent joins your display URL:
1. Takes screenshots to see what you're working on
2. Types in your IDE via input API
3. Runs tests in your terminal
4. Debugs by seeing actual UI state

**AI and human as peers on same desktop.** Not AI suggesting—AI executing.

### Teaching and Training

Instructor's desktop URL shared with 30 students. Everyone sees the same screen. Instructor demonstrates. Students can take control when invited. Interactive learning at scale.

### Support Without Screen Share

Customer has issue. Shares display URL. Support agent opens URL on ANY device. Sees customer's desktop. Types fix. Issue resolved. No Zoom. No "can you click here?". Just shared desktop via URL.

---

## Best Practices

### Optimize for Your Network

**On fast connection:**
```txt
?encoding=h264&quality=90&video=true
```

**On slow/metered connection:**
```txt
?encoding=jpeg&quality=60&video=false&bandwidth_limit=500000
```

### Use Readonly for Presentations

**Prevent accidental input during demos:**

```txt
?readonly=true&steal=false&sharing=true
```

Viewers can't type or click. Perfect for presentations or monitoring dashboards.

### Configure Keyboard for Your OS

**macOS users need key swap:**

```txt
?swap_keys=true&keyboard_layout=us
```

Maps Cmd to Ctrl automatically, preserving muscle memory for copy/paste.

### Enable Reconnect for Stability

**Auto-reconnect on network interruption:**

```txt
?reconnect=true
```

Essential for mobile use (switching WiFi/cellular) or unreliable networks.

### Use Thumbnails for Galleries

**Build monitoring views with lightweight previews:**

```javascript
// Get thumbnail (small, fast)
const thumb = await fetch('.../thumbnail/last');

// Full screenshot only when needed
const full = await fetch('.../screenshot/last');
```

Thumbnails are 320px wide vs full 1920px—dramatically less bandwidth.

### Disable Features for Performance

**Turn off unused features:**

```txt
?sound=false&printing=false&clipboard=false&file_transfer=false
```

Reduces bandwidth and CPU usage. Enable only what you need.

---

## Useful Questions

### Can I really run desktop applications on my phone?

Yes! Your phone's browser becomes a window into a full Linux desktop. Run VS Code, LibreOffice, GIMP, browsers—any GUI application. The phone isn't running the apps—it's displaying a desktop that runs in the container. The heavy lifting happens on your server.

### What's the difference between display-1, display-2, etc.?

Each number is a separate desktop environment. `display-1` might show VS Code, `display-2` shows monitoring tools, `display-3` shows browsers. Each isolated, each accessible via its own URL. One container can have multiple desktops.

### How does multiplayer actually work without conflicts?

The display protocol synchronizes state automatically. When User A types, it updates the display server, which broadcasts to all connected clients including User B. Input is serialized (one keystroke at a time), but visual updates are instant for everyone. Like Google Docs for desktops.

### Can AI agents control GUI applications?

Yes — fully. The Computer Use API provides complete programmatic mouse and keyboard control over HTTP. AI agents can: 1) Capture screenshots via `GET /screenshot` to see desktop state, 2) Move and click the mouse at exact coordinates, 3) Type text and press key combinations, 4) Manage windows (focus, resize, move, close), 5) Chain compound actions via `POST /api/v1/display/input/batch` for complex multi-step workflows. This is one of Hoody's most powerful capabilities — see [Computer Use API](#computer-use-api) below.

### What happens if my internet drops while using a display?

With `?reconnect=true` (default), the client automatically reconnects when your connection returns. The desktop keeps running on the server—you just lost the view temporarily. When reconnected, you see current state (not what it was when you disconnected).

### Do displays work on touch devices like tablets?

Yes! The HTML5 client adapts to touch input automatically. Tap = click, pinch = zoom, two-finger scroll = scroll. Virtual keyboard available via `?keyboard=true`. Full desktop control from touch-only devices.

### Can I customize colors and themes?

Extensively. Control: floating menu style, window decorations, toolbar visibility, dark mode. All via URL parameters. Build your perfect visual environment.

**See:** [UI Theming →](/api/displays/ui-theming/)

### How much bandwidth does a display session use?

Depends on encoding and activity. H264 video: 2-5 Mbps for smooth graphics. JPEG static updates: 100-500 Kbps. Configure via: `?encoding=jpeg&quality=60&bandwidth_limit=1000000` to cap at 1 Mbps.

### Can I embed displays in my application?

Absolutely! Use iframes to embed container displays directly. Common patterns: dashboards showing live server states, documentation with interactive examples, customer portals with diagnostic desktops.

### What's the latency for remote displays?

Keep in mind that this isn't our priority for now, but we promise total smoothness with Displays, soon. As of now, typically 50-200ms depending on distance to server and network quality. H264 encoding optimized for smooth interaction. Good enough for coding, document editing, web browsing—not recommended for gaming or high-frequency trading.

---

## Troubleshooting

### Display Won't Load or Shows Black Screen

**Check container is running:**
```bash
curl "https://api.hoody.icu/api/v1/containers/{container_id}?runtime=true" \
  -H "Authorization: Bearer $HOODY_TOKEN"
```

Verify `runtime_info.displays` shows active display with PID.

**Common causes:**

1. **Container stopped** - Start it:
   ```bash
   curl -X POST "https://api.hoody.icu/api/v1/containers/{container_id}/start" \
     -H "Authorization: Bearer $HOODY_TOKEN"
   ```

2. **Display service not started** - Wait 30-60 seconds after container start for services to initialize

3. **Wrong display number** - Check container's `runtime_info.displays` for available display IDs

### Connection Drops Frequently

**Enable reconnect:**
```txt
?reconnect=true
```

**Reduce quality for stability:**
```txt
?quality=50&encoding=jpeg&video=false
```

**Check network:**
- Test on different WiFi/cellular
- Verify server connectivity
- Check firewall isn't blocking WebSocket

### Keyboard Not Working or Keys Wrong

**For macOS users:**
```txt
?swap_keys=true&keyboard_layout=us
```

**For other layouts:**
```txt
?keyboard_layout=gb  # UK
?keyboard_layout=de  # German
?keyboard_layout=fr  # French
```

**Enable virtual keyboard on touch devices:**
```txt
?keyboard=true
```

### Clipboard Not Syncing

**Enable clipboard if disabled:**
```txt
?clipboard=true
```

**Check browser permissions:**
- Browser may block clipboard access
- Try different browser
- Grant clipboard permissions when prompted

**Some browsers restrict clipboard for security.** Copy/paste within the remote desktop always works.

### Poor Performance or Lag

**Optimize encoding:**
```txt
# Fast connection
?encoding=h264&quality=90

# Slow connection  
?encoding=jpeg&quality=40&video=false
```

**Reduce bandwidth:**
```txt
?bandwidth_limit=500000  # 500 Kbps max
```

**Disable high-bandwidth features:**
```txt
?sound=false&video=false
```

**Check server load:**
```bash
# Query system resources
GET /api/v1/system/resources
```

### Can't Take Control (Readonly)

**Check URL parameter:**
```txt
?readonly=false  # Enable control
```

**Verify permissions:**
- Display might have proxy permissions restricting control
- Check container's proxy-permissions configuration
- Try removing permissions temporarily for testing

### Multiple Users Conflict

**Use session sharing:**
```txt
?sharing=true&steal=false
```

**Without this:**
- `sharing=false` allows only one user
- `steal=true` (default) lets new users kick old ones out

**For collaboration, enable sharing.**

---

## What's Next

**Explore other visual services:**


  
    Chrome automation as REST API—control browsers programmatically, scrape data, run tests.
    
    [Explore Browser →](/kit/browser/)
  
  
  
    Execute shell commands via HTTP—your terminal as an API, accessible everywhere.
    
    [Explore Terminals →](/kit/terminals/)
  
  
  
    VS Code instances via HTTP—spawn IDEs on-demand, share coding sessions.
    
    [Explore Code →](/kit/code/)
  


**Master display configuration:**
- **[Web Client →](/api/displays/web-client/)** - All 50+ customization parameters
- **[Screenshots →](/api/displays/screenshots/)** - Programmatic desktop capture
- **[Session Sharing →](/api/displays/session-sharing/)** - Collaboration modes

---

> **Your desktop is a URL.**  
> **Access from any device.**  
> **Share instantly.**  
> **Embed everywhere.**

**This is how desktops work in the HTTP era.**