A Chrome extension that takes liking off the table on Instagram. It cancels the network requests Instagram sends when you like something, and hides the like buttons so the temptation isn't there in the first place.
It is a self-control tool, not a security product — see Limitations.
Two layers, because neither one is sufficient alone.
| Mechanism | What it covers | Can the page work around it? |
|---|---|---|
declarativeNetRequest |
The five REST endpoints Instagram posts likes to, plus the six GraphQL like mutations when the mutation name is in the URL | No — enforced by the browser's network stack |
MAIN-world fetch/XHR patch |
The same six GraphQL mutations when the name is in the POST body, which declarativeNetRequest cannot read |
In principle yes; see below |
content.css + DOM markers |
Hides like buttons, disables double-tap-to-like, keeps carousel arrows working | Cosmetic only |
Concretely, that covers likes on feed posts, reels, stories, comments, and reel reactions in DMs.
Everything the extension blocks is listed in two readable files —
public/rules/block-likes.json and the mutation
list at the top of
public/content/main-world.js. Nothing is hidden
in a bundle.
One inherited quirk: rule
5blocksdirect_v2/threads/broadcast/reel_share, which is sharing a reel in a DM rather than liking one. It has been in this extension since the beginning and is preserved as-is. Delete the rule if you want sharing back.
Worth being straight about:
- The MAIN-world patch is best-effort. It runs in the page's own JavaScript
world — that is the only place a request body can be inspected — so in
principle Instagram could re-patch
fetchor forge the settings event. ThedeclarativeNetRequestrules are the layer that genuinely cannot be worked around, which is why the URL blocking lives there. declarativeNetRequestcannot read request bodies. That limit is structural, not an oversight, and it is the entire reason the second layer exists.- Instagram's markup and endpoints rot. Class names are build-generated hashes that rotate on every deploy, and Meta renames its internal GraphQL mutations without notice. Nothing here depends on a class name, but selectors and endpoint names still go stale. When they do, the like button reappears — please open a selector rot issue.
- Your language may be missing. Instagram localizes the
aria-labelon the like button, so hiding it depends on a list of translations inpublic/content/selectors.js. If yours isn't there the button stays visible — the network blocking still holds, so likes are still blocked. Adding a language is a one-line change. - Instagram will show an error when you try to like something. That is by design: a blocked request fails exactly the way a dropped connection does, so Instagram's own error handling rolls the heart back.
There is no Chrome Web Store listing. Build it and load it unpacked:
git clone https://github.com/Bar-2020/ig-like-blocker.git
cd ig-like-blocker
npm ci
npm run buildThen, in Chrome:
- Open
chrome://extensions/. - Turn on Developer mode (top right).
- Click Load unpacked and select the
dist/folder.
Requires Chrome 111 or newer.
Click the toolbar icon. The badge reads off whenever blocking is paused.
| Setting | Effect |
|---|---|
| Block likes | Master switch. Off pauses everything, including the network rules. |
| Hide like buttons | Hides the heart on posts, reels and comments. |
| Disable double-tap to like | Stops a double-tap on the media from liking it, while leaving the carousel arrows clickable. |
Changes apply immediately to already-open Instagram tabs — no reload needed.
The extension makes no network requests of its own, contains no analytics, and
loads no remote code. Its only stored state is four values in
chrome.storage.sync — the settings above — which Chrome syncs to your own
Google account and nowhere else. It has permission for www.instagram.com only.
npm run watch # rebuild dist/ on change
npm test # unit tests for the network patch
npm run check # lint + format + test + build + verify — what CI runsnpm run dev is not useful here; a Vite dev server can't be loaded as an
extension. Build to dist/ and reload from chrome://extensions/.
See CONTRIBUTING.md for the layout, the verification procedure, and — most usefully — how to fix the selectors when Instagram changes them.