# Peer

> Peer object allows easily interacting with connected clients.

When a new client connects to the server, crossws creates a peer instance that allows getting information from clients and sending messages to them.

## Instance properties

### `peer.id`

Unique random identifier ([uuid v4](https://developer.mozilla.org/en-US/docs/Glossary/UUID)) for the peer.

### `peer.request?`

Access to the upgrade request info. You can use it to do authentication and access users headers and cookies.

<note>

This property is compatible with web [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) interface, However interface is emulated for Node.js and sometimes unavailable. Refer to the [compatibility table](#compatibility) for more info.

</note>

### `peer.remoteAddress?`

The IP address of the client.

<note>

Not all adapters provide this. Refer to the [compatibility table](#compatibility) for more info.

</note>

### `peer.websocket`

Direct access to the [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) instance.

<note>

WebSocket properties vary across runtimes. When accessing `peer.websocket`, a lightweight proxy increases stability. Refer to the [compatibility table](#compatibility) for more info.

</note>

### `peer.context`

The context is an object that contains arbitrary information about the request.

You can augment the `PeerContext` interface types to add your properties.

```ts
declare module "crossws" {
  interface PeerContext {
    customData?: string[];
  }
}
```

<note>

context data can be volatile in some runtimes.

</note>

### `peer.topics`

All topics, this peer has been subscribed to.

### `peer.namespace`

Peer's pubsub namespace.

## Instance methods

### `peer.send(message, { compress? })`

Send a message to the connected client.

### `peer.subscribe(channel)`

Join a broadcast channel.

<read-more to="/guide/pubsub">



</read-more>

### `peer.unsubscribe(channel)`

Leave a broadcast channel.

<read-more to="/guide/pubsub">



</read-more>

### `peer.publish(channel, message)`

Broadcast a message to the channel. The peer that the publish is called on itself is excluded from the broadcast.

<read-more to="/guide/pubsub">



</read-more>

### `peer.close(code?, number?)`

Gracefully closes the connection.

Here is a list of close codes:

- `1000` means "normal closure" (default)
- `1009` means a message was too big and was rejected
- `1011` means the server encountered an error
- `1012` means the server is restarting
- `1013` means the server is too busy or the client is rate-limited
- `4000` through `4999` are reserved for applications (you can use it!)

To close the connection abruptly, use `peer.terminate()`.

### `peer.terminate()`

Abruptly close the connection.

To gracefully close the connection, use `peer.close()`.

## Compatibility

<table>
<thead>
  <tr>
    <th>
      
    </th>
    
    <th>
      <a href="/adapters/bun">
        Bun
      </a>
    </th>
    
    <th>
      <a href="/adapters/cloudflare">
        Cloudflare
      </a>
    </th>
    
    <th>
      <a href="/adapters/cloudflare#durable-objects">
        Cloudflare (durable)
      </a>
    </th>
    
    <th>
      <a href="/adapters/deno">
        Deno
      </a>
    </th>
    
    <th>
      <a href="/adapters/node">
        Node (ws)
      </a>
    </th>
    
    <th>
      <a href="/adapters/node#uwebsockets">
        Node (μWebSockets)
      </a>
    </th>
    
    <th>
      <a href="adapters/sse">
        SSE
      </a>
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        send()
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        publish()
      </code>
      
       / <code>
        subscribe()
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-1" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-1">
          1
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-1" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-1-2">
          1
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-1" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-1-3">
          1
        </a>
      </sup>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-1" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-1-4">
          1
        </a>
      </sup>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        close()
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        terminate()
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-2" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-2">
          2
        </a>
      </sup>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-2" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-2-2">
          2
        </a>
      </sup>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        request
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-30" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-30">
          3
        </a>
      </sup>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-31" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-31">
          4
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-31" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-31-2">
          4
        </a>
      </sup>
    </td>
    
    <td>
      ✓
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        remoteAddress
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ⨉
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket.url
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket.extensions
      </code>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-4" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-4">
          5
        </a>
      </sup>
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-4" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-4-2">
          5
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-4" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-4-3">
          5
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-4" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-4-4">
          5
        </a>
      </sup>
    </td>
    
    <td>
      ⨉
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket.protocol
      </code>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-5" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-5">
          6
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-5" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-5-2">
          6
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-5" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-5-3">
          6
        </a>
      </sup>
    </td>
    
    <td>
      <sup>
        <a href="#user-content-fn-5" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-5-4">
          6
        </a>
      </sup>
      
       ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-5" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-5-5">
          6
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-5" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-5-6">
          6
        </a>
      </sup>
    </td>
    
    <td>
      ⨉
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket.readyState
      </code>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-6" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-6">
          7
        </a>
      </sup>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-6" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-6-2">
          7
        </a>
      </sup>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket.binaryType
      </code>
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-7" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-7">
          8
        </a>
      </sup>
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓ <sup>
        <a href="#user-content-fn-7" ariaDescribedBy="footnote-label" dataFootnoteRef="" id="user-content-fnref-7-2">
          8
        </a>
      </sup>
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ⨉
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        websocket.bufferedAmount
      </code>
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ⨉
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ✓
    </td>
    
    <td>
      ⨉
    </td>
  </tr>
</tbody>
</table>

<section className="footnotes" dataFootnotes="">

## Footnotes

1. pubsub is not natively handled by runtime. peers are internally tracked. [↩](#user-content-fnref-1) [↩<sup>

2

</sup>

](#user-content-fnref-1-2) [↩<sup>

3

</sup>

](#user-content-fnref-1-3) [↩<sup>

4

</sup>

](#user-content-fnref-1-4)
2. `close()` will be used for compatibility. [↩](#user-content-fnref-2) [↩<sup>

2

</sup>

](#user-content-fnref-2-2)
3. After durable object's hibernation, only `request.url` (and `peer.id`) remain available due to 2048 byte in-memory state limit. [↩](#user-content-fnref-30)
4. using a proxy for [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) compatible interface (`url`, `headers` only) wrapping Node.js requests. [↩](#user-content-fnref-31) [↩<sup>

2

</sup>

](#user-content-fnref-31-2)
5. [`websocket.extensions`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/extensions) is polyfilled using [`sec-websocket-extensions`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism#websocket-specific_headers) request header. [↩](#user-content-fnref-4) [↩<sup>

2

</sup>

](#user-content-fnref-4-2) [↩<sup>

3

</sup>

](#user-content-fnref-4-3) [↩<sup>

4

</sup>

](#user-content-fnref-4-4)
6. [`websocket.protocol`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/protocol) is polyfilled using [`sec-websocket-protocol`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism#websocket-specific_headers) request header. [↩](#user-content-fnref-5) [↩<sup>

2

</sup>

](#user-content-fnref-5-2) [↩<sup>

3

</sup>

](#user-content-fnref-5-3) [↩<sup>

4

</sup>

](#user-content-fnref-5-4) [↩<sup>

5

</sup>

](#user-content-fnref-5-5) [↩<sup>

6

</sup>

](#user-content-fnref-5-6)
7. [`websocket.readyState`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState) is polyfilled by tracking open/close events. [↩](#user-content-fnref-6) [↩<sup>

2

</sup>

](#user-content-fnref-6-2)
8. Some runtimes have non standard values including `"nodebuffer"` and `"uint8array"`. crossws auto converts them for [`message.data`](/guide/message#messagedata). [↩](#user-content-fnref-7) [↩<sup>

2

</sup>

](#user-content-fnref-7-2)

</section>
