A modern, lightweight VNC client library for React, Next.js, Node.js, and Bun with TypeScript support
npm install react-vnc-lib

A modern, lightweight VNC client library for React applications with working VNC authentication!
- 🎯 Working VNC Authentication - RFC 6143 compliant with proper DES implementation
- ⚡ WebSocket Support - Real-time VNC connections over WebSocket
- 🔒 Secure - Supports both VNC authentication and "None" security types
- 🌐 Hetzner Compatible - Tested with Hetzner VNC web console
- 📱 Responsive - Auto-scaling and touch/mouse input support
- 🎨 Modern React - Hooks-based API with TypeScript support
- 🔧 Flexible - Works with any VNC server (TightVNC, RealVNC, etc.)
``bash`
npm install react-vnc-libor
yarn add react-vnc-lib
`tsx
import React from 'react';
import { useVNC } from 'react-vnc-lib';
function VNCViewer() {
const { connect, disconnect, state, canvasRef } = useVNC({
url: 'wss://your-vnc-server.com/websockify',
password: 'your-vnc-password', // Now works properly!
viewOnly: false,
scale: 1.0,
debug: true
});
return (
Status: {state.connected ? 'Connected' : state.connecting ? 'Connecting' : 'Disconnected'}
Error: {state.error}
}export default VNCViewer;
`
This library now has properly working VNC authentication based on RFC 6143 compliance! Here's what was fixed:
`tsx`
interface VNCClientOptions {
url: string; // WebSocket URL (ws:// or wss://)
username?: string; // Optional username (for future auth types)
password?: string; // VNC password (now works properly!)
viewOnly?: boolean; // Read-only mode (default: false)
quality?: number; // Image quality 1-10 (default: 6)
compression?: number; // Compression level 1-10 (default: 2)
autoResize?: boolean; // Auto resize canvas (default: true)
scale?: number; // Display scale factor (default: 1.0)
timeout?: number; // Connection timeout ms (default: 10000)
debug?: boolean; // Enable debug logging (default: false)
}
`tsx
import { VNCClient } from 'react-vnc-lib';
// Direct VNC client usage
const client = new VNCClient({
url: 'wss://vnc.example.com/websockify',
password: 'secret123',
debug: true
});
// Event handling
client.on('connected', () => console.log('VNC Connected!'));
client.on('disconnected', () => console.log('VNC Disconnected'));
client.on('error', (event) => console.error('VNC Error:', event.data.message));
// Connect
await client.connect();
// Send input
client.sendKeyEvent({ key: 'Enter', down: true, code: 'Enter' });
client.sendPointerEvent({ x: 100, y: 100, buttons: 1 });
// Disconnect
client.disconnect();
`
`tsx
function VNCViewer() {
const { connect, state } = useVNC({
url: 'wss://vnc.example.com/websockify',
password: 'secret'
});
const handleConnect = async () => {
try {
await connect();
} catch (error) {
console.error('Connection failed:', error.message);
// Handle specific error types
if (error.message.includes('Authentication failed')) {
alert('Invalid password');
} else if (error.message.includes('Connection timeout')) {
alert('Server not reachable');
}
}
};
return (
Error: {state.error}
}🐛 Troubleshooting
$3
1. Authentication Fails
`
Enable debug mode and check console for challenge/response hex values
Ensure password is correct and server supports VNC Authentication
`2. Connection Refused
`
Check WebSocket URL format (ws:// or wss://)
Verify server is running and accessible
Check for CORS issues in browser
`3. WebSocket Close Codes
`
1006: Connection lost unexpectedly
1003: Server rejected connection due to invalid data
1002: Protocol error
`$3
Enable debug logging to see detailed connection information:
`tsx
const { connect } = useVNC({
url: 'wss://vnc.example.com/websockify',
password: 'secret',
debug: true // Enables detailed console logging
});
`🏗️ Architecture
$3
1. WebSocket Connection - Establish WebSocket to VNC server
2. Version Handshake - Negotiate RFB protocol version (3.8)
3. Security Negotiation - Choose authentication method
4. Authentication - VNC password authentication with DES encryption
5. Initialization - Exchange client/server capabilities
6. Protocol Messages - Framebuffer updates, input events, etc.$3
This library uses a proper DES implementation for VNC that:
- Implements correct bit reversal (RFC 6143 Errata ID 4951)
- Uses full DES algorithm with standard S-boxes and permutations
- Based on proven working VNC client implementations (noVNC, established clients)
- Maintains RFC 6143 compliance and compatibility with all major VNC servers📜 License
MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- RFC 6143 specification authors
- VNC community for protocol documentation
- RFC 6143 Errata ID 4951 for the critical bit reversal fix
- Vidar Holen's VNC DES analysis for documenting the VNC DES quirks
- Dave Zimmerman and Jef Poskanzer for DES implementation guidance
- Open source VNC implementations for reference
---
Note: This library implements VNC authentication correctly based on RFC 6143 with the required errata fixes. Previous versions had authentication issues that are now resolved in v1.3.0+.
Features
- 🚀 Modern TypeScript - Full type safety and modern ES2020+ features
- ⚡ Minimal Dependencies - Zero runtime dependencies, React as optional peer dependency
- 🎯 WebSocket Based - Real-time VNC protocol over WebSocket
- 🖱️ Full Input Support - Keyboard and mouse event handling
- 📱 Responsive - Canvas-based rendering with scaling support
- 🔧 Configurable - Extensive customization options
- 🎨 React Components - Ready-to-use React hook and component
Installation
`bash
With npm
npm install react-vnc-libWith yarn
yarn add react-vnc-libWith pnpm
pnpm add react-vnc-libWith bun
bun add react-vnc-lib
`$3
For React usage, install the peer dependencies:
`bash
npm install react react-dom
`Quick Start
$3
`tsx
import React from 'react';
import { VNCViewer } from 'react-vnc-lib';function App() {
return (
url="ws://localhost:6080"
autoConnect={true}
scale={0.8}
viewOnly={false}
showStatus={true}
/>
);
}export default App;
`$3
`tsx
import React from 'react';
import { useVNC } from 'react-vnc-lib';function CustomVNCViewer() {
const {
state,
connect,
disconnect,
canvasRef,
error,
loading
} = useVNC({
url: 'ws://localhost:6080',
autoConnect: true,
debug: true
});
return (
Status: {state.connected ? 'Connected' : 'Disconnected'}
{error && Error: {error}}
);
}
`$3
`javascript
import { VNCClient } from 'react-vnc-lib';const client = new VNCClient({
url: 'ws://localhost:6080',
username: 'user',
password: 'password',
debug: true
});
// Set up event listeners
client.on('connected', () => {
console.log('Connected to VNC server');
});
client.on('error', (event) => {
console.error('VNC Error:', event.data.message);
});
client.on('framebuffer-update', (event) => {
console.log('Received framebuffer update');
// Handle framebuffer data
});
// Connect
await client.connect();
// Send keyboard input
client.sendKeyEvent({
key: 'a',
code: 'KeyA',
down: true
});
// Send mouse input
client.sendPointerEvent({
x: 100,
y: 100,
buttons: 1
});
// Disconnect
client.disconnect();
`API Reference
$3
Main VNC client class for establishing connections and handling protocol communication.
#### Constructor
`typescript
new VNCClient(options: VNCClientOptions)
`#### Options
`typescript
interface VNCClientOptions {
url: string; // WebSocket URL to VNC server
username?: string; // Username for authentication
password?: string; // Password for authentication
viewOnly?: boolean; // Enable view-only mode (default: false)
quality?: number; // Quality setting 0-9 (default: 6)
compression?: number; // Compression level 0-9 (default: 2)
autoResize?: boolean; // Auto-resize canvas (default: true)
scale?: number; // Scale factor 0.1-2.0 (default: 1.0)
timeout?: number; // Connection timeout ms (default: 10000)
debug?: boolean; // Enable debug logging (default: false)
}
`#### Methods
-
connect(): Promise - Connect to VNC server
- disconnect(): void - Disconnect from server
- sendKeyEvent(event: VNCKeyEvent): void - Send keyboard event
- sendPointerEvent(event: VNCPointerEvent): void - Send mouse event
- requestFramebufferUpdate(incremental?: boolean): void - Request screen update
- getState(): VNCConnectionState - Get current connection state
- on(event: string, handler: VNCEventHandler): void - Add event listener
- off(event: string, handler: VNCEventHandler): void - Remove event listener$3
React hook for VNC client integration.
`typescript
const vncState = useVNC(options: UseVNCOptions);
`#### Returns
`typescript
interface UseVNCReturn {
client: VNCClient | null;
state: VNCConnectionState;
connect: () => Promise;
disconnect: () => void;
sendKeyEvent: (event: VNCKeyEvent) => void;
sendPointerEvent: (event: VNCPointerEvent) => void;
requestUpdate: (incremental?: boolean) => void;
canvasRef: React.RefObject;
error: string | null;
loading: boolean;
}
`$3
Ready-to-use React component with built-in UI.
`typescript
url="ws://localhost:6080"
autoConnect={true}
showStatus={true}
className="my-vnc-viewer"
style={{ width: '100%', height: '500px' }}
/>
`#### Props
All
VNCClientOptions plus:-
className?: string - Custom CSS class
- style?: React.CSSProperties - Custom styles
- showStatus?: boolean - Show connection status (default: true)
- showLoading?: boolean - Show loading indicator (default: true)
- disableKeyboard?: boolean - Disable keyboard input
- disableMouse?: boolean - Disable mouse input
- autoFocus?: boolean - Auto-focus canvas (default: true)
- connectButtonText?: string - Custom connect button text
- disconnectButtonText?: string - Custom disconnect button textEvents
The VNC client emits the following events:
-
connecting - Connection attempt started
- connected - Successfully connected
- disconnected - Connection closed
- error - Connection or protocol error
- framebuffer-update - Screen update received
- server-cut-text - Clipboard data from server
- bell - Bell/beep from server
- resize - Server resolution changedAdvanced Usage
$3
`typescript
const client = new VNCClient({
url: 'ws://localhost:6080',
username: 'admin',
password: 'secretpassword'
});
`$3
`typescript
const client = new VNCClient({
url: 'ws://localhost:6080',
quality: 9, // Highest quality
compression: 0 // No compression
});
`$3
`typescript
url="ws://localhost:6080"
scale={0.5} // Scale down for mobile
autoResize={true} // Auto-resize to fit
disableKeyboard={true} // Disable for touch-only
/>
`Server Setup
This library connects to VNC servers via WebSocket. You'll need a WebSocket-to-VNC proxy such as:
- websockify
- noVNC proxy
- Custom WebSocket proxy
Example with websockify:
`bash
Install websockify
pip install websockifyStart proxy (connects WS port 6080 to VNC port 5900)
websockify 6080 localhost:5900
`Browser Compatibility
- Chrome/Chromium 80+
- Firefox 75+
- Safari 13+
- Edge 80+
Node.js Compatibility
- Node.js 16+
- Bun 1.0+
Development
`bash
Clone repository
git clone https://github.com/sepandy/react-vnc-lib.git
cd react-vnc-libInstall dependencies
npm installStart development mode
npm run devBuild library
npm run buildRun tests
npm testLint code
npm run lint
``Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.
See CHANGELOG.md for a list of changes.
- 📖 Documentation
- 🐛 Issue Tracker
- 💬 Discussions
- Inspired by noVNC
- Built with modern TypeScript and React best practices