Self-hosted virtual browser that streams Chromium via WebRTC
A single Go binary that launches a Chromium instance on a remote server and streams it to your local browser via WebRTC, accessible over SSH tunnel.
- π Single static binary - high-performance Go + GStreamer
- β‘ Buttery smooth 60 FPS - ultra-low latency streaming
- π Auto-downloads correct Chromium build for your OS
- π₯ Native GStreamer VP8 encoding (Mimicking Neko architecture)
- π Full audio support via PulseAudio + Opus codec
- π Secure over SSH tunnel (no cloud dependency)
- π±οΈ Full interaction support (Mouse, Keyboard, Scroll, Shortcuts)
- πΎ Persistent browser profile (cookies, bookmarks, passwords)
- βοΈ Hot-reloadable resolution, FPS, and bitrate
- π§ Simple CLI (start, stop, status)
# Install dependencies (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install -y xvfb xdotool pulseaudio libgstreamer1.0-dev \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
gstreamer1.0-pulseaudio
# Clone the repository
git clone https://github.com/zulfikawr/vbrowser.git
cd vbrowser
# Build
make build# On your remote server
./vbrowser start
# In another terminal (or from local machine)
ssh -L 7070:localhost:7070 user@remote-server
# Open in your local browser
# http://localhost:7070- Go 1.21+ (for building)
- GStreamer 1.0+:
libgstreamer1.0-devand plugins (base, good, bad, ugly) - PulseAudio:
pulseaudioandgstreamer1.0-pulseaudio - Xvfb & xdotool:
sudo apt-get install xvfb xdotool - ~500MB disk space for Chromium
- ~500MB RAM
- Any modern browser with WebRTC support
- SSH access to server
Default config location: ~/.config/vbrowser/config.json
{
"server": {
"host": "127.0.0.1",
"port": 7070
},
"browser": {
"auto_download": true,
"window_width": 1920,
"window_height": 1080
},
"stream": {
"video_codec": "vp8",
"target_fps": 60,
"max_bitrate_kbps": 8000
}
}See configs/default.json for all options.
Start the vbrowser daemon:
vbrowser start [flags]
Flags:
-f, --foreground Run in foreground (don't daemonize)
--port int Override server port
--no-download Skip Chromium auto-downloadStop the running daemon:
vbrowser stopShow daemon status:
vbrowser statusOutput:
β vbrowser is running
PID: 12345
URL: http://127.0.0.1:7070
Chromium: /home/user/.local/share/vbrowser/chromium/chrome
Display: :99 (1920x1080)
Print version info:
vbrowser versionmake buildmake testmake lintGOOS=linux GOARCH=amd64 go build -o dist/vbrowser-linux-amd64 ./cmd/vbrowservbrowser/
βββ cmd/vbrowser/ # Main entry point
βββ internal/
β βββ browser/ # Chromium management & download
β βββ capture/ # Legacy capture (keeping for reference)
β βββ cmd/ # CLI commands
β βββ config/ # Configuration
β βββ platform/ # Platform-specific code
β βββ process/ # PID file management
β βββ stream/ # WebRTC streaming
βββ pkg/
β βββ gst/ # Native GStreamer CGo bindings
β βββ server/ # HTTP server & signaling
βββ configs/ # Example configs
sudo apt-get install xvfb xdotool pulseaudio libgstreamer1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-pulseaudioChange port in config or use --port flag:
./vbrowser start --port 8080Check logs:
./vbrowser start --foreground --log-level debug- Check WebSocket connection in browser console
- Verify Chromium is running:
ps aux | grep chrome - Check Xvfb is running:
ps aux | grep Xvfb - Check GStreamer pipeline is active in logs.
Contributions welcome! Please read CONTRIBUTING.md first.
MIT License - see LICENSE file for details.
- m1k1o/neko - Architecture inspiration for low-latency GStreamer streaming
- pion/webrtc - Pure Go WebRTC implementation
- chromedp - Chrome DevTools Protocol
- GStreamer - Multimedia framework
Built by @zulfikawr