Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Integrated Browser ExtensionsNew to Visual Studio Code? Get it now.
Integrated Browser Extensions

Integrated Browser Extensions

Ryan Boylett

|
1 install
| (0) | Free
Userscripts, custom CSS and request blocking for the VS Code Integrated Browser, driven entirely through the public `browser` extension API and CDP.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info
Integrated Browser Extensions

Integrated Browser Extensions

Version

Userscripts, custom CSS and request blocking for the VS Code Integrated Browser. Tampermonkey, Stylus and a sliver of uBlock, minus the part where you leave VS Code, alt-tab to your browser, and resurface 40 minutes later wondering what you came in for.

What this is

VS Code's Integrated Browser renders pages in a real Chromium WebContentsView and exposes a Chrome DevTools Protocol session to extensions. This extension uses that to inject userscripts at document-start, give them a GM_* API, apply per-site CSS, and block or rewrite requests.

It is a content-script engine, not a Chrome extension host: there is no support for .crx / Web Store extensions, chrome.runtime / chrome.tabs, or background service workers.

Install

Open the Extensions view in VS Code (Ctrl/Cmd+Shift+X), search for Integrated Browser Extensions, and click Install - or get it from the Marketplace.

You can also install the .vsix directly:

code --install-extension integrated-browser-extensions.vsix

[!IMPORTANT] This extension uses the browser extension API. In VS Code builds where that API is not enabled, the panel and rule editing still work, but nothing is injected into pages. To enable it, launch with:

code --enable-proposed-api ryan.integrated-browser-extensions

The panel shows a banner when this is the case.

After installing, open the Browser Scripts view from the Activity Bar.

Quick start

  1. Open a page in the Integrated Browser.
  2. Open the Browser Scripts view in the Activity Bar.
  3. Click New Userscript (the + button) - a *.user.js file opens in the editor.
  4. Edit and save. The script is applied to matching tabs immediately; reload the page if it uses @run-at document-start.

To bring in an existing userscript, drop a *.user.js file into <globalStorage>/userscripts/ (or point integratedBrowserExtensions.extensionDirectory at a folder of them - see below).

Writing a userscript

New scripts start with a metadata block. Tampermonkey / Greasemonkey / Violentmonkey syntax is supported:

// ==UserScript==
// @name        Hide the cookie banner
// @namespace   me
// @version     1.0.0
// @description Remove the cookie consent overlay on example.com
// @match       https://*.example.com/*
// @exclude     https://example.com/checkout/*
// @run-at      document-start
// @grant       GM_addStyle
// @require     https://cdn.jsdelivr.net/npm/some-lib@1/dist/some-lib.min.js
// @resource    logo  https://example.com/logo.svg
// @connect     api.example.com
// ==/UserScript==

(function () {
	'use strict';

	GM_addStyle(`#cookie-overlay, .cmp-banner { display: none !important; }`);

	GM_xmlhttpRequest({
		method: 'GET',
		url: 'https://api.example.com/dismiss',
		onload: (res) => console.log('dismissed', res.status)
	});
})();

Metadata read: @name @namespace @version @description @author @homepage/@homepageURL @icon @match @include @exclude @grant @require @resource @connect @run-at (document-start / document-end / document-idle) @inject-into @noframes.

GM_* / GM.* provided: GM_info, GM_addStyle, GM_addElement, GM_getValue / GM_setValue / GM_deleteValue / GM_listValues, GM_getResourceText / GM_getResourceURL, GM_xmlhttpRequest / GM.xmlHttpRequest, GM_setClipboard, GM_notification, GM_openInTab, GM_download, GM_log, plus unsafeWindow. Promise-returning GM.* equivalents are also available. (GM_registerMenuCommand / GM_unregisterMenuCommand are accepted as no-ops so scripts that use them still load.)

GM_xmlhttpRequest runs in the extension host, so it bypasses page CORS. It is limited to hosts allowed by the script's @connect directives and the integratedBrowserExtensions.gmXhr.allowedHosts setting.

