How It Works
Playwriter’s relay server runs on the host machine alongside Chrome. A traforo tunnel exposes it to the internet through Cloudflare, giving you a secure public URL. Remote machines connect through this URL to control Chrome.Host Machine Setup
The host machine runs Chrome with the Playwriter extension installed.Install the Chrome extension
Enable extension on tabs
Click the extension icon on any tab you want to make controllable (icon turns green)
Keep this terminal running, or use tmux for persistent operation:
About the Tunnel ID (-t flag)
The -t flag sets the tunnel ID, which becomes the URL subdomain:
-t my-machine→https://my-machine-tunnel.traforo.dev- Omit
-t→ random 8-character UUID is generated
Remote Machine Setup
Set environment variables and use Playwriter normally.Using the CLI (Recommended)
Using the MCP Server
The CLI with the skill is recommended. Use MCP only if your AI assistant doesn’t support skills.
Using the Playwright API
Connect programmatically:Use Cases
Control a Remote Mac Mini
Run Chrome on a headless machine and control it from your laptop. The Mac mini runs the tunnel persistently via tmux. Benefits:- Automate browser tasks from anywhere
- Run tests against real Chrome on macOS
- Manage web apps remotely
- Keep browser state between sessions
Fix Issues for Users Remotely
The user starts the tunnel, shares the URL + token with you, and you can see exactly what they see. Workflow:- User runs:
npx -y traforo -p 19988 -t support-session -- npx -y playwriter serve --token <shared-token> - User shares:
https://support-session-tunnel.traforo.devand token - You connect and navigate their tabs, inspect elements, take screenshots
- User sees Chrome’s automation banner and can revoke access by closing the terminal
Control Multiple Machines
Each machine runs its own tunnel with a unique-t ID and the same token. Loop over tunnel URLs to run commands across the fleet:
Development from VM or Devcontainer
Your code runs in a VM or devcontainer but Chrome runs on the host. The tunnel bridges the gap without needing host networking or port forwarding. See Docker Setup below.LAN Access (Without Traforo)
If both machines are on the same network, skip traforo and connect directly via IP address. Find your host IP with:- macOS/Linux:
ifconfig | grep "inet " - Windows:
ipconfig
Docker / Devcontainer Setup
The relay server must run on the same machine as Chrome. The Chrome extension connects to the relay via localhost WebSocket, and the/extension endpoint only accepts connections from 127.0.0.1.
Architecture
Start relay on host
On the host machine (where Chrome is running):Using
--host localhost binds to 127.0.0.1 so no token is needed. Docker containers reach it through host.docker.internal.Platform Support for host.docker.internal
| Platform | Works out of the box? | Notes |
|---|---|---|
| macOS (Docker Desktop) | Yes | Supported since Docker Desktop 18.03 |
| Windows (Docker Desktop) | Yes | Supported since Docker Desktop 18.03 |
| Linux (Docker Engine) | No | Requires --add-host (see below) |
Linux Configuration
On Linux,host.docker.internal is not provided automatically. Add it explicitly:
host-gateway special value (Docker Engine 20.10+) resolves to the host’s gateway IP. On older Docker versions, replace it with the bridge gateway IP directly (typically 172.17.0.1, find with ip route | grep default).
MCP from Docker
If your AI assistant or MCP client runs inside Docker:--add-host=host.docker.internal:host-gateway.
Security
Traforo URLs are Non-Guessable
Each tunnel gets a unique ID (random UUID by default). Nobody can discover your tunnel by scanning.Token Authentication Required
Whenplaywriter serve binds to 0.0.0.0, it refuses to start without a --token.
Authentication checks:
- HTTP requests to
/cli/*and/recording/*needAuthorization: Bearer <token>or?token=<token> - WebSocket connections to
/cdpneed?token=<token> - Without correct token, relay returns 401
Extension Endpoint is Localhost-Only
The/extension WebSocket endpoint only accepts connections from 127.0.0.1 or ::1. A remote attacker cannot impersonate the extension even with the token.
No Open Ports
Traforo uses an outbound WebSocket to Cloudflare. The host machine needs no inbound ports open. Works behind NATs, firewalls, and corporate networks.Visible Automation
Chrome shows an automation banner on controlled tabs.Instant Revocation
Closing the terminal immediately disconnects the tunnel.Environment Variables Reference
| Variable | Description | Example |
|---|---|---|
PLAYWRITER_HOST | Remote relay URL or IP | https://x-tunnel.traforo.dev192.168.1.10host.docker.internal |
PLAYWRITER_TOKEN | Authentication token | MY_SECRET_TOKEN |
PLAYWRITER_PORT | Override relay port (default: 19988) | 8080 |
PLAYWRITER_PORT is not needed when using traforo tunnels, which handle port mapping automatically.Security Best Practices
Troubleshooting
Cannot connect to remote relay server
Error:Cannot connect to remote relay server at <host>
Solutions:
- Verify relay is running on host:
playwriter serve --token <secret> - Check tunnel URL is correct (matches
-tflag) - Test tunnel directly:
curl https://my-machine-tunnel.traforo.dev/version - Check host firewall allows outbound WebSocket connections
Connection times out
Possible causes:- Relay server crashed (check with
ps aux | grep playwriter) - Network connectivity issues
- Tunnel disconnected (restart traforo command)
- Restart the relay + tunnel on host
- Use
playwriter logfileto check relay logs - Test connectivity:
curl https://my-machine-tunnel.traforo.dev/version
Token authentication failed
Error:401 Unauthorized
Solution: Ensure PLAYWRITER_TOKEN matches the token in playwriter serve --token <secret>
Docker: Connection refused to host.docker.internal
Error:ECONNREFUSED
Solutions:
- Verify relay is running on host:
playwriter serve --host localhost - On Linux, add
--add-host=host.docker.internal:host-gateway - Check firewall rules aren’t blocking port 19988
- Test from container:
curl http://host.docker.internal:19988/version
Next Steps
Configuration
Learn about all environment variables and configuration options
CLI Usage
Use the recommended CLI workflow for better control