# Browser storage

> What the SDK keeps in your users' browsers, for your cookie or storage notice: each localStorage item with its purpose, lifetime and contents. No cookies, no user IDs.

Under EU and UK rules, a site tells its users what it stores on their devices. When your app runs Coworkkit, that includes what the SDK stores, and this page is the complete list: 11 items in your site’s own storage, so only pages on your site can read them — all in `localStorage` except one `sessionStorage` entry the SDK writes only when your app turns on `resume`. Whether an item needs consent is a call for you and your privacy adviser; these are the facts to make it with.

## In short

- **The SDK sets no cookies.** Everything it keeps is in `localStorage`, except one `sessionStorage` entry it writes only when your app turns on `resume` — so a full page load in the same tab can rejoin a live voice session. It uses no IndexedDB.
- **It stores no user or account ID.** Nothing below records who the user is or their account in your app. The one `sessionStorage` entry records the live voice session — the one it lets a reload rejoin — and only while that session is live in its own tab.
- **The microphone and speaker choice is a browser device ID.** It is stored as the browser’s per-site device ID: an opaque ID the browser issues for your site, which we don’t link to a person or an account.
- **Almost nothing expires on its own.** A stored item stays until the user clears your site’s data, or until the SDK removes it when the setting returns to its default; each row says which. The one exception is the `sessionStorage` entry: the browser drops it when the tab closes, and it lapses at most 30 minutes after the session started.
- **The LiveKit client stores nothing** unless your app changes LiveKit’s log level itself. See [below](#livekit).

## Items your users can have

The SDK writes these while your app runs. Each row says when, and when it goes away.

| Key | What it’s for | Contents | How long it stays | Storage |
| --- | --- | --- | --- | --- |
| `coworkkit:lang` | The language the user picked in the button's settings, so the next session starts in it. Written only when your coworker offers more than one language. | A language code, e.g. `de-DE`. | Until the user clears your site's data. The SDK deletes it if your coworker stops offering that language (checked when the next session starts). | `localStorage` |
| `coworkkit:look:<code>` | Your coworker's look (the button's appearance), kept so the next visit paints it straight away. Written only when your coworker has a saved look, or your app passes a look code. | The look's cosmetic settings as JSON, at most `face`, `dotShape` and `accentColor`, e.g. `{"face":"island","accentColor":"#7c3aed"}`. | Until the user clears your site's data; the SDK never deletes it. One item per look code, so a code you stop using leaves its item behind. | `localStorage` |
| `coworkkit:session-look` | Which look to paint on the next visit, before any session starts. Written when a session starts and your coworker has a saved look. | A look code, e.g. `amber-fox-7f`. It names your coworker's look and is the same for every visitor. | Until the user clears your site's data. The SDK deletes it when a session starts and your coworker has no saved look (the default look). | `localStorage` |
| `coworkkit:way-peek` | That the button has already shown this browser, once, where to switch between talking and typing: a short hint that slides out of the button a couple of seconds into a session. Written the first time that hint is shown, and only when the text option is on for your coworker. | Always `1`. It says nothing about the visitor: it is the same for everyone using your app. | Until the user clears your site's data; the SDK never deletes it. | `localStorage` |
| `coworkkit:session:v1` | The live voice session, so a full page load in the same tab rejoins the call instead of dropping it. Written only when your app turns on `resume`, once a session is live. | The live session as JSON — the join token and the address of the room it connects to, plus the look and language the session started with, e.g. `{"token":"…","serverUrl":"…"}`. | Per tab, and short-lived. The SDK deletes it when the session ends, when a resume fails, or once its token lapses; the browser also drops it when the tab closes. The token is valid at most 30 minutes. | `sessionStorage` |
| `coworkkit-fab-position` | Where the user dragged the button, so it stays there. Never written if you pin the button with `draggable={false}`. | The button's top-left corner in pixels from the top-left of the window, as JSON, e.g. `{"x":1180,"y":640}`. | Until the user clears your site's data. The SDK deletes it when the user double-clicks the button to send it back to its corner. | `localStorage` |
| `coworkkit-fab-minimized` | That the user minimised the button to the edge of the screen, so it stays minimised across reloads. | Always `1`. | Until the user clears your site's data. The SDK deletes it when the user restores the button. | `localStorage` |
| `coworkkit-audio-prefs` | The microphone and speaker the user chose in the button's settings, so the next session uses them. | The browser's per-site device IDs as JSON, e.g. `{"microphoneId":"<device ID>","speakerId":"<device ID>"}`; either field may be missing. | Until the user clears your site's data; the SDK never deletes it. If a saved device is gone, the SDK uses the default device instead. | `localStorage` |

## Developer-only items

These appear only when a developer shows Coworkkit’s dev tools or runs a development build: the [Watch panel](/docs/watch) and the [development banner](/docs/dev-mode). Users of a production build don’t get them unless you turn Watch on in production.

| Key | What it’s for | Contents | How long it stays | Storage |
| --- | --- | --- | --- | --- |
| `coworkkit-watch-rect` | Where the Watch panel sits and how big it is, after someone moves or resizes it. Watch shows only in a development build, or in production when you set `enableInProduction`. | The panel's position and size in pixels as JSON, e.g. `{"x":820,"y":16,"w":460,"h":640}`. | Until the user clears your site's data; the SDK never deletes it. Double-clicking the panel's title bar writes the default size back rather than deleting it. | `localStorage` |
| `coworkkit-twin-rect` | Where the Twin panel sits and how big it is. The Twin is Coworkkit's internal test panel; it isn't in the published `@coworkkit/react` package, so an app built from npm never writes this. | The panel's position and size in pixels as JSON, e.g. `{"x":16,"y":60,"w":360,"h":520}`. | Until the user clears your site's data; the SDK never deletes it. Double-clicking the panel's title bar writes the default size back rather than deleting it. | `localStorage` |
| `coworkkit-devbar-dismissed` | That the developer hid the development banner, so it stays collapsed across reloads. The banner exists only in development builds. | Always `1`. | Until the user clears your site's data. The SDK deletes it when the developer expands the banner again. | `localStorage` |

## The LiveKit client

The SDK runs the voice connection on the LiveKit client library (`livekit-client`), which installs with it. That library remembers a log level only when your app asks it to: calling its `setLogLevel` or `setLogExtension` saves the level in `localStorage` under `loglevel:livekit` (plus one `loglevel:` key per LiveKit logger), or in a session cookie where `localStorage` is unavailable. The SDK never calls either, so unless your own code does, the LiveKit client stores nothing.

## Removing it

Clearing your site’s data in the browser removes every item. Every key starts with `coworkkit`, so your own code can find and delete them too, for example behind a “forget this device” button.

Related: [Configuration](/docs/configuration) for the `draggable` prop, [Network requirements](/docs/network-requirements) for what the SDK connects to, and [Regions](/docs/regions) for where a voice session runs.
