Stream your Windows desktop with near-zero latency, multi-core dirty tracking, and native ZRLE compression.
Quick Start · Why vncrs · Features · Examples · Performance · Extensibility
Traditional VNC servers on Windows (like TigerVNC, TightVNC, or UltraVNC) rely on heavy C++ installers, legacy GDI display hooks, or continuous full-frame CPU diffing that hogs 15–25% of your processor.
vncrs solves this with a modern, pure Rust architecture:
- 0ms CPU dirty detection by reading hardware damage hints directly from the Windows Desktop Window Manager (DWM) compositor.
- Zero-copy frame swapping using a buffer ping-pong pool that eliminates gigabytes of memory copies per second.
- Multi-core Rayon fallback with 128-bit SIMD chunk diffing when hardware hints are unavailable.
- Instant embeddability into any Rust application with a single
cargo add vncrs.
- Zero-Copy Capture Pipeline — Windows Graphics Capture (WGC) frames are swapped via pointer exchange, recycling allocations with zero heap churn and no redundant zeroing memsets.
- TigerVNC Continuous Updates Push Engine — Full support for RFB pseudo-encoding
-313and Fence-312. Streams frames continuously at display refresh rate without waiting for client RTT pull requests. - Tight Encoding with SIMD JPEG & Palette — Prioritizes RFB Tight (ID 7) with instant solid fill (
0x80), SIMD-accelerated JPEG (0x90) for video/gradients, and palette deflate for UI/text. - Hardware-Driven Dirty Rects — Consumes native compositor damage regions, cutting dirty scanning CPU usage to nearly 0%.
- SIMD 32-Byte Diffing & Fast Sampling — 32-byte chunk vector diffing and 5-point tile fast rejection when hardware compositor hints are absent.
- Native ZRLE & SIMD Zlib Compression — Hardware-accelerated
zlib-rsdeflate engine with 128-bit solid tile fast path, achieving up to 95% bandwidth reduction. - Rect Coalescing — Merges adjacent and overlapping damage tiles to minimize protocol packet overhead and zlib stream flushes.
- Full Input Injection — Mouse movement, 4-way scrolling, control keys, and full Cyrillic/Unicode keyboard mapping via
enigo. - Hardened Against DoS — Bounded message parsers (prevents OOM exploits), constant-time challenge auth, and no misaligned pointer casts.
- Use
vncrswhen: You need high-FPS, low-latency remote desktop streaming on Windows without installing heavy third-party services, or want to embed remote desktop sharing inside your own Rust app or bot. - Not for: Linux/macOS display servers (this crate leverages Windows Graphics Capture and Windows input synthesis APIs).
cargo add vncrsuse vncrs::{VncServer, VncServerConfig};
use vncrs::capture::windows::WindowsCapture;
use vncrs::input::enigo_input::EnigoInput;
fn main() -> vncrs::Result<()> {
let config = VncServerConfig::new()
.port(5900)
.password("secret")
.name("My Workstation")
.max_fps(60);
let capture = WindowsCapture::new()?;
let input = EnigoInput::new();
let mut server = VncServer::new(capture, input, config);
server.listen()
}Connect with any standard VNC viewer:
vncviewer 127.0.0.1:5900Three ready-to-run examples are included:
Minimal server listening on port 5900:
cargo run --example simple_serverShares your screen with remote input strictly disabled:
cargo run --example headlessFeature-complete command-line server with CLI flags:
cargo run --example full_server -- --port 5900 --password secret --fps 60 --name "Workstation"| Flag | Default | Description |
|---|---|---|
-p, --port <PORT> |
5900 |
TCP listen port |
--password <PASS> |
None |
Access password (max 8 characters per RFB standard) |
-n, --name <NAME> |
"Rust VNC" |
Display name broadcasted to connecting viewers |
--fps <FPS> |
60 |
Max frame rate (1–240 FPS) |
--view-only |
false |
Disallow remote keyboard and mouse input |
-v, --verbose |
false |
Enable structured log output |
| Encoding | RFB ID | Best For | Compression Ratio | CPU Overhead |
|---|---|---|---|---|
| Tight | 7 |
Standard high-FPS streaming, video & 3D (TigerVNC, Remmina, noVNC) | Exceptional (~90-98% reduction) | Ultra-Low (Instant solid fill & SIMD JPEG) |
| ZRLE | 16 |
UI/Desktop text with lossless requirements | Highest lossless (~95% reduction) | Ultra-Low (128-bit solid tile fast path) |
| Hextile | 5 |
Low-latency local networks | Moderate (~60% reduction) | Minimal |
| Zlib | 6 |
Streaming over constrained connections | High (~80% reduction) | Moderate |
| Raw | 0 |
Loopback / ultra-high bandwidth | 0% (raw BGRA stream) | Zero |
- Hardware Compositor Dirty Hints: Unlike legacy servers that compute pixel-by-pixel diffs on the CPU,
vncrsreads dirty regions reported by the Windows compositor D3D11 surface. - Zero-Copy Ring Pool: Framebuffers are swapped via
std::mem::swapbetween the capture worker thread and the server session loop, preventing megabytes ofmemcpyper frame. - Rect Coalescing Engine: Blends fragmented damage tiles into optimized bounding boxes, drastically cutting down TCP packet headers and zlib stream resets.
VncServerConfig uses a type-safe builder pattern:
let config = vncrs::VncServerConfig::new()
.port(5900)
.password("pass1234")
.name("Gaming Rig")
.max_fps(144) // Clamped to [1, 240]
.tile_size(64); // Clamped to [16, 256]use std::sync::atomic::Ordering;
let server = vncrs::VncServer::new(capture, input, config);
let running = server.running_flag();
ctrlc::set_handler(move || {
running.store(false, Ordering::Relaxed);
}).ok();
server.listen()?;Feed frames from DirectX games, virtual monitors, or custom pipelines:
pub trait ScreenCapture {
fn width(&self) -> u16;
fn height(&self) -> u16;
fn stride(&self) -> usize;
/// Swap buffer with zero allocations. Returns Ok(true) if a fresh frame is ready.
fn swap_frame(&mut self, buf: &mut Vec<u8>) -> vncrs::Result<bool>;
/// Optional hardware dirty rect hints from compositor
fn take_dirty_hints(&mut self, _out: &mut Vec<CaptureRect>) -> bool { false }
}Direct remote control events to an isolated sandbox or game automation framework:
pub trait InputHandler {
fn move_mouse(&mut self, x: u16, y: u16);
fn mouse_button(&mut self, button: u8, pressed: bool);
fn scroll(&mut self, direction: ScrollDirection);
fn key_event(&mut self, keysym: u32, down: bool);
}- Network Boundary: Standard VNC (RFB 3.8) challenge-response authentication uses 56-bit DES without transport layer encryption. For untrusted public networks, route through an SSH tunnel or WireGuard / Tailscale VPN:
ssh -L 5900:127.0.0.1:5900 user@remote-windows-host
- View-Only Mode: Pass
vncrs::input::NoopInputwhen only observation is needed to lock out any remote input injection. - Memory Safety: Every packet parser enforces strict bounds (e.g. 1 MB limit on clipboard text) to neutralize remote buffer allocation attacks.
Distributed under the MIT License.