Privileged APIs

Table of Contents

Violentmonkey APIs are derived from those in Greasemonkey v3, and most of them work the same way, GM.* Greasemonkey v4-compatible aliases were added in VM2.12.0.


unsafeWindow is the actual window object of the page.

It is useful when @grant is declared with anything other than none.

  • If @grant none is declared, or no @grant is declared at all:

    Sandbox is disabled, meaning the script can add/modify globals directly without the need to use unsafeWindow.

    • window: the original window object
    • unsafeWindow: the original window object
  • If any API is declared with @grant:

    Sandbox is enabled, meaning the script is executed in an isolated context where window is a wrapper of the original window object. So you might need unsafeWindow if you want to modify a global variable.

    • window: a wrapper of the original window object, adding a new attribute to window does not work if it is expected to be accessed by a script in the original world
    • unsafeWindow: the original window object


GM_* are a group of special APIs provided by Violentmonkey.


An object that exposes information about the current userscript. It has following properties:

  • uuid: string

    A unique ID of the script.

  • scriptMetaStr: string

    The meta block of the script.

  • scriptWillUpdate: boolean

    Whether the script will be updated automatically.

  • scriptHandler: string

    The name of userscript manager, which should be the string Violentmonkey.

  • version: string

    Version of Violentmonkey.

  • isIncognito: boolean- since VM2.15.4

    True when this is an incognito profile (Chrome) or private mode (Firefox).

  • platform: object- since VM2.12.4

    Unlike navigator.userAgent, which can be overriden by other extensions/userscripts or by devtools in device-emulation mode, GM_info.platform is more reliable as the data is obtained in the background page of Violentmonkey using a specialized extension API (browser.runtime.getPlatformInfo and getBrowserInfo).

    • arch: string

      One of "arm", "mips", "mips64", "x86-32", "x86-64".

    • browserName: string

      "chrome", "firefox" or whatever was returned by the API.

    • browserVersion: string
    • os: string

      One of "android", "cros", "linux", "mac", "openbsd", "win".

  • script: object

    Contains structured fields from the Metadata Block:

    • description: string
    • excludes: string[]
    • includes: string[]
    • matches: string[]
    • name: string
    • namespace: string
    • resources: Array<{name, url}>
    • runAt: string
    • version: string
  • injectInto: string- since VM2.10.0

    The injection mode of current script. See @inject-into for more information.


Retrieves a value for current script from storage.

let value = GM_getValue(key, defaultValue)
  • key: string

    The name for value to load.

  • defaultValue: any

    The default value to return if no value exists in the storage.


Sets a key / value pair for current script to storage.

GM_setValue(key, value)
  • key: string

    The unique name for value within this script.

  • value: any

    The value to be stored, which must be JSON serializable (string, number, boolean, null, or an array/object consisting of these types) so for example you can't store DOM elements or objects with cyclic dependencies.


Deletes an existing key / value pair for current script from storage.

  • key: string

    The unique name for value within this script.


Returns an array of keys of all available values within this script.

let arrayOfKeys = GM_listValues()


Adds a change listener to the storage and returns the listener ID.

let listenerId = GM_addValueChangeListener(name, callback)
  • name: string

    The name of the observed variable

  • callback: (name, oldValue, newValue, remote) => void
    • name: string

      The name of the observed variable

    • oldValue: any

      The old value of the observed variable (undefined if it was created)

    • newValue: any

      The new value of the observed variable (undefined if it was deleted)

    • remote: boolean

      true if modified by the userscript instance of another tab or false for this script instance. Can be used by scripts of different browser tabs to communicate with each other.


Removes a change listener by its ID.

  • listenerId: string


Retrieves a text resource from the metadata block.

let text = GM_getResourceText(name)


Retrieves a blob: or data: URL of a resource from the metadata block.

