Remote Desktop

RDP

Automate remote desktops via RDP by redirecting nut.js operations to a remote machine.

Overview

The @nut-tree/plugin-rdp plugin connects to a remote machine via RDP and redirects nut.js operations (screen capture, mouse, keyboard, clipboard) to the remote session. This lets you use the same nut.js APIs you already know to automate a remote desktop — image search, OCR, keyboard input, mouse control, and clipboard all work transparently over the RDP connection.

Remote Screen

Capture and search the remote desktop

useRemoteScreen()

Remote Input

Send mouse and keyboard events to the remote machine

useRemoteKeyboard()

Remote Clipboard

Read and write the remote clipboard

useRemoteClipboard()

Installation

typescript
npm install @nut-tree/plugin-rdp

Subscription Required

This package is included in Solo and Team subscription plans.

Quick Reference

connect

connect(params: ConnectionParameters): Promise<RemoteConnection>
Promise<RemoteConnection>

Connect to a remote machine via RDP and return provider registration functions

useRemote

useRemote()
void

Activate all remote providers at once (screen, keyboard, mouse, clipboard)

useRemoteScreen

useRemoteScreen()
void

Redirect screen capture and search to the remote desktop

useRemoteKeyboard

useRemoteKeyboard()
void

Redirect keyboard input to the remote machine

useRemoteMouse

useRemoteMouse()
void

Redirect mouse control to the remote machine

useRemoteClipboard

useRemoteClipboard()
void

Redirect clipboard operations to the remote machine

isConnected

isConnected(): boolean
boolean

Check whether the RDP connection is still active

disconnect

disconnect()
void

Close the RDP connection


Usage

Connecting

Use connect() to establish an RDP session. The returned object contains provider registration functions and connection management helpers:

typescript
import { connect } from "@nut-tree/plugin-rdp";

const remote = await connect({
    hostname: process.env.REMOTE_HOSTNAME,
    port: parseInt(process.env.REMOTE_PORT),
    username: process.env.REMOTE_USERNAME,
    password: process.env.REMOTE_PASSWORD,
    ignoreCertificate: true,
});

console.log(`Connected: ${remote.isConnected()}`);

All Providers at Once

Use useRemote() to redirect all nut.js operations to the remote machine in a single call:

typescript
import { screen, keyboard, mouse, clipboard, imageResource, Key } from "@nut-tree/nut-js";
import "@nut-tree/nl-matcher";
import { connect } from "@nut-tree/plugin-rdp";

const remote = await connect({
    hostname: process.env.REMOTE_HOSTNAME,
    port: parseInt(process.env.REMOTE_PORT),
    username: process.env.REMOTE_USERNAME,
    password: process.env.REMOTE_PASSWORD,
});

// Redirect all nut.js operations to the remote machine
remote.useRemote();

screen.config.confidence = 0.87;
screen.config.resourceDirectory = "./resources";

// All nut.js APIs now operate on the remote desktop
await screen.waitFor(imageResource("start.png"), 10000, 1000);
await keyboard.type(Key.LeftWin);
await keyboard.type("notepad");
await keyboard.type(Key.Enter);
await keyboard.type("Hello from nut.js!");

Individual Providers

You can also activate providers selectively. For example, redirect only screen capture and keyboard while keeping the local mouse:

typescript
const remote = await connect({ /* ... */ });

// Only redirect screen and keyboard
remote.useRemoteScreen();
remote.useRemoteKeyboard();

// mouse and clipboard still operate locally

Remote Clipboard

With useRemoteClipboard(), the standard clipboard API reads from and writes to the remote machine's clipboard:

typescript
import { clipboard, keyboard, Key } from "@nut-tree/nut-js";

// Select all and copy on the remote machine
await keyboard.type(Key.LeftControl, Key.A);
await keyboard.type(Key.LeftControl, Key.C);

// Read the remote clipboard
const text = await clipboard.getContent();
console.log(`Remote clipboard: ${text}`);

// Write to the remote clipboard and paste
await clipboard.setContent("Pasted from local!");
await keyboard.type(Key.LeftControl, Key.V);

Disconnecting

Always close the RDP connection when done. Use a try/finally block to ensure cleanup:

typescript
const remote = await connect({ /* ... */ });
remote.useRemote();

try {
    // ... automation ...
} finally {
    remote.disconnect();
}

Connection Parameters

hostname

hostname: string
required

Hostname or IP address of the remote machine

port

port: number
required

RDP port (typically 3389)

username

username: string
required

Login username for the remote machine

password

password: string
required

Login password for the remote machine

ignoreCertificate

ignoreCertificate?: boolean
optional

Skip TLS certificate validation. Useful for self-signed certificates in development.

enableDebugLog

enableDebugLog?: boolean
optional

Enable detailed RDP protocol debug logging


Combining with Other Plugins

The RDP plugin works seamlessly with other nut.js plugins. Since it redirects the low-level providers, higher-level features like image search (via nl-matcher) and screen recording operate on the remote desktop automatically.

With Screen Recording

Combine RDP with @nut-tree/plugin-screenrecording to record the remote session. The screen recorder captures whatever the active screen provider returns, so after calling useRemoteScreen(), recordings capture the remote desktop:

typescript
import { screen, keyboard, Key } from "@nut-tree/nut-js";
import "@nut-tree/nl-matcher";
import { connect } from "@nut-tree/plugin-rdp";
import { useScreenRecorder } from "@nut-tree/plugin-screenrecording";

useScreenRecorder();

const remote = await connect({ /* ... */ });
remote.useRemote();

await screen.startRecording({ fps: 30, bufferSeconds: 5 });

try {
    // ... remote automation ...
} catch (e) {
    // Save recording on failure
    await screen.stopRecording({ outputPath: "./error.mp4" });
    throw e;
} finally {
    remote.disconnect();
}

await screen.discardRecording();

Use @nut-tree/nl-matcher for image-based automation on the remote desktop. Prepare reference images by taking screenshots of the remote machine's UI elements:

typescript
import { screen, mouse, imageResource, centerOf, straightTo } from "@nut-tree/nut-js";
import "@nut-tree/nl-matcher";
import { connect } from "@nut-tree/plugin-rdp";

const remote = await connect({ /* ... */ });
remote.useRemote();

screen.config.confidence = 0.87;
screen.config.resourceDirectory = "./resources";

// Wait for and click a UI element on the remote desktop
const target = await screen.waitFor(
    imageResource("submit-button.png"),
    10000,
    1000,
    { providerData: { validateMatches: true } },
);
await mouse.move(straightTo(centerOf(target)));
await mouse.leftClick();

Best Practices

Connection Management

  • Always wrap automation in try/finally and call disconnect() in the finally block
  • Store credentials in environment variables — never hardcode them
  • Use isConnected() to verify the connection is still alive before critical operations
  • Add initial sleep() after connecting to allow the remote desktop to fully render

Security

Only use ignoreCertificate: true in development or trusted environments. In production, ensure proper TLS certificates are configured on the remote machine.

Network Latency

RDP automation depends on network conditions. Consider increasing timeouts for screen.waitFor() when automating over high-latency connections.

Was this page helpful?