AdGuard Browser Extension: one tree for MV2 and MV3, four stores
AdGuard browser extension
At a glance
- What is it?
- AdGuard's extension blocks ads and trackers from a popup switch and a visual Assistant, and the same TypeScript tree builds both manifest generations for four browser stores. The build side is where the cost sits: two environment values nobody publishes a default for, a Playwright image, and a version field that trails its own tags.
- Who is it for?
- AdGuard Browser Extension suits a user who wants ad and tracker blocking they can read, build and patch themselves, and suits you poorly if Safari or a phone is your only target. Install it, then read the permission list before you let it near a logged-in session, and send filter complaints through AdGuard's reporting tool rather than the extension tracker.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- AdguardTeam/AdguardBrowserExtension4,556 ★ · +122
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| AdguardTeam/AdguardBrowserExtension | 4.4k | 4.6k |
122 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Four stores carry it, and the popup switch works on first open
AdGuard's extension installs from four stores, one link per browser family:
https://agrd.io/extension_chrome
https://agrd.io/extension_firefox
https://agrd.io/extension_opera
https://agrd.io/extension_edgeChrome and Chromium based browsers take the first, Firefox the Mozilla Add-ons website, Opera its add-ons store, and Microsoft Edge the Microsoft Store. Nothing has to be switched on afterwards. Clicking the AdGuard icon in the toolbar opens a popup where blocking already runs against a recommended set of filter lists, and the main switch in that popup turns protection off for the site you are on rather than for the whole browser. That granularity is the part worth learning first, since a payment or ticketing page that renders badly with blocking on can be exempted without turning the blocker down everywhere. The gear icon opens the full options page, and the Assistant, chosen as "Block ads manually", lets you point at an element and block it without writing a rule. No Safari path appears anywhere in that list. The README's table of contents does link a browser compatibility section and a versioning schema section, so version floors and the numbering rules live outside the install text. The alternative for people who want filtering outside the browser is the vendor's standalone Windows and Mac application, which the README names as the counterpart to this extension; those builds sit on the paid half of the product, and the comparison page at https://adguard.com/compare.html is where the gap between the two is laid out.
Every manifest permission names the job it performs
AdGuard's permission list is written as an audit trail, because every entry states the work behind it. `tabs` exists to get the URL of the options page tab. `webRequest` applies cosmetic rules, detects and removes tracking cookies, and counts blocked resources. `cookies` deletes cookies from requests or changes their lifetime, `contextMenus` creates a context menu, and `storage` saves user settings, user rules and custom filters. `unlimitedStorage` is there for a plain reason: filter lists get large. `webNavigation` catches the moment for injecting scriptlets, and `privacy` reaches into the browser privacy settings.
One entry is not symmetric across stores. `privacy` is required in Firefox and optional in Chrome, Edge and Opera, so the same code asks a reviewer for a different set depending on where you install it. Read the rest of the list as a description of what the blocker does to a live session: it can observe every request a page makes, drop cookies at will and rewrite cookie lifetime on your behalf. For anyone deciding whether to install, that table is the honest description of the product, and it is longer than a typical blocker's because a filter engine needs somewhere to keep its lists.
MV2 blocks requests synchronously, MV3 delegates to declarativeNetRequest
One source tree carries two manifest generations, and the permission list is where the fork shows first. MV2 builds ask for `<all_urls>`, which grants access to all websites so content scripts and filtering rules can apply, and for `webRequestBlocking`, which is what lets the extension block or modify HTTP requests synchronously:
- `<all_urls>` - grants access to all websites to apply content scripts and filtering rules
- `webRequestBlocking` - required to block or modify HTTP requests synchronously
- `host_permissions` - grants access to all websites (MV3 uses this instead of `<all_urls>`)MV3 drops both of those. `host_permissions` replaces the all-site grant, blocking moves to `declarativeNetRequest` for blocking, redirecting and modifying URL requests, and `declarativeNetRequestFeedback` keeps a log of what was changed. Two permissions appear only in MV3: `scripting`, required to inject the Assistant script into pages, and `userScripts`, required so a user can subscribe to custom filter lists and evaluate rules from them. That last line is the one to notice, because on MV3, running a rule from a list you subscribed to yourself needs a permission the MV2 build never asked a store for.
The same seam runs through the test suite. The scripts `vitest run --project mv2` and `vitest run --project mv3` run the two halves separately, `tsconfig.mv2.json` and `tsconfig.mv3.json` compile them apart, and the CI script writes `unit-tests-mv2.xml` plus `unit-tests-mv3.xml` before `tools/merge-junit.ts` combines them into one `unit-tests.xml`. Browser level runs take different routes again, with `tools/browser-test/index.ts` for integration and `tools/browser-test/e2e/vitest-runner.ts` for end to end, each of which clears its own `tmp` directory first.
One bundler entry runs under three BUILD_ENV values
Every build path in package.json goes through `tools/bundle.ts`, with a BUILD_ENV value in front of it and, in some scripts, a target name after it:
"dev": "cross-env BUILD_ENV=dev tsx tools/bundle.ts",
"dev:watch": "cross-env BUILD_ENV=dev tsx watch tools/bundle.ts chrome",
"dev:watch:ff": "cross-env BUILD_ENV=dev tsx watch tools/bundle.ts firefox-amo",
"beta": "cross-env BUILD_ENV=beta tsx tools/bundle.ts",
"release": "cross-env BUILD_ENV=release tsx tools/bundle.ts",
"adguard-api": "cross-env BUILD_ENV=dev tsx tools/bundle.ts adguard-api"The `release` script differs from `beta` by the BUILD_ENV value alone, so the shipping build is a switch rather than a second pipeline. The trailing arguments carry more weight: `firefox-amo` matches the Mozilla Add-ons listing, `chrome` is the Chromium package, and `adguard-api` is a third named build target.
Output size is a tracked quantity here rather than an accident. `tools/bundle-size/check.ts` and `tools/bundle-size/update.ts` read and rewrite `.bundle-sizes.json` in the repository root, so a growth in package weight shows up as a diff a reviewer can see. Filter data moves through the same script family: `resources` runs `tools/resources.ts`, `resources:mv3` runs `tools/resources/update-dnr-rulesets.ts` and then `tools/resources-mv3.ts`, and `resources:mv3:extract-unsafe-rules` calls `dnr-rulesets exclude-unsafe-rules` over `./Extension/filters/chromium-mv3/declarative`, which is where the static rules for the newer manifest live.
A complete build needs two values the repository only names
`.env.example` names two required keys, both placeholders, plus two commented optional overrides:
# Artifactory domain is needed for blocking pages download
ARTIFACTORY_DOMAIN=<artifactory_domain>
# TokenGuard API key is needed for checking dangerous script rules
TOKENGUARD_API_KEY=<tokenguard_api_key>The first key is the host a build downloads blocking pages from, and those pages are what a user sees when content is blocked. The second is a TokenGuard API key for checking dangerous script rules; the optional overrides point at `https://tokenguard.int.agrd.dev/api/v1/` and a `deepseek-v4-flash` model. That sits in an awkward place beside the opening claim in the README that AdGuard does not collect any information about you: the call belongs to the build side of the line rather than to the installed extension, but it is still part of what a contributor needs before anything can be shipped from a local machine.
The boundary is worth keeping straight when judging the project. You can read the TypeScript, run `vitest run`, and inspect the filter data without either value, and nothing in the extension you install asks for them. Anyone who evaluates this extension for a locked-down build environment should treat those two variables as an unanswered question, not as a one line setup step.
The container builds tsurlfilter only when a context brings it
The Dockerfile starts from `mcr.microsoft.com/playwright:v1.53.2-noble`, installs git, curl and zip, and pins the package manager with a global `[email protected]`. It also sets `git config --global --add safe.directory '*'`, which is there to silence the dubious ownership error a bind mounted checkout produces, and points the store at `/pnpm-store` so the pnpm cache survives from one layer to the next.
The stage that follows, `firefox-preinstall`, downloads Firefox 153.0 for the Selenium end to end tests and checks it against a pinned SHA256, so source changes do not invalidate that layer.
One more detail sits above all of this: the line `# ENV NODE_VERSION=22.17.0` is commented out, so whatever Node the Playwright image carries is what runs your build. Contributors comparing two local builds should keep that in mind before blaming a dependency difference for a behaviour they did not change.
The version field trails the tags sitting on the same branch
The version string committed at the repository root reads `5.5.3+41.build.20261013011339`, and its numeric part stops at 5.5.3. The release tags carry a fourth number: v5.5.2.3 on 2026-08-26, v5.5.3.0-beta on 2026-09-23, and v5.5.3.3 on 2026-09-30; the last push to master was on 2026-10-30.
In plain terms, the number a contributor reads in package.json is not the number the project ships by, and anyone mapping a version onto a build has to work from the tag list instead of that field. The README links DEPLOYMENT.md and a Versioning Schema section from its table of contents.
The rest of the root says what kind of repository this is. A pnpm workspace sits at the top with `pnpm-lock.yaml` and `pnpm-workspace.yaml`, `Extension/` holds the shipped code and filter data, `tools/` holds the bundler, the locale and resource scripts and the browser test runners, and `tests/` holds the suite. Alongside them are `constants.ts`, `vitest.config.ts`, `vitest.setup.ts`, five tsconfig files, husky hooks with `.lintstagedrc.mjs`, a `.twosky.json` next to the locale script, plus `.github/` and `.vscode/` directories. `AGENTS.md` and `SECURITY.md` are there as well, so a contributor has a written disclosure path before touching anything.
Missed ads and false positives get filed in another repository
One note under the issue reporting instructions sends a whole class of bug elsewhere: filter related issues, with missed ads and false positives named as the examples, belong in AdGuard's reporting tool rather than in this repository. The division is structural instead of bureaucratic. The extension carries the engine and the interface, the lists are data, and a pattern that matches one thing too many is a different fix from a bug in the code that applies it.
The remaining contribution routes are narrower. Translation work goes to the vendor's translation program page instead of a pull request against message strings, testers pick up a beta build for any browser from a dedicated beta page, and everything else is collected on a general contribute page. Bug reports themselves are a plain New issue button on the issues page.
That split has a practical consequence for anyone triaging their own install. A site that shows an ad under blocking points at the filters, not at the extension, so checking the right tracker is the difference between a fix and a report that closes as out of scope.
Editorial conclusion
AdGuard Browser Extension suits a user who wants ad and tracker blocking they can read, build and patch themselves, and suits you poorly if Safari or a phone is your only target. Install it, then read the permission list before you let it near a logged-in session, and send filter complaints through AdGuard's reporting tool rather than the extension tracker. Contributors should confirm which Node the container runs before trusting a local build, since the version pin in the Dockerfile is commented out.
Frequently asked questions
Is AdGuard browser extension safe?
AdGuard states that it does not collect any information about you and does not participate in any acceptable ads program, and that its only income comes from selling premium versions of its software. The extension is GPL-3.0 and asks for broad access at the same time, including webRequest, cookies, privacy and all-site access, so installing it means giving the publisher request and cookie control over your session.
Is Chrome killing AdBlock?
AdGuard Browser Extension answers the manifest split with two builds: MV2 blocks or modifies HTTP requests synchronously through webRequestBlocking, while MV3 blocks, redirects and modifies them through declarativeNetRequest and needs userScripts so a user can subscribe to custom filter lists and evaluate their rules. Firefox treats the privacy permission as required, where Chrome, Edge and Opera treat it as optional.
Is there an extension for AdGuard on my browser?
Yes, in four places: the Chrome Web Store for Chrome and Chromium based browsers, the Mozilla Add-ons website for Firefox, the Opera add-ons store, and the Microsoft Store for Microsoft Edge. The install section gives one link for each of them and names no Safari package.
AdGuard browser extension vs app: which one should I use?
Unlike its standalone counterparts for Windows and Mac, the AdGuard browser extension is completely free and open source, and it blocks ads and trackers from inside the browser. The vendor keeps a comparison page at https://adguard.com/compare.html that sets the two side by side.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/adguardteam-adguardbrowserextension)Star history chart for your README
[](https://hysenlabs.com/projects/adguardteam-adguardbrowserextension)Was this useful?