let blobUrl = GM_getResourceURL(name);
let blobOrDataUrl = GM_getResourceURL(name, isBlobUrl);
  • name: string

    Name of a resource defined in the metadata block.

  • isBlobUrl: boolean = true- since VM2.13.1
    • true returns a blob: URL. It's short and cacheable, so it's good for reusing in multiple DOM elements.

    • false returns a data: URL. It's long so reusing it in DOM may be less performant due to the lack of caching, but it's particularly handy for direct synchronous decoding of the data on sites that forbid fetching blob: in their CSP.

Note: when setting this URL as src or href of a DOM element, it may fail on some sites with a particularly strict CSP that forbids blob: or data: URLs. Such sites are rare though. The workaround in Chrome is to use GM_addElement, whereas in Firefox you'll have to disable CSP either globally via about:config or by using an additional extension that modifies HTTP headers selectively.


Since VM2.13.1

Appends and returns an element with the specified attributes with the primary purpose of circumventing a strict Content-Security-Policy that forbids adding inline code or style.

let element1 = GM_addElement(tagName, attributes);
let element2 = GM_addElement(parentNode, tagName, attributes);
  • parentNode?: Node | Element | ShadowRoot

    The parent node to which the new node will be appended.

    It can be inside ShadowDOM: someElement.shadowRoot.

    When omitted, it'll be determined automatically:

    1. document.head (<head>) for script, link, style, meta tags.
    2. document.body (<body>) for other tags or when there's no <head>.
    3. document.documentElement (<html> or an XML root node) otherwise.
  • tagName: string

    A tag name like 'script'.

  • attributes?: object

    The keys are HTML attributes, not DOM properties, except textContent which sets DOM property textContent. The values are strings so if you want to assign a private function to onload you can do it after the element is created.


// using a private function in `onload`
let el = GM_addElement('script', { src: 'https://....' });
el.onload = () => console.log('loaded', el);
// same as GM_addStyle('a { color:red }')
let el = GM_addElement('style', { textContent: 'a { color:red }' });
// appending to an arbitrary node
let el = GM_addElement(parentElement.shadowRoot, 'iframe', { src: url });


  • The element is returned immediately (synchronously) even with GM.addElement, no need for .then(), but you can use it if you want, just once though as it's auto-removed to avoid recursion. The API is synchronous because Violentmonkey runs scripts only when the root element appears, so there's always a node to serve as a parent.
  • Invalid arguments will raise an exception, which can be caught using try {} catch (e) {}, just like standard DOM API document.createElement.


Appends and returns a <style> element with the specified CSS.

let styleElement = GM_addStyle(css);
  • css: string

    The CSS code to inject.

Older versions of Violentmonkey (prior to 2.12.0) returned an imitation of Promise, which is still maintained for compatibility, so don't be surprised if you see code like GM_addStyle(css).then(el => { /* whatever */ });


Opens URL in a new tab.

  1. using an object

    let tabControl = GM_openInTab(url, options)
    • url: string

      The URL to open in a new tab. URL relative to current page is also allowed.

      Note that Firefox disallows data:, blob:, chrome:, file:, and many about: URLs.

    • options?: object
      • active: boolean = true

        Make the new tab active (i.e. open in foreground).

      • container?: number- since VM2.12.5, Firefox-only

        Set tab's container in Firefox:

        • not specified = reuse script's tab container
        • 0 = default (main) container
        • 1, 2, etc. = internal container index
      • insert: boolean = true- since VM2.11.0

        Insert the new tab next to the current tab and set its "openerTab" so when it's closed the original tab will be focused automatically. When false or not specified, the usual browser behavior is to open the tab at the end of the tab list.

      • pinned: boolean = false- since VM2.12.5

        Pin the tab (i.e. show without a title at the beginning of the tab list).

  2. Using a boolean, compatible with Greasemonkey:

    let tabControl = GM_openInTab(url, openInBackground)
    • openInBackground: boolean

      Open the tab in background. Note, this is a reverse of the first usage method so for example true is the same as { active: false }.

Returns an object with following properties:

  • onclose?: () => void

    Сan be assigned to a function. If provided, it will be called when the opened tab is closed.

  • closed: boolean

    Whether the opened tab is closed.

  • close: () => void

    A function to explicitly close the opened tab.

