Skip to content

Build multiplayer without a server.

Instantly add multiplayer to your app without buying a server. FREE 10 GB/month bandwidth.

CA5u83eeMKS5drqAdchhJQeUpt7x4DNaU7ZBnaMZjUpumpWhy crypto?
Paste into your coding agent

make a 2D top-down shooter using arrr.fun's test tier

No registration required. It runs on a test room that works for an hour.

One connect(). Read it your way.

Read the same stream as messages, fixed ticks or positional voice. send() takes JSON or a Uint8Array. Get your key from the console, or get a test room: no registration required.

javascript
import { connect } from 'arrr-network';

const room = await connect('support-42', {
  appId: 'my-app',
  apiKey: 'arrr_…',           // console → Apps
  user: { id: 'alice' },
  onMessage(data, seq) {      // same order on every client
    log.append(seq, data);
  }
});

room.send({ text: 'hello' });
javascript
import { connect } from 'arrr-network';

const room = await connect('duel-42', {
  appId: 'my-app',
  apiKey: 'arrr_…',           // console → Apps
  user: { id: 'alice' },
  onTick(frame, inputs) {     // one batch per tick, identical everywhere
    for (const input of inputs) world.apply(input.data);
    world.step();
  }
});

room.send({ move: { x: 1, y: 0 } });
javascript
import { connect } from 'arrr-network';

const room = await connect('lounge', {
  appId: 'my-app',
  apiKey: 'arrr_…',           // console → Apps
  user: { id: 'alice' },
  onVoice(from, seq, x, y, z, frame) {
    speakers.play(from, frame);   // one encoded frame from a nearby talker
  }
});

room.sendVoice(x, y, z, opusFrame);   // while talking
room.sendVoice(x, y, z);              // every 500 ms while quiet: position only
html
<script src="https://arrr.fun/sdk/arrr-network.iife.js"></script>
<script>
  (async () => {
    const room = await arrrNetwork.connect('support-42', {
      appId: 'my-app',
      apiKey: 'arrr_…',       // console → Apps
      user: { id: 'alice' },
      onMessage(data, seq) { log.append(seq, data); }
    });
    room.send({ text: 'hello' });
  })();
</script>

What you can build

Multiplayer games

Inputs batched into ticks. Snapshots for late joiners, desync detection built in.

Voice rooms

One upload per talker, a bounded download per listener, any room size.

Chat and feeds

An ordered log with join and leave events nobody can fake.

Collaborative tools

Same operations, same order, on every client. No merge step.

Live data

Anything with a WebSocket can publish. Every subscriber reads the same sequence.

Anything else

JSON, bytes or audio. What it means is yours.

The network orders. Your code decides.

Nodes only number and relay; payloads are opaque to them. Every room is mirrored across nodes, so the load is spread out and a room outlives the node it started on.

How a room works on the ARRR networkClients ask the cloud service which node hosts their room, then connect to that node over a WebSocket. Messages reach the room's authority node, which numbers them in arrival order and batches them into ticks. Each tick is broadcast to the authority's own clients and, over a peer link, to every replica node's clients, so every client receives the same messages in the same order.Cloud servicecloud.arrr.funthe directory: which nodehosts this room?Authority nodenumbers messages as they arrive,batches them into one tick,broadcasts the tickReplica nodemirrors the room, forwards itsclients' messages upstream,takes over if the authority diespeer linkClient Ayour app+ the SDKClient Byour app+ the SDKClient Cyour app+ the SDKwhich node?node + join tokenmessages upordered ticks downmessages upordered ticks down1234
One room, two nodes, three clients. Dashed: the one question a client asks before it sends.
  1. Find the room

    The client asks the cloud service which node hosts the room and gets a node and a join token. The service never sees a message.

  2. Send

    The client opens a WebSocket to that node and sends. Replicas forward to the room's authority node.

  3. One order

    The authority numbers messages as they arrive and batches each tick. Numbering happens in one place, so no two clients can disagree.

  4. Same tick everywhere

    The tick goes to every client on every node. Read it with onMessage or onTick; what it means is your code's business.

Voice skips the queue. Audio rides its own channel on the same socket, unordered, forwarded to the nearest listeners by position. Nothing waits for a tick.

Three ways aboard

Try it

One request gets you a test room for an hour, up to 10 players. No registration required. Or ask your coding agent to build on the test tier.

Build an app

Create an app in the console and pass its API key to connect(). The network hosts your rooms.

Provide a node

Coming soon. Run arrr-node on your own machine and host rooms for the network.