Skip to main content
A tunnel moves bytes and interprets nothing along the way. When your service speaks a protocol of its own, take the connection directly and read and write it yourself.

Prerequisites

  • An API key from the console, exported as BOXLITE_API_KEY. See API keys.
  • pip install boxlite, and the REST URL exported as BOXLITE_REST_URL. See Quickstart.
  • A box you can start, and a service inside it that listens on a TCP port.
  • The box must be created with inbound enabled. A tunnel against a private box is refused, and inbound has defaulted to disabled since 0.10.5 — see Network policy.
Every example reads both values from the environment, so nothing hard-codes a credential.

Take the connection yourself

connect() hands you the byte stream directly. This is the level you work at for a protocol that is not HTTP — a line protocol, a binary framing, a database wire protocol — or when you want full control over what goes on the wire.
connect() spends the tunnel. So does forward(). Build a fresh await box.network.tunnel(port) for each connection you need; only uri() leaves a tunnel reusable.

Read until the far side closes

read(max_bytes) returns up to max_bytes bytes, and an empty bytes object once the far side has closed — that empty read is the end-of-stream signal the loop above breaks on. There is no separate EOF flag to check.
Not using asyncio? SyncBox.network and SyncBox.tunnel(port) return SyncNetworkHandle and SyncTunnelForwarder, the synchronous equivalents of everything on this page.

Next steps

Network

How tunnels work, the full parameter reference, and the outbound boundary.

Network policy

Control what the box itself is allowed to reach.