The short version
Annotated has no persistent content script or broad host permission. It does not sell personal data, build advertising profiles, or collect general browsing history.
- Passage/media metadata is read only after a toolbar, side-panel, or selection-menu gesture.
- Radar looks up public annotations only after you press Scan this source; it sends the current tab's public canonical URL without cookies and never passively scans browsing history.
- Pasting a source URL only opens that HTTP(S) destination; it does not read or capture the opened page.
- Drafts and recordings start in this Chrome profile. They are not end-to-end encrypted by Annotated. Opening Preview is not publication.
- A source-tab clip has a separate rights acknowledgment and Record click, a Chrome indicator, Stop/discard controls, and a 90-second ceiling.
- Agent API/MCP data is private and account-scoped. Browser capture still stops for fresh human actions; the separate direct-media mode uses an explicit delegated API-key-holder attestation with no browser confirmation.
- Google/X sign-in, publishing, and live social activity happen on this website, not inside the extension.
What the extension handles
Opening a pasted source
The visible Paste a source URL launcher accepts a bounded, credential-free HTTP(S) address and asks Chrome to open it in a tab. Annotated does not inject into, read, or save that destination as a draft merely because it was opened. Because the extension has no host permissions, you must then invoke its toolbar/side-panel capture or Annotate “…” selection-menu action on that tab before page data can be read. The address may still appear in Chrome's own history under your browser settings.
Passage and timing capture
After you invoke capture, Annotated may process the page and canonical URL, title, publisher, author, description, optional image URL, capture time, a live selected passage with nearby anchors, or a bounded media start/end time. Article extraction does not collect full-page HTML or cookies. A public article excerpt is capped at 100 words while the longer immutable selector can remain attached for integrity checks; the public excerpt must be a literal part of that capture. The first-run checkbox enables Capture, Sample, and Open source, but the acknowledgment is persisted only when you choose one of those actions. The selection-menu handler checks that stored acknowledgment before injection; before consent it stores no selection, URL, or other page data and opens the disclosure with a generic notice. The extension confirms that a passage came from a live browser selection; our server does not independently refetch or certify the publisher page. Annotated declares incognito: "not_allowed" and rejects capture or persistence in Incognito windows.
Annotation Radar
Radar is off until you press Scan this source. That action reads the active tab's public HTTP(S) URL, removes common tracking parameters, and sends the resulting canonical URL to the companion's public Radar endpoint with credentials omitted and no referrer. The response contains at most 50 public annotations and is displayed in the side panel. Radar does not read page text, cookies, private tabs, or general browsing history, and the extension adds no host permission for it. Before that canonicalization, Annotated rejects embedded credentials, local/private hosts, and query controls associated with access links or authentication callbacks—including keys, codes, state, OTP, tokens, signatures, and OAuth verifiers. A rejected control is not silently stripped into an apparently safe URL.
Moment Finder caption search
Moment Finder is off until you press Find, and it first verifies that the active tab is the captured source. On generic media, it reads a browser-exposed caption or subtitle track. On YouTube, if no such track is exposed, in-page code may read YouTube's player-provided caption metadata and download only that video's matching caption resource from YouTube. The search query is never included in that request. Caption text, the query, and results stay transient in Chrome: none is uploaded to Annotated or a transcription service, and Annotated stores no transcript. This adds no host permission.
Local storage protection
Draft fields in chrome.storage.local and voice/source-clip blobs in IndexedDB are local to this Chrome profile, but Annotated does not end-to-end encrypt them. They rely on Chrome, the operating system, and access to your browser profile for protection. Do not capture confidential, sensitive, or unnecessary personal information. Use discard or Clear local data when you no longer need a local copy.
Voice commentary
Microphone access starts only after you press its Record control. An approved voice note is kept as WebM Opus in extension IndexedDB, for at most two minutes and 4 MiB. Preview transfers a one-time copy; the extension copy remains while a retained draft or Library item references it so you can reopen Preview, until you discard or clear it.
Source-tab clips
For a captured video or podcast draft, you may separately confirm that you will respect rights and claims and press the source Record control. Chrome then records the visible contents and audio of only the invoked active tab for your selected interval. The clip is not necessarily limited to the page's video or audio element. Browser chrome and other tabs are not captured. Chrome shows its recording indicator; Annotated shows a countdown and Stop; recording auto-stops by 90 seconds. Source-tab video is downscaled to at most 426×240 (240p), 30 fps, and 16 MiB; podcast capture is audio-only. Preview transfers a one-time copy; the extension copy remains in IndexedDB while a retained draft or Library item references it, until you discard or clear it. It is optional while drafting or previewing and required before publishing a media annotation. A saved clip's sharing-rights attestation must be no more than 24 hours old at transfer and upload reservation; Confirm sharing rights again renews it without re-recording, and the hosted Publish step asks for a separate final confirmation.
Adjust range and Grab the last
When the active video or podcast exposes a seekable window, Annotated stores the playhead and that window during your explicit capture. Under Adjust range, a Grab the last 30-, 60-, or 90-second choice can select an already-seekable range immediately before that playhead. It does not run a background or rolling recorder, cannot recover moments outside the player's own seekable history, and does not record until you separately press Record source clip.
Preview and local staging
When you choose Review & share, Annotated first checks both the current and canonical source URLs as credential-free HTTP(S) public sources. Local/private hosts and sensitive access, signed-link, OAuth callback, or one-time-code query controls reject Preview rather than being stripped. For an accepted source, source metadata, written commentary, and opaque local draft/recording identifiers are placed in the new tab's URL fragment. Browsers do not include a fragment in the page's HTTP request. Voice and source-clip bytes are never put in the URL.
For each local recording, the extension creates a separate 256-bit capability bound to the exact origin https://annotated-source-clips.vercel.app, the draft, and that recording; a source-clip grant is also bound to the source, captured range, and rights attestation. It can be used once and expires after five minutes. The page connects to the runtime ID supplied for that preview, receives bounded ordered chunks, removes capability coordinates from the address, and stages the blob in this origin's IndexedDB. Preview media is cleared after publish/discard; records older than 24 hours are removed when Preview next runs cleanup. A same-tab draft resume used across OAuth expires and is consumed after ten minutes.
What the companion service handles
Account and contributions
If you choose Google or X, Better Auth and that provider process sign-in. Google requests only openid and email. Annotated stores the Google provider account ID and email, derives the initial display name from that email, and does not request or persist a Google provider image. X requests tweet.read and users.read, not email, and reads only your ID, name, and username—no provider image. Because Better Auth requires an account email field, the service derives a non-routable internal address under x.annotated.invalid from the returned X username and ID. It is an internal identifier, not a contact address. Provider-returned access, refresh, and ID tokens are used only transiently to complete the OAuth callback and are stripped before account persistence; the nullable token fields remain empty for these flows. Neon stores the resulting user/provider identifiers, editable profile, and Better Auth session/authentication information. These are personally identifiable and authentication records even though sign-in occurs on the website rather than in the extension.
We process published annotations, source attribution, public evidence threads and receipt relations, comments, follows, applause, blocks, private reports, claim/support intake, and account controls to operate the product and prevent abuse. Public annotations, profiles, comments, follows, applause, evidence relations, and thread titles/theses are intentionally displayed. Reports, blocks, claim contacts, private explanations, claim submission events, and support details stay private. A claimant's optional statement remains private after that person makes the exact wording eligible until the annotation creator separately publishes it; the creator can later withdraw it. Publication and withdrawal are retained in the private audit. Public copy says we have not verified the claimant's identity or relationship, and the public resolution record omits claim/reference IDs, workflow state, private-transition timing, name, email, relationship, private explanation, and evidence URL.
Agent API, MCP, and scoped keys
When an account owner creates an Agent API key, the raw secret is shown once. Neon stores a one-way digest, prefix, label, scopes, creation/last-use/revocation state, and any expiry selected by the owner. The key's client may act only within those scopes, so it should be treated like a password and revoked when no longer needed. A non-expiring or revoked key record has no separate automatic deletion deadline before account deletion.
Agent operations can store owner-scoped source URLs and titles, a supplied VTT/SRT transcript or cues and its fingerprint, natural-language search queries and hashes, bounded candidate snippets/ranges, jobs, clip intents, rights grants, browser handoffs, worker diagnostics, clips, and private artifact receipts in Neon and private R2. These are not public merely because an API or MCP tool created them. Browser offers keep the query, prepared snippet/range, capability, and result binding in memory; the extension persists only bounded non-secret source/job/expiry/lifecycle metadata. A result crosses back only after the separate browser Send action.
Authorized direct-media capture
authorized_remote is a separate website/API path that callers must use only for a directly fetchable media URL deliberately registered for that mode. Registration records the caller's declaration without fetching or classifying the URL. At job time the worker validates the public-network destination, redirects, MIME type, byte count, and duration; invalid locators fail without an artifact. A caller holding the account owner's clips:write key must explicitly make a delegated rights attestation for the exact clip intent. That is the final capture authorization for this path: no per-clip browser checkbox or Record action follows. The caller is asserting authority; Annotated does not independently verify legal rights. Generic page URLs should use browser, upload, or locator-only handling.
The private Railway worker receives only the exact authorized source/range and render limits—not the user's cookie, API key, transcript, query, browser capability, or R2 credential. It fetches under strict public-network, redirect, MIME, duration, and size controls; produces bounded media; and uses a one-attempt signed upload. The web service privately re-reads and verifies the bytes before sealing a receipt. The receipt identifies the capture method, recorded rights basis, and artifact fingerprint; it does not certify rights or truth.
Session, request, and abuse-prevention data
A Better Auth session row in Neon can contain the raw request IP address and raw browser user-agent string along with its token and expiry. Better Auth's database authentication rate limiter can store a key containing the normalized client IP and authentication route, plus a counter and timestamp. Annotated's separate product-mutation limiter stores SHA-256-derived opaque subject keys—including hashed IP-derived identifiers for unauthenticated requests—plus counters and timestamps. We use these records for sign-in security, abuse prevention, service availability, and troubleshooting, not advertising or product analytics.
Private media
Cloudflare R2 stores published voice and source media in the private annotated-media bucket. Public Access is disabled. The authenticated audio API validates a voice note and stores it server-side. Before source-clip browser staging or upload reservation, the source URL must repeat the same public-source validation used by Preview. An accepted clip uses a short-lived presigned PUT and is sent directly from this browser to a never-served raw key rather than through the Next.js request body. The service privately verifies the stored WebM bytes and promotes the accepted copy to a separate final key. Normal cleanup queues raw deletion, and an R2 lifecycle independently deletes any source-clips/raw/ orphan after one day. Playback first requires a public/unlisted annotation visibility check; for voice or source clips, the service then issues five-minute signed object access.
R2 browser CORS allows only this production origin, only GET, HEAD, and PUT, only the content-type and range request headers, and a one-hour preflight cache. CORS is not authorization: every browser-direct object operation still requires a valid short-lived signature; server verification and cleanup use private service credentials.
Processors
Vercel hosts the website/API and can process HTTP request/platform logs. Neon hosts relational, Better Auth, session, agent, and rate-limit records. Cloudflare hosts private R2 media and can process HTTP, object-access, and security logs. Railway runs the private pull-only media worker and can process service/runtime logs. Google or X participates only when you choose that provider. Infrastructure logs depend on the production account settings and may include request time, route/object key, network address, user agent, response status, and security/diagnostic metadata. The current product sends no product-analytics or third-party error-monitoring events and has no advertising or data-broker integration.
Chrome Web Store Limited Use
Our use and transfer of information received from Chrome APIs follows the Chrome Web Store User Data Policy, including its Limited Use requirements. We use that data only for the prominently disclosed capture, local recovery, preview, publish, delivery, security, and user-requested support/claim purposes. We do not use or transfer it for personalized advertising, unrelated profiling, or sale. Human access to non-public data is limited to user-requested support/claim review, security/abuse response, or legal obligations.
Retention, export, and deletion
- A still-referenced local draft/Library preview has no automatic expiry and is not end-to-end encrypted by Annotated. Discard or Clear local data removes extension drafts, preview history, voice notes, source clips, grants, and pending captures; the first-run acknowledgment remains saved as the control says.
- Unpublished companion-site media staging is cleared after publish/discard; records older than 24 hours are removed when Preview next runs cleanup. Unattached media upload records expire after 24 hours, and maintenance queues private objects for retryable deletion.
- Private agent sources and supplied transcripts default to seven days; searches/candidates to two hours; clip intents, capture grants, and unfinished clips to at most 30 minutes; and private receipts to 30 days. The recurring bounded cleanup scrubs expired queries/source metadata, deletes unreferenced rows, and queues unreferenced private objects for retryable deletion. A public/unlisted receipt or published annotation can retain its referenced provenance/artifact until that public record is removed. API keys follow their selected expiry or explicit revocation and account-deletion controls.
- Comment deletion replaces its body with a removal marker. Annotation deletion removes its public excerpt/commentary and comments and queues owned media for deletion. If an intake claim is attached, the original source attribution can remain privately with that claim for review; otherwise the stored source is redacted.
- Better Auth sessions carry an expiry, but the application defines no separate fixed post-expiry purge window for session/security rows. Provider account identifiers normally remain with the account until update or deletion. OAuth access, refresh, and ID tokens are transient during callback and stripped before account persistence; nullable token/expiry columns remain empty for these flows. Authentication and product rate-limit rows may be pruned opportunistically, but the current application provides no dedicated fixed purge guarantee.
- Account deletion cascades the Better Auth account/provider/session rows, profile, and ordinary product contributions; removes the profile link from retained private safety reports; anonymizes claims filed with the account email; clears companion-site session/storage; and queues owned R2 objects for deletion. Cloudflare deletion is retried if temporarily unavailable. It cannot erase separate extension data, already-created rate-limit rows, provider-side records, or Vercel/Cloudflare infrastructure logs.
- Account export is a private, no-store JSON download of the account/profile, owned annotations with source attribution, authored comments, follows, applause, blocks you created, reports you submitted, and claims matching the account email. It excludes OAuth/session secrets, media-upload rows, and binary R2 media.
Claim and support intake return private reference IDs. Annotation creators receive a private resolution inbox for claims attached to their own work, and an annotation may show a separate privacy-safe public action trail. Claim submission and statement-publication decisions remain in the private audit even when statement wording is later withdrawn from public display. This is not an automatic legal decision or a guarantee of outbound email or any particular outcome. The current implementation has no automatic expiry for claim/support or rate-limit records and defines no retention period for Vercel/Cloudflare logs. We restrict access and retain application records only as operationally or legally necessary; deployment operators must configure provider logs for the shortest practical window and honor provider-side deletion/retention controls.
Your choices
You can avoid the pasted-URL launcher, discard or clear local extension data, decline microphone/source recording, stop/discard a source clip, cancel Preview/sign-in, create only narrowly scoped Agent API keys, revoke those keys, edit your public profile, delete your comments/annotations, export account data, or delete the account. Provider-side account controls remain with Google or X.
Use the account deletion page for export/deletion controls. Chrome's extension settings also let you remove the extension and its browser storage.
Security
We use HTTPS, package-local extension code, exact-origin one-use media bridges, private R2, short-lived signed object operations, strict request validation, application-level ownership/visibility checks, and rate limits. PostgreSQL row-level security is not part of this implementation. No system is perfectly secure; report concerns promptly.
Children
Annotated is not directed to children under 13, and we do not knowingly collect their personal information.
Questions or requests
Use Support for privacy/data requests. Content owners and affected parties can use File a claim from the affected annotation for a private intake reference.