The support tool of the future.
Embed Esper in your web app and help lives one click away. Your team, human or AI, sees the user's screen of your app and the errors behind it. Nothing else, with their consent, masked by default, on servers you run.
See what they see. Fix it together.
A live view of the user's page, a pointer that shows them where to click, and control only if they hand it over. It feels like standing at their desk, without asking anyone to share a screen.
Share this page with Sara from Acme support?
She'll see this app and nothing else. Nothing is shared until you say yes, and you can stop at any time.
Help lives in your product
Add the SDK to your web app and wire it to your own help button. Your users never install anything, never read out a code, never join a meeting link.
A page, not a screen
Your team sees the user's view of your app and nothing else. Other tabs, other windows and the desktop behind the browser cannot appear, by construction.
The console comes to you
Console output, errors and failing requests appear live beside the page. Nobody has to ask a customer to open the developer tools.
Consent runs the session
Nothing is shared until the user accepts a prompt that names who is asking. A visible indicator stays on for the whole session, and one click ends it.
Rewind, by invitation
Users can include the last few minutes when they ask for help. Until they tick that box, it lives in their browser's memory and nowhere else.
Yours, end to end
The SDK connects to a relay you host, and every session is encrypted end to end. The relay forwards ciphertext it cannot read. There is no Esper cloud.
From stuck to helped in one click.
No installs, no meeting links, no codes read over the phone. The whole path runs inside your product, on your servers.
Run the relay
One binary on your server, next to the broker you may already run. No state, no database, and it cannot read a session.
Install the SDK
One npm package in your web app, pointed at your relay. Your support admins pair like any Esper device and get co-browsing scopes.
A user asks for help
They click your own help button. Nothing is captured yet: the request just appears for your team, with whatever context you attach.
They say yes
A prompt names the person asking to look. Decline, and nothing was ever shared. Accept, and a visible indicator switches on.
Your team helps
They see the user's page as it changes and the errors behind it, and point at what to click next. Taking control is a separate question the user answers on screen.
They share a page. Not their life.
Screen sharing hands over everything on a monitor. Co-browsing is scoped to your app by construction. The rest of the user's machine is not dimmed or cropped out, it is simply not there.
What your team sees
- Their live view of your app, as it changes
- Console output, errors and failing requests, live
- The last few minutes, only if they tick the box when asking
- Where your agent should look: pointing and highlights
- Fields you have chosen to unmask
- Context you attach: page, version, signed-in user
What it can never see
- Other tabs, other windows, the desktop behind the browser
- Masked fields, which never leave the user's page
- Passwords and payment fields, which cannot be unmasked
- Auth headers and cookies, redacted before anything leaves
- Sessions of anyone who never asked for help
- Anything before the user consents, or after they end it
Full context. Zero recording.
The logs, the errors, the failing requests, the moments before: everything a session-replay suite gives support, scoped to one session one user asked for. People who never ask for help never send a byte.
12:04:31 · payment form mounted
12:04:52 · POST /api/charge → 402
12:04:52 · Uncaught TypeError: card.expiry is undefined
at validateCard (billing.js:214)
12:05:08 · Authorization: [redacted]
Live devtools, agent side
Console output, uncaught errors with stacks, failing requests and performance appear beside the page while your team helps. Auth headers and cookies are redacted before anything leaves the browser; request bodies travel only for routes you allow.
Errors arrive with the request
Attach the page's recent errors to the help request itself, so your team triages before anyone joins. A crash that explains itself may never need a session at all.
The last few minutes, by choice
The SDK can keep a short rewind buffer in the user's browser memory, never anywhere else. When they ask for help, one checkbox includes it. Unticked, not a byte of it ever leaves the page.
Put an agent in the chair.
Co-browsing speaks MCP like the rest of Esper, so the support seat can hold a person, an AI, or an AI that knows when to hand over.
- First response in seconds, and a person one click away.
- It guides on the page. Walking a user through pasting an API key while the key stays masked. The machine helping never reads the secret.
- Any model, no blessed vendor. The same scoped grants a human admin holds.
Built for GDPR.
Session tooling is where privacy reviews stall: always-on recording, stored replays, a vendor in the data path. This one was designed so there is almost nothing to review.
Compliance is a property of your deployment, not a badge on a tool. Esper's part is leaving almost nothing to review.
A help button, not a project.
Point the SDK at your relay and wire it to your own UI. Where the button lives, what it says and when it shows is your product's call. Esper handles everything after the click.
npm install @esper/cobrowse
import { esper } from "@esper/cobrowse";esper.init({relay: "wss://support.acme.com",siteKey: "pk_live_…",});// your button, wherever it liveshelpButton.onclick = () => esper.requestHelp();
Plain TypeScript
No framework required. The site key is publishable and grants nothing on its own.
One-attribute masking
Hide anything with data-esper-mask. Inputs are masked before you do anything at all.
Verified identity
Greet users by name: your backend signs a short-lived token, and the claim is verified, never taken from client-side code.