privacy & capture
read this before deploying remediate to a context where end users will trigger captures.
screenshots, recordings, and
nearbyTextcapture whatever is visible on the page at the moment of capture. that includes passwords, account numbers, addresses, payment info, anything in the dom. test your masking in staging before turning it on in production. you are the data controller for everything remediate produces.
what gets captured, by mode
screenshots (photo)
a png rasterized from the dom of the selected region.
includes: text, layout, css backgrounds, same-origin images. excludes: cross-origin images, iframes, video frames, canvas with cors-tainted content (these render blank). no permission prompt.
screen recordings (video)
an actual video stream of the captured surface, via getDisplayMedia. the user picks the surface in a native prompt: full screen, a window, or a tab. the user can pick any surface, including ones outside your app. they may capture other apps, other tabs, or their entire desktop.
desktop only. mobile safari has no api for this. requires https.
unlike sentry session replay or posthog session recording, this is a real video, not a dom mutation log. there is no per-element masking inside the video stream.
voice notes
raw audio from the user's default microphone, via getUserMedia. triggers a native mic permission prompt the first time. requires https. ambient sounds, other voices, anything within mic range will be captured.
annotations and nearbyText
clicking a dom element captures a css selector, dom path, bounding rect, classes, attributes, a subset of computed styles, and nearbyText, the visible text content within roughly 200px of the element.
nearbyText is the part to watch. if a user pins an element next to an order summary, the order total goes into the payload. if they pin a button next to "logged in as alex@example.com", the email goes into the payload.
text notes
whatever the user types. nothing else.
environment
every submission carries userAgent, language, timezone, viewport, screen size, and color scheme. sent on every submission.
metadata
only what you pass to the metadata prop. nothing implicit.
masking
remediate honors a single attribute everywhere it walks the dom:
<div data-remediate-mask>
<p>account number: 4111-1111-1111-1111</p>
</div>elements marked with data-remediate-mask:
- are blacked out in screenshots before the bitmap is rendered
- are excluded from
nearbyTextwalks during annotation capture - have their attributes redacted in
ElementCapture
this does not affect screen recordings. masking a real video stream is unreliable, so the only safe answer is "don't enable video on screens with sensitive data."
mask aggressively:
- account numbers, payment info, ssns, government ids
- email addresses and phone numbers in headers/profiles
- internal ids that map back to a user
- chat messages and email content
- anything you would not email to support
defaults
remediate captures everything visible by default. it is not private-by-default.
this is intentional. the user has clicked "report a bug." they are consciously sending you what they see. but you remain responsible for what they are allowed to see. mask before you ship.
server-side handling
since you own the storage, you also own the disclosure. a defensible baseline:
- encrypt at rest. payload json and blobs both. submissions contain pii by default.
- set a retention window. 30, 60, 90 days, then delete. don't keep feedback forever.
- scope access. not every engineer should be able to read every submission.
- log who reads what. audit trail on the viewing side.
- handle deletion requests. users can ask you to delete their feedback under gdpr or ccpa. since you own the storage, deletion is a query. make sure you can find every blob and every row by
metadata.userIdor whatever you key on. - don't forward raw payloads to third-party llms without the user's knowledge. summarize server-side first, or get explicit consent.
- rate-limit the endpoint. nothing in the widget prevents a malicious client from posting forever.
- validate. parse with zod or your validator of choice. don't trust the shape blindly even if it came from
parseFeedback.
telling your users
remediate doesn't show a notice automatically. you should. somewhere visible the first time a user opens the widget, or in your privacy policy:
"when you submit feedback, we capture a screenshot of the page, any recording or voice note you make, and basic info about your browser. captured data is sent to our servers and used only to investigate and fix the issue you reported. we don't share it with third parties. you can request deletion at [contact link]."
adapt the copy. the goal is informed consent, not legalese.
the law
remediate is a client-side capture library. we don't host, store, or see your data. you do. that means you are the data controller for any data captured. you are responsible for compliance with gdpr, ccpa, hipaa, pci-dss, and any other regimes your users fall under.
this page is not legal advice. if you are capturing in a regulated context, talk to a lawyer.
what is not captured
- network requests
- console logs
- cookies, localStorage, sessionStorage
- canvas pixel data (annotations don't extract canvas contents)
- contents of cross-origin iframes
- contents of cross-origin images
- anything that was not on screen when the user clicked capture
if you want any of these, you will do it yourself. metadata is the place.