Short answer
Yes, by design, if your browser game already talks to its own authoritative server over WebSocket. You ship that server as a Node.js 24 project, a Python 3.12 project, or a Linux x64 program (Go, Rust, Bun or anything that produces a runnable Linux binary), declare its TCP port, and list the exact website origins allowed to connect. Players connect over wss:// to a NetCraftGames gateway path of the form /play/<gameId>; TLS ends at the gateway and frames are forwarded to your server.
Packaging a Node, Python, Go or Rust server
The servers have Node.js 24 and Python 3.12 installed. They never run npm, pip or any other package manager, so the packages your server needs travel inside your upload, built for Linux. On your own computer, in the project folder:
- Node.js:
ncg pack . --node --install. It builds a folder with your code, the production packages for Linux x64 and a start script, then packs it. Nothing runs unless you pass--install. See the Node.js guide. - Python:
ncg pack . --python --install, which downloads wheels for Linux and Python 3.12 only (no source builds). See the Python guide. - Go:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o build/server ./cmd/server - Rust:
cargo build --release --target x86_64-unknown-linux-gnu
The image is Ubuntu 24.04, so a Linux program you build yourself must not need a newer glibc than 2.39. Whatever you use, the process must bind 0.0.0.0 on a fixed port, read secrets from the environment, and not start by downloading and running scripts.
What you provide
- The server archive as
.tar.gz(for Node and Python, the folderncg packbuilds). - The declared TCP port, a health route and a join probe with a known reply.
- Exact allowed browser origins, for example
https://play.example.com. - A WebSocket server. By default the gateway connects to
ws://<server>:<port>/. If your server answers at another path, such as/ws, you write that one path in the manifest aswsPath; you fix it, and nothing a player sends can change it. Details in the guide. - Not supported: Colyseus (it needs plain web requests before the WebSocket), and socket.io unless it is set to WebSocket only.
- Optional: a loopback JSON player-count endpoint so empty servers can be shut down.
Steps
- Build for LinuxFor Node or Python run
ncg pack . --node --install(or--python), which builds the packages for Linux x64. For Go or Rust build a Linux x86-64 program and check it withfile build/server, which should say ELF 64-bit LSB executable, x86-64. - Bind 0.0.0.0 on a fixed portListen on all interfaces and read the port from the environment with a default, for example
PORT=8080. Declare your WebSocket port as the first TCP port in the manifest, because the gateway forwards to it. Never bind to127.0.0.1only. - Add a health route and join probeReturn a short known body from
/healthand a game-level join check, so a join can be proven rather than assumed. - Declare exact originsList each website origin allowed to connect, with scheme and host. Requests from other origins are refused.
- Keep secrets out of the archiveRead tokens from environment variables. Archives with embedded credentials are rejected and the values are never repeated back to you.
- Connect from the page with wssUse the
wss://address from your connection configuration. Test in several real browsers after launch.
Gateway limits
| Limit | Current value |
|---|---|
| Browser WebSocket gateway: largest frame | 64 KiB |
| Browser WebSocket gateway: rate per connection | up to 120 messages and 2 MiB per second |
| WebRTC signaling: largest message | 16 KiB |
| WebRTC room size | 2 to 16 peers; rooms expire after two hours |
| Idle shutdown | after 10 continuous minutes with zero players (needs player-count reporting) |
| Region | us-east-1 only |
Honest gaps
- Not certified. Origin handling, protocol compatibility and a real browser join across browsers still need live evidence.
- Application bytes are metered, not the WebSocket and TLS overhead, so transfer figures are approximate.
- No DDoS or abuse guarantees beyond the per-connection limits above.
- Mobile Safari and background tabs can drop WebSockets; your client must reconnect.
- No anti-cheat. Authoritative server logic is yours.
Frequently asked questions
Do I need my own TLS certificate for a browser game server?
Not on NetCraftGames. Players connect to a wss address on the gateway, which terminates TLS and forwards frames to your server. Your server can speak plain WebSocket to the gateway. You still need to list the exact website origins allowed to connect, because the gateway checks the Origin header on every connection.
Which languages can I use for a browser WebSocket server?
Node.js 24 and Python 3.12 projects, or anything that produces a Linux x64 program, such as Go or Rust. NetCraftGames does not install dependencies or run package managers for you, so ncg pack prepares the packages for Linux on your computer first. The server must listen on 0.0.0.0, read secrets from the environment and answer a health check and join probe.
Does my WebSocket have to be at the root path?
No. Write the path your server answers at, for example /ws, as wsPath in your ncg.json. It is a fixed value that you choose, and the gateway never forwards a path or query from a player. A socket.io server works only when it is set to WebSocket transport and the path in the manifest includes its fixed query. Colyseus does not work, because it makes plain web requests first.
Sources
- MDN: WebSockets API, accessed October 3, 2026