> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurdoverse.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Networking

> fetch, WebSocket, EventSource and XMLHttpRequest, and where they differ from a browser.

`fetch`, `XMLHttpRequest`, `WebSocket` and `EventSource` are globals. No import, no permission. They
follow the specs, so [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) is the reference.

<Note>
  URLs must be absolute. A relative URL like `"/api/status"` fails.
</Note>

```ts theme={null}
const res = await fetch("https://httpbin.org/json", { signal: AbortSignal.timeout(5000) });
if (res.ok) console.log(await res.json());
```

***

## Differences from a browser

* No CORS and no cookie jar. Any header (`User-Agent`, `Cookie`, `Origin`, …) goes out as you set it.
* `redirect: "manual"` returns the real 3xx response, so you can read `Location`.
* The system proxy is ignored.
* Certificates are always checked; there's no way to skip it.
* Network and certificate failures reject with a `TypeError` whose `cause.code` is `"ENETWORK"` or `"ECERT"`.
  A non-2xx status resolves normally, check `res.ok`.
* `XMLHttpRequest` can't be synchronous (`open(method, url, false)` throws), and `responseXML` is always `null`.

***

## WebSocket

```ts theme={null}
const ws = new WebSocket("wss://ws.postman-echo.com/raw");
ws.binaryType = "arraybuffer";
ws.onopen = () => ws.send("hello");
ws.onmessage = (e) => console.log(e.data);
ws.onclose = (e) => console.log("closed", e.code, e.wasClean);
```

***

## Example

Post the map to a server when it changes, with a timeout.

```ts theme={null}
import game from "@native/game";

const ENDPOINT = "https://example.com/api/map";
let lastMap: string | null = null;

async function report(map: string): Promise<void> {
    try {
        const res = await fetch(ENDPOINT, {
            method: "POST",
            headers: { "content-type": "application/json" },
            body: JSON.stringify({ map, player: script.name }),
            signal: AbortSignal.timeout(5000),
        });
        if (!res.ok) console.warn("server said", res.status);
    } catch (e) {
        console.warn("report failed:", (e as Error).message);
    }
}

on("tick", () => {
    const map = game.shortMapName;
    if (!map || map === lastMap) return;
    lastMap = map;
    void report(map);
});
```