let tabControl = GM_openInTab(url);
tabControl.onclose = () => console.log('tab is closed');


Registers a command in Violentmonkey popup menu.

GM_registerMenuCommand('Text', onClick)
const id2 = GM_registerMenuCommand('Text2', onClick, { title: 'Two' })
const id3 = GM_registerMenuCommand('Text3', onClick, { autoClose: false })

Returns the command's caption since VM2.12.5 or id since VM2.15.9.

  • caption: string

    This text will be shown in the popup menu.

  • onClick: (event) => void

    When the command is clicked in the menu, this function will run with the following parameter:

    • event: MouseEvent | KeyboardEvent- since VM2.13.1 is the event that activated the command so you can check event.button, event.shiftKey, event.key, and so on.
  • options?: object- since VM2.15.9
    • id?: string

      Default: caption text since VM2.16.2. Default in 2.15.9-2.16.1: a randomly generated string.

    • title?: string

      A hint shown in the status bar when hovering the command.

    • autoClose?: boolean = true

      Whether to auto-close the popup after the user invoked the command.

If you want to add a shortcut, please refer to keyboard shortcut.

Here's how you can change the command in-place, thus preserving its relative position in the list of multiple commands:

const id = 'status';
const inplace = id === GM_registerMenuCommand('Enabled', onClick, { id });
if (inplace) {
  // supported: change the command in-place using the same `id`
  GM_registerMenuCommand('Disabled', onClick, { id, title: 'Status' });
} else {
  // not supported: recreate the commands
  GM_registerMenuCommand('Disabled', onClick);
  GM_registerMenuCommand('Foo', onClick2);
  GM_registerMenuCommand('Bar', onClick3);


Unregisters a command which has been registered to Violentmonkey popup menu.

  • captionOrId: string

    The caption or id of the command to unregister. See GM_registerMenuCommand for more info.


Shows an HTML5 desktop notification.

  1. using an object:

    let control = GM_notification(options)
    • options: object
      • text: string

        Main text of the notification.

      • title?: string

        Title of the notification.

      • image?: string

        URL of an image to show in the notification.

      • silent?: boolean = false- since VM2.15.2, Chrome 70

        No sounds/vibrations when showing the notification. Only for Chromium-based browsers as of Aug 2023.

      • tag?: string- since VM2.15.4

        Unique name of the notification, e.g. 'abc', same as the web Notification API. Names are scoped to each userscript i.e. your tag won't clash with another script's tag.

        The purpose of a tagged notification is to replace an older notification with the same tag, even if it was shown in another tab (or before this tab was navigated elsewhere and your notification had zombieTimeout).

      • zombieTimeout?: number = 0- since VM2.15.4

        Number of milliseconds to keep the notification after the userscript "dies", i.e. when its tab or frame is reloaded/closed/navigated. If not specified or invalid, the default behavior is to immediately remove the notifications.

      • zombieUrl?: string- since VM2.16.1

        URL to open when a zombie notification is clicked, see zombieTimeout for more info.

      • onclick?: () => void

        Callback when the notification is clicked by user. As of VM2.15.2 it also forces the notification to be visible until clicked in Chrome which by default hides the notification after a few seconds.

      • ondone?: () => void

        Callback when the notification is closed, either by user or by system.

  2. Using separate parameters, compatible with Greasemonkey:

    GM_notification(text, title, image, onclick)
    • text: string

      Main text of the notification.

    • title?: string

      Title of the notification.

    • image?: string

      URL of an image to show in the notification.

    • onclick?: () => void

      Callback when the notification is clicked by user.

As of VM2.12.8 returns a control object with the following properties:

  • remove: () => Promise<void>

    A function to remove the notification.


Sets data to system clipboard.

GM_setClipboard(data, type)
  • data: string

    The data to be copied to system clipboard.

  • type: string = 'text/plain'

    The MIME type of data to copy.


Makes a request like XMLHttpRequest, with some special capabilities, not restricted by same-origin policy.

Note: h is lowercase (the historical spelling).

let control = GM_xmlhttpRequest(details)
  • details: object
    • url: string

      URL relative to current page is also allowed.

    • method?: string

      Usually GET.

    • user?: string

      User for authentication.

    • password?: string

      Password for authentication.

    • overrideMimeType?: string

      A MIME type to specify with the request.

    • headers?: object

      For example { 'name1': 'value1', 'name2': 'value2' }.

      Some special headers are also allowed:

      • 'Cookie'
      • 'Host'
      • 'Origin'
      • 'Referer'
      • 'User-Agent'
    • responseType?: string

      One of the following:

      • 'text' 👈 default
      • 'json'
      • 'blob'
      • 'arraybuffer'
      • 'document' (since VM2.12.0)
    • timeout?: number- since VM2.9.5

      Time to wait for the request, none by default.

    • data?: string | ArrayBuffer | Blob | DataView | FormData | ReadableStream | TypedArray | URLSearchParams

      Data to send with the request, usually for POST and PUT requests.

    • binary?: boolean- since VM2.12.2

      Send the data string as a blob. This is for compatibility with Tampermonkey/Greasemonkey, where only string type is allowed in data.

    • context?: any

      Can be an object and will be assigned to context of the response object.

    • anonymous?: boolean = false- since VM2.10.1

      When set to true, no cookie will be sent with the request and since VM2.12.5 the response cookies will be ignored.

      When absent, an inverted value of Greasemonkey4-compatible withCredentials is used. Note that Violentmonkey sends cookies by default, like Tampermonkey, but unlike Greasemonkey4 (same-origin url only).

    Event handlers:

    • onabort?: () => void
    • onerror?: () => void
    • onload?: () => void
    • onloadend?: () => void
    • onloadstart?: () => void- since VM2.12.5
    • onprogress?: () => void
    • onreadystatechange?: () => void
    • ontimeout?: () => void

    Each event handler is a function that accepts one argument responseObject


  • synchronous is not supported.

Returns a control object with the following properties:

  • abort: () => void

    A function to abort the request.

The response object is passed to each event handler with the following properties, most of which are identical to those provided by the standard XMLHttpRequest:

  • status: number
  • statusText: string
  • readyState: number
  • responseHeaders: string
  • response: string | Blob | ArrayBuffer | Document | object | null
  • responseText: string | undefined, only provided when available
  • responseXML: Document | null- since VM2.13.4, only provided when available
  • lengthComputable: boolean, only provided when available
  • loaded: number, only provided when available
  • total: number, only provided when available
  • finalUrl: string, the final URL after redirection
  • context: any, the same context object you specified in details


Since VM2.9.5

Downloads a URL to a local file.

  1. using an object:

    • options: object:

      • url: string

        The URL to download.

      • name: string

        The filename to save to. Folders/subpaths aren't supported yet.

      Most GM_xmlhttpRequest options are supported.

      • headers?: object
      • timeout?: number- since VM2.9.5
      • context?: any- since VM2.13.4
      • user?: string- since VM2.13.4
      • password?: string- since VM2.13.4
      • anonymous?: boolean = false- since VM2.13.4
      • onabort?: () => void- since VM2.13.4
      • onerror?: () => void
      • onload?: () => void
      • onloadend?: () => void- since VM2.13.4
      • onloadstart?: () => void- since VM2.13.4
      • onprogress?: () => void
      • onreadystatechange?: () => void- since VM2.13.4
      • ontimeout?: () => void

      The onload event handler is called after the data is downloaded from URL, before writing the file.

  2. using separate parameters:

    GM_download(url, name)
    • url: string

      The URL to download.

    • name: string

      The filename to save to. Folders/subpaths aren't supported yet.

Returns a control object with the following properties, same as GM_xmlhttpRequest:

  • abort: () => void

    A function to abort the request.


GM (since VM2.12.0) is a single variable with Greasemonkey4-compatible aliases, the async functions return a Promise that's resolved with the returned value.

Open Chat