Devices

Recognize the browser behind sign-ups and logins with coss/device.

Email addresses and IP addresses are cheap to change; browsers are less so. coss/device gives the browser behind an event an id, so COSS can tell when one browser signs up account after account, and spot automated browsers.

In the browser

Make a token when the user submits the form, and send it to your server with it:

await ("/sign-up", {
  : "POST",
  : { "content-type": "application/json" },
  : .({ ..., : () }),
});

collectDevice() is synchronous, tiny (it comes with the coss package, without its API client) and never throws.

On your server

Pass the token on with the event:

const {  } = await ..({
  : "signup",
  : { : . },
  ,
  : { : . },
});
// data?.signals.device: { valid: true, automation: false, timezone: "Europe/London", … }

Reasons and rules

Rules can test device.automation, device.timezone (IANA, like America/New_York), device.language, duplicate.device and velocity.device_1h / velocity.device_24h. A time zone far from the IP's country is a useful hint (device.timezone in a list, with ip.country).

What it collects

  • An id: 16 random bytes the browser keeps in localStorage (coss_device_id). No cookies. COSS stores only a keyed hash of it.
  • Coarse facts: time zone, languages, platform, screen size and touch support.
  • Automation markers: navigator.webdriver and headless browsers' user agents.

No canvas, WebGL, font or audio fingerprinting. That has a cost: a browser whose storage is cleared (or a private window) looks like a new one. Use device signals as one hint among others.

The token isn't signed: it comes from the browser, so whoever controls the browser can write anything into it. A forged token can hide automation or pose as a new browser; it can't take over another browser's history without its id.

Storing an id on the user's device may need their consent where ePrivacy rules apply, depending on your purpose. Until you have it, collectDevice({ storage: "memory" }) keeps the id for the page only (nothing is written).

Testing

Sandbox keys also accept test-device:<name> (an ordinary browser whose id is <name>: send the same name twice to get duplicate.device) and test-device-automated (Testing).