Stay Unseen
v1.0.5 · local only

Privacy for social browsing

Look first. Stay unseen.

Open a story, read a message, start typing a reply — Instagram, Facebook and Messenger normally report all three back to the other person. Stay Unseen stops those signals inside your browser, before they are sent. Six independent toggles, a counter for everything it blocked, and no server anywhere in the picture.

The Stay Unseen popup: header reading “Protecting Instagram, Facebook & Messenger”, four counters totalling 684 blocked signals, and six feature toggles all switched on.

// three signals

What actually gets stopped

Each of these is a separate request the site makes on your behalf. Each has its own toggle, and turning one off restores that site's normal behaviour immediately.

Story and reel views

The “seen” write that puts your name in the viewer list is cancelled. You still see the story; the ring still opens. Your name does not arrive.

Instagram Stories Facebook Stories

Message read receipts

Read your DMs without the other side's message flipping to “Seen”. The mark-as-read call never leaves. Optionally the unread dot stays in your own interface too, so you can find the thread again.

Instagram DMs Facebook Messages Messenger

Typing indicators

Draft, rewrite and delete a reply without the bubbling dots appearing on their screen. Sent through websocket frames as often as plain requests, so both paths are covered.

Instagram typing Messenger typing

// the whole interface

The popup, screen by screen

Real captures of the extension's own popup — its markup, its stylesheet, its script — at the exact 372 px width the browser gives it. Nothing is cropped: the taller states scroll inside the frame just as they do in the toolbar.

Stay Unseen — popup
Popup with all six features enabled: status line reads “Protecting Instagram, Facebook & Messenger”, counters read 684 blocked all time, 260 story views, 289 read receipts, 135 typing signals.
372 × 826 css pxeverything on

// default state

Everything on

The header states what is currently protected. Below it, four counters: the all-time total, then story views, read receipts and typing signals separately, so you can tell which kind of signal your own browsing actually produces.

The six feature rows are the whole control surface. Display holds the one preference that changes your interface rather than the network — keeping the unread dot on threads you opened while blocking was on.

684blocked all time
260story views
289read receipts
135typing signals

// mechanism

Two layers, because one is not enough

Some signals go out as ordinary POSTs that a network rule can cancel outright. Others are GraphQL calls and websocket frames indistinguishable by address from the traffic that makes the site work. So Stay Unseen works at both levels.

Layer 01

The network rules

A packaged ruleset cancels the specific POST and PUT requests that report a view, a read or typing activity. Chrome and Edge use declarativeNetRequest; Firefox uses blocking webRequest. Rules are restricted to instagram.com, facebook.com and messenger.com and ship inside the extension — nothing is fetched at runtime.

Layer 02

The page patch

At document_start, before the site's own code runs, Stay Unseen wraps fetch, XMLHttpRequest, WebSocket.send and the page's module registry. Outgoing bodies are matched in memory against a fixed pattern list; the ones that are seen, read or typing writes are dropped, and everything else passes through untouched.

Layer 03

Honest counting

Opening one story can trip half a dozen suppressions across both layers. The counter folds signals for the same feature arriving within 1500 ms into one block, so the number tracks things you did rather than internal retries. The Status drawer keeps the raw per-signal counts if you want them.

Three numbered steps — you open a story or DM, Stay Unseen drops the signal, nobody sees a thing — above a Recent blocks list with timestamped entries for Instagram Stories, Instagram DMs, Messenger typing and Facebook Messages, and a panel listing that nothing leaves your browser.
The path a seen signal takes, and the blocks it produces.
Overview: the headline “Look without being seen” beside the popup showing 847 signals blocked all time, split into 331 story views, 402 read receipts and 114 typing signals, with all six feature toggles on.
What it does, and what it has already stopped.
Controls: the six feature rows each with their own blocked count and switch, a Display section holding “Keep unread in the UI”, and notes explaining that off means off and counters are per feature.
Six independent switches, each counted separately.

// privacy

There is nowhere for your data to go

Stay Unseen has no server. Not an unused one, not a disabled one — there is no backend in the project. Everything it knows lives in your browser's local extension storage, and uninstalling it deletes all of it.

  • No account, email or sign-in. Install it and it works.
  • No analytics, telemetry or crash reporting. Nothing is counted anywhere but on your own machine.
  • No remote code. Every script and every blocking rule is inside the package you download.
  • No browsing history. It has permission for instagram.com, facebook.com and messenger.com and no access at all to any other site.
  • Your messages are never stored. Bodies are inspected in memory to make the block-or-allow decision, then forgotten.
  • Nothing is sold or shared, because nothing is collected.
What is kept on your device
StoredWhy
Six on/off settings, one per featureSo your toggles survive a restart
A blocked count per featurePowers the counters and the toolbar badge
The last 20 blocked requests — URL, feature, timestampPowers the diagnostics panel, so you can confirm it is working
The last 30 candidate requests and 20 websocket frames, message text removedLets the popup show which signals it detected, so one that stops being blocked can be diagnosed
Why it reads request bodies at all

On Instagram and Messenger, a read receipt and an ordinary message go to the same address. Telling them apart means looking at the body. Before anything is written to a diagnostics list, the fields holding text you typed are replaced with <user_text> — which is also what stops a message containing the word “typing” from being mistaken for a typing signal and dropped.


// limitations

What it cannot do

Worth reading before you install, so nothing here comes as a surprise later.

  • Sending still notifies. A message, reaction or story reply is a thing you chose to send — the recipient is told.
  • Online status is untouched. Stay Unseen does not hide your active or online indicator.
  • Activity from before you installed it cannot be withdrawn. Views already reported stay reported.
  • Meta changes its internals. When endpoint names or module names move, a feature can stop blocking until the patterns are updated — the diagnostics lists are there so you can tell when that has happened.
  • It is an independent project, not affiliated with, endorsed by, or connected to Meta Platforms, Instagram, Facebook, or Microsoft.

// install

Load it in about a minute

Version 1.0.5, published to each browser's own store and built against its own manifest. Pick yours, add it, and it starts working on the next page load.

  1. Open the listing for your browser above. Chrome's page also works in Brave, Vivaldi and Opera.
  2. Add it. Add to Chrome, Get on Edge, or Add to Firefox, then confirm the permission prompt — access to instagram.com, facebook.com and messenger.com, and nothing else.
  3. Pin the icon so the counters and toggles are one click away. Chrome and Edge hide new extensions behind the puzzle-piece button; Firefox uses the toolbar overflow menu.
  4. Reload any Instagram, Facebook or Messenger tab you already had open. The page patch installs at document start, so tabs opened before the install are not protected until they reload.
  5. Click the icon. All six features start switched on, and the header names what is currently protected.
  6. Check it is live: open the Status drawer. Network blocking should read active, and the patch rows fill in as you use each site.

Updates arrive through the store automatically. Prefer to load it unpacked, or want to read the code first? The per-browser source zips are still in Chrome, Edge and Firefox builds — unzip one, then use Load unpacked on chrome://extensions or edge://extensions with developer mode on, or Load Temporary Add-on on about:debugging#/runtime/this-firefox and pick the folder's manifest.json.