Production-ready HTTP-to-OSC bridge for VRChat control
Features • Quick Start • API Reference • Security • Documentation
VRChat OSC Bridge is a secure, production-ready HTTP server that translates HTTP requests into OSC (Open Sound Control) messages for VRChat. Perfect for building chatbots, automation tools, or external VRChat integrations.
Built for production with enterprise-grade security:
- API key authentication on all endpoints
- Smart rate limiting to prevent abuse
- Input validation & sanitization
- Comprehensive audit logging
- CORS protection & secure defaults
- Chatbox Control - Send messages, show typing indicators
- Avatar Movement - Control walking, running, jumping, looking
- Avatar Parameters - Set custom avatar parameters
- World Navigation - Launch into specific VRChat worlds
- Screen Capture - Take screenshots remotely
- Audio Recording - Capture audio streams
- AI Transcription - Real-time speech-to-text with Whisper
- API Key Authentication - Required for all endpoints
- Rate Limiting - Configurable per-endpoint limits
- Input Validation - Pydantic schemas prevent injection attacks
- Audit Logging - Track all sensitive operations
- Whitelist Protection - Raw OSC addresses restricted
- CORS Configuration - Controlled cross-origin access
- Environment-based config - No hardcoded secrets
- Detailed error messages - Easy debugging
- Comprehensive logging - Production-ready monitoring
- Clean API design - RESTful endpoints
- Python client included -
lexis_control.py
- Python 3.8 or higher
- VRChat with OSC enabled
- pip or virtualenv
# 1. Clone the repository
git clone https://github.com/kushiemoon-dev/vrchat-osc-bridge.git
cd vrchat-osc-bridge
# 2. Create virtual environment (recommended)
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# 3. Install dependencies
pip install -r requirements.txt
# 4. Configure environment
cp .env.example .env
# 5. Generate secure API key
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Copy output to .env as API_KEY=...
# 6. Enable OSC in VRChat
# VRChat → Settings → OSC → Enable
# 7. Start the bridge
python bridge.py# Send a test message
curl -X POST http://localhost:8765/chatbox \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"message": "Hello VRChat!"}'All endpoints require API key authentication via Bearer token:
Authorization: Bearer YOUR_API_KEYSend Message
POST /chatbox
{
"message": "Hello world!",
"direct": true, # Send immediately (true) or open keyboard (false)
"notify": true # Play notification sound
}Typing Indicator
POST /chatbox/typing
{
"typing": true # Show/hide typing indicator
}Move Avatar
POST /move
{
"vertical": 1.0, # -1 to 1 (backward/forward)
"horizontal": 0.0, # -1 to 1 (left/right)
"look": 0.0, # -1 to 1 (turn left/right)
"duration": 0.5 # How long to move (seconds)
}Jump
POST /jumpRun Toggle
POST /run
{
"running": true
}Voice Toggle
POST /voice
{
"unmute": true
}POST /avatar/parameter
{
"name": "VoiceLevel", # Alphanumeric names only
"value": 0.5 # -1.0 to 1.0
}POST /launch
{
"world_id": "wrld_xxx-xxx-xxx", # VRChat world ID
"url": "vrchat://launch?..." # Or direct launch URL
}Screenshot
GET /screenshot
# Returns JPEG imageAudio Recording
POST /listen
{
"duration": 5 # Seconds (max 30)
}
# Returns WAV audio fileSpeech Transcription
POST /transcribe
{
"duration": 5, # Seconds (max 30)
"device_id": null # Optional: specific audio device
}
# Returns: {"text": "transcribed speech", "language": "en"}List Audio Devices
GET /listen/devices
# Returns list of available audio input devicesHealth Check
GET /health
# Returns: {"status": "ok", "service": "vrchat-bridge"}Raw OSC (Advanced)
POST /raw
{
"address": "/chatbox/input", # Whitelisted addresses only
"args": ["message", true]
}| Endpoint | Limit | Reason |
|---|---|---|
| Default | 60/min, 1000/hour | General protection |
/chatbox |
30/min | Prevent spam |
/screenshot |
5/hour | Resource intensive |
/listen |
10/hour | Resource intensive |
/transcribe |
10/hour | AI processing costs |
/launch |
5/hour | User experience |
/raw |
10/min | Security critical |
All sensitive configuration via environment variables (.env):
# Required
API_KEY=your_secure_32_char_key_here
# Optional
BRIDGE_HOST=0.0.0.0 # IP to bind to
BRIDGE_PORT=8765 # Port to listen on
VRC_IP=127.0.0.1 # VRChat OSC IP
VRC_PORT=9000 # VRChat OSC port
RATE_LIMIT_PER_MINUTE=60 # Global rate limit
RATE_LIMIT_PER_HOUR=1000 # Global rate limit
ALLOWED_ORIGINS=* # CORS origins (comma-separated)
FLASK_ENV=production # production or development
DEBUG=false # Debug mode
WHISPER_MODEL=base # Whisper model (tiny/base/small/medium/large)
WHISPER_DEVICE=cpu # cpu or cuda-
Generate Strong API Keys
python3 -c "import secrets; print(secrets.token_urlsafe(32))" -
Never Commit Secrets
.envis gitignored- Use
.env.exampleas template
-
Restrict Network Access
- Use firewall rules
- Bind to specific IPs only
- Consider VPN for remote access
-
Use HTTPS in Production
- Deploy behind nginx/caddy
- Use Let's Encrypt certificates
- Never expose HTTP to internet
-
Monitor Logs
- Check audit logs regularly
- Set up log aggregation
- Alert on suspicious patterns
-
Rotate API Keys
- Monthly rotation recommended
- Immediate rotation if exposed
- Use different keys per client
All inputs are validated and sanitized:
- Chatbox: Max 1000 chars, UTF-8 validated
- Movement: Clamped to -1.0 to 1.0 range
- Parameters: Alphanumeric names only
- OSC Addresses: Strict whitelist (
/chatbox/,/input/,/avatar/parameters/) - World IDs: Regex validated (
wrld_format) - Durations: Capped at 30 seconds
Firewall Configuration (Linux)
# iptables - Allow only from specific IP
sudo iptables -A INPUT -p tcp --dport 8765 -s TRUSTED_IP -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8765 -j DROP
# firewalld
sudo firewall-cmd --permanent --add-port=8765/tcp --source=TRUSTED_IP
sudo firewall-cmd --reloadWindows Firewall
- Allow Python through Windows Firewall
- Restrict to "Private Networks" only
The included lexis_control.py provides a Python interface:
import os
os.environ['BRIDGE_HOST'] = 'localhost'
os.environ['BRIDGE_PORT'] = '8765'
os.environ['API_KEY'] = 'your_api_key'
from lexis_control import chatbox, move, jump, set_parameter
# Send message
chatbox("Hello from Python!")
# Move forward for 1 second
move(vertical=1.0, duration=1.0)
# Jump
jump()
# Set avatar parameter
set_parameter("VoiceLevel", 0.8)401 Unauthorized
- Missing or invalid API key
- Check
Authorization: Bearer ...header - Verify API key in
.env
400 Bad Request
- Invalid input data
- Check request schema
- Validate parameter types/ranges
429 Too Many Requests
- Rate limit exceeded
- Wait before retrying
- Adjust limits in
.envif needed
500 Internal Server Error
- Server-side issue
- Check logs for details
- File issue on GitHub
Custom Rate Limits
# In .env
RATE_LIMIT_PER_MINUTE=120 # Double the default
RATE_LIMIT_PER_HOUR=5000CORS Configuration
# In .env
ALLOWED_ORIGINS=https://example.com,https://app.example.comDebug Mode
# In .env
DEBUG=true
FLASK_ENV=development# Install dev dependencies
pip install -r requirements.txt
# Test authentication
curl http://localhost:8765/health # Should fail (401)
curl -H "Authorization: Bearer YOUR_KEY" http://localhost:8765/health # Should succeed
# Test rate limiting
for i in {1..100}; do curl -H "Authorization: Bearer YOUR_KEY" http://localhost:8765/health; donevrchat-osc-bridge/
├── bridge.py # Main server
├── lexis_control.py # Python client
├── requirements.txt # Dependencies
├── .env.example # Config template
├── .gitignore # Git exclusions
├── LICENSE # MIT License
└── README.md # This file
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- VRChat for the OSC protocol
- python-osc for OSC implementation
- Flask for HTTP server
- Whisper for speech recognition
- Built for Lexis
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ for the VRChat community