Skip to main content
Every computer streams over one WebSocket URL on www.orgo.ai. Any websockify-compatible VNC client connects to it, so you need no Orgo package to embed one. The orgo-vnc React component is a convenience wrapper over the same URL.

The connection URL

Both endpoints need your API key, so call them from your server.

Two credentials, and which one goes in the browser

Your server holds the API key, reads the password with it, and returns only the password to your page.
The computer password is root on that computer. The same value opens /ws/terminal and POST /api/desktops/{instance_id}/proxy/bash, not only the screen. Anyone who can read it from your page can run commands on the computer.So fetch it per session from your own backend, and keep it out of your client bundle. In Next.js that means never a NEXT_PUBLIC_* variable: those are compiled into the JavaScript every visitor downloads. Point embeds at a disposable computer rather than one holding real work.
An sk_ key is rejected when it arrives from a browser. Passing one as ?token= closes the socket with 4001. Send the computer password instead.

Embed from any domain

There is no origin allowlist on this path and nothing to register with us. The per-computer password is the credential, and it is the only thing that decides whether a connection is allowed.

Embed with noVNC

Two files. First a server route that trades your API key for the two values the browser needs.
app/api/computer/route.ts
Gate that route with your own auth. Anyone who can call it can drive the computer.
Then the browser:
Browser
That last line reads noVNC internals, because noVNC’s own disconnect event does not carry the close code. It is what orgo-vnc does too.

A failed embed is a black screen

The proxy rejects a connection by accepting the WebSocket upgrade and then closing it. noVNC therefore sees an ordinary disconnect, raises nothing, and the canvas stays black. The close code is the only way to tell a bad password from a stopped computer. Anything outside 4000-4599 is a standard WebSocket code, not ours. 4003, 4007, 4008, 4500 and 4502 are worth retrying. The rest need an input changed first.
Every long-lived embed eventually hits 4008. After 30 minutes with no human input the proxy closes the connection. The timer measures keyboard, pointer and clipboard input from your page, not pixels, so a computer an agent is driving with nobody watching still counts as idle. Treat 4008 as a clean close and reconnect on the next user action.

The React component

Use 0.3.0 or later. 0.2.x took a hostname prop and connected to wss://{hostname}/websockify, from when every computer had its own host. That address no longer exists, so 0.2.x cannot connect to any current computer. Replace hostname with instanceId.
app/screen.tsx
onError is the reason to use the package: it decodes every close code above into a message. Handle it, or a rejected connection is invisible again.

Props

Imperative handle

The package also exports buildWsUrl(host, instanceId, password) to build the URL for you, and describeCloseCode(code) and closeCodeMessage(code) to render the table above yourself.

Next steps

Quickstart

Full SDK setup

API reference

Control computers programmatically