Using your existing scripts

Point integratedBrowserExtensions.extensionDirectory at directories or globs containing *.user.js files (the settings UI provides an Add Item button):

"integratedBrowserExtensions.extensionDirectory": [
  "${userHome}/Documents/userscripts",
  "/srv/shared/scripts/**/*.user.js"
]

These appear as read-only external scripts. You can enable and disable them; editing happens in their source files.

Live editing

Userscripts are plain files - edit and save them. On save, the watcher re-applies the script to matching tabs. By default the new version runs on the next navigation; enable integratedBrowserExtensions.reloadOnSave to reload tabs whose URL matches the changed script so it re-runs cleanly. CSS rules hot-swap in place without a reload regardless of this setting.

Custom CSS

CSS rules work like userscripts: each is a *.user.css file with a metadata header. Click + in the CSS Rules section to create one and it opens in the editor. The header uses the same @match / @include / @exclude matching as userscripts:

/* ==UserStyle==
@name        Quieter GitHub
@match       https://github.com/*
==/UserStyle== */

.js-notification-shelf, .flash-warn { display: none !important; }

Save the file and the CSS is injected at document-start on matching pages. Edits hot-swap into the page without a reload, and disabling or deleting a rule removes it from the page.

Network rules

In the Network Rules section, click + and expand the rule:

  • Action - Block, Redirect, or Modify headers
  • URL pattern - a * glob or /regex/, matched against the full request URL
  • Resource types (optional) - Document, Script, Image, XHR, Fetch, Stylesheet, Media, ...
  • Redirect to (redirect) - destination URL; $1, $2, ... apply when the pattern is a regex
  • Request / Response headers (modify headers) - one per line: Header: value to set, -Header to remove

Rules are enforced through the CDP Fetch domain on every browser tab.

Settings

Setting Default Description
integratedBrowserExtensions.enabled true Master switch for all injection
integratedBrowserExtensions.userscripts.enabled true Apply userscripts
integratedBrowserExtensions.styles.enabled true Apply custom CSS
integratedBrowserExtensions.network.enabled true Apply network rules
integratedBrowserExtensions.injectIntoSubframes true Inject into cross-origin iframes too
integratedBrowserExtensions.reloadOnSave false When a userscript changes, reload browser tabs whose URL matches it (CSS hot-swaps without a reload regardless)
integratedBrowserExtensions.extensionDirectory [] Extra directories / globs scanned for *.user.js files (supports * and **; ${userHome} / ~ are expanded)
integratedBrowserExtensions.gmXhr.allowedHosts ["*"] Host patterns GM_xmlhttpRequest may reach
integratedBrowserExtensions.debugMode false Emit console.info lines in the page when a userscript or CSS rule is injected, and log entries when a network rule is enabled on a tab or matches a request
integratedBrowserExtensions.debugCdp false Log every CDP message (verbose)

Commands

Command Description
Browser Scripts: New Userscript Create a userscript and open it for editing
Browser Scripts: Re-apply To All Browser Tabs Rebuild and re-inject into every open browser tab
Browser Scripts: Show Log Open the extension's output channel

Limitations

  • Not a Chromium extension host: no .crx / Web Store extensions, chrome.runtime / chrome.tabs, background service workers, or popup/options pages.
  • Userscripts run in the page's main world, so @inject-into content behaves like page and unsafeWindow === window.
  • GM_getValue / GM_setValue are synchronous against a snapshot taken when the script was injected; writes from another tab become visible after the next navigation or re-apply. Use the async GM.getValue / GM.setValue if you need cross-tab freshness.
  • In some VS Code builds the browser API is a proposed API - see the note under Install.

Support

If this is useful to you and you'd like to support its development, you can buy me a coffee on Ko-fi - always optional, always appreciated.

Support me on Ko-fi

